diff --git a/Mobile-Expensify b/Mobile-Expensify
index 42ad9da8bfde..fdf508981aff 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 42ad9da8bfde582b57b2e66dc30e22757e06deea
+Subproject commit fdf508981aff5189c5c17c67493a3d1c4535c1a6
diff --git a/android/app/build.gradle b/android/app/build.gradle
index c7a7c6045cb9..a5b9d35d6bf0 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -111,8 +111,8 @@ android {
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         multiDexEnabled rootProject.ext.multiDexEnabled
-        versionCode 1009040500
-        versionName "9.4.5-0"
+        versionCode 1009040600
+        versionName "9.4.6-0"
         // Supported language variants must be declared here to avoid from being removed during the compilation.
         // This also helps us to not include unnecessary language variants in the APK.
         resConfigs "en", "es"
diff --git a/assets/images/receipt-search.svg b/assets/images/receipt-search.svg
new file mode 100644
index 000000000000..bbf36cf9b1df
--- /dev/null
+++ b/assets/images/receipt-search.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M3 1.82c0-.36.44-.54.69-.28l.77.81c.16.17.42.17.58 0l1.17-1.23c.16-.17.42-.17.58 0l1.17 1.23c.16.17.42.17.58 0l1.17-1.23c.16-.17.42-.17.58 0l1.17 1.23c.16.17.42.17.58 0l1.17-1.23c.16-.17.42-.17.58 0l1.17 1.23c.16.17.42.17.58 0l.77-.81c.25-.26.69-.08.69.28v5.24c0 .38-.52.57-.8.32a6.05 6.05 0 0 0-4.03-1.54c-3.38 0-6.12 2.79-6.12 6.24 0 2.08.74 3.12 1.47 4.16.2.28.4.56.58.86.09.15.07.34-.05.47l-1.26 1.32c-.16.17-.42.17-.58 0l-1.17-1.23a.394.394 0 0 0-.58 0l-.77.81a.4.4 0 0 1-.69-.28z"/><path fill-rule="evenodd" d="M12.08 16.16c.76 0 1.48-.21 2.09-.58l3.12 3.12 1.41-1.41-3.12-3.12c.37-.61.58-1.33.58-2.09 0-2.25-1.83-4.08-4.08-4.08S8 9.83 8 12.08s1.83 4.08 4.08 4.08m0-2c1.15 0 2.08-.93 2.08-2.08S13.23 10 12.08 10 10 10.93 10 12.08s.93 2.08 2.08 2.08"/></svg>
\ No newline at end of file
diff --git a/config/eslint/eslint.config.mjs b/config/eslint/eslint.config.mjs
index f41e62edc95c..86e05b589d15 100644
--- a/config/eslint/eslint.config.mjs
+++ b/config/eslint/eslint.config.mjs
@@ -157,11 +157,6 @@ const restrictedImportPaths = [
 ];
 
 const restrictedImportPatterns = [
-    {
-        group: ['**/TransitionTracker', './TransitionTracker', '../TransitionTracker'],
-        message:
-            "TransitionTracker is an internal primitive. Please use higher-level APIs (Navigation with 'afterTransition'/'waitForTransition', KeyboardUtils, useConfirmModal). See contributingGuides/INTERACTION_MANAGER.md.",
-    },
     {
         group: ['**/assets/animations/**/*.json'],
         message: "Do not import animations directly. Please use the '@components/LottieAnimations' import instead.",
@@ -188,6 +183,26 @@ const restrictedReportNameImportPatterns = [
     },
 ];
 
+// `isPaidGroupPolicy` is BILLING/paid-only (Collect/Control). Existing usages are grandfathered via
+// eslint-seatbelt; this only flags NEW imports so they make a conscious choice: for workspace feature
+// gating (violations, report fields, workspace chat, report creation, expense-workspace usability) use
+// `isGroupPolicy` / `isReportInGroupPolicy` instead, otherwise free group plans like Submit (submit2026)
+// are wrongly excluded and access bugs return.
+const restrictedPaidGroupPolicyImportPatterns = [
+    {
+        group: ['**/PolicyUtils', '**/libs/PolicyUtils'],
+        importNames: ['isPaidGroupPolicy'],
+        message:
+            'isPaidGroupPolicy is billing/paid-only (Collect/Control). For workspace feature gating use isGroupPolicy so free group plans like Submit are not excluded. If this is genuinely a billing/paid-only check, keep it and disable this line with a reason.',
+    },
+    {
+        group: ['**/ReportUtils', '**/libs/ReportUtils'],
+        importNames: ['isPaidGroupPolicy', 'isPaidGroupPolicyExpenseReport'],
+        message:
+            'isPaidGroupPolicy / isPaidGroupPolicyExpenseReport are billing/paid-only. For feature gating use isReportInGroupPolicy / isGroupPolicyExpenseReport so Submit workspaces are not excluded. If this is genuinely billing/paid-only, keep it and disable this line with a reason.',
+    },
+];
+
 const config = defineConfig([
     expensifyConfig,
     typescriptEslint.configs.recommendedTypeChecked,
@@ -255,8 +270,6 @@ const config = defineConfig([
 
         files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'],
         rules: {
-            '@lwc/lwc/no-async-await': 'off',
-
             // TypeScript specific rules
             '@typescript-eslint/prefer-enum-initializers': 'error',
             '@typescript-eslint/no-var-requires': 'off',
@@ -336,7 +349,6 @@ const config = defineConfig([
             'es/no-optional-chaining': 'off',
             '@typescript-eslint/no-deprecated': ['error', {allow: ['translateFn']}],
             'arrow-body-style': 'off',
-            'no-continue': 'off',
             'no-empty': ['error', {allowEmptyCatch: true}],
 
             // Import specific rules
@@ -715,7 +727,7 @@ const config = defineConfig([
                 'error',
                 {
                     paths: restrictedImportPaths,
-                    patterns: [...restrictedImportPatterns, ...restrictedReportNameImportPatterns],
+                    patterns: [...restrictedImportPatterns, ...restrictedReportNameImportPatterns, ...restrictedPaidGroupPolicyImportPatterns],
                 },
             ],
         },
diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 57557c64e0ce..7efae31cde1c 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -68,7 +68,7 @@
 "../../src/Expensify.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/GlobalModals.tsx"	"no-restricted-syntax"	2
 "../../src/ONYXKEYS.ts"	"no-restricted-syntax"	2
-"../../src/ROUTES.ts"	"@typescript-eslint/no-deprecated/getUrlWithBackToParam"	132
+"../../src/ROUTES.ts"	"@typescript-eslint/no-deprecated/getUrlWithBackToParam"	139
 "../../src/ROUTES.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/TIMEZONES.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/AccountingConnectionConfirmationModal.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
@@ -109,6 +109,7 @@
 "../../src/components/AvatarSelector.tsx"	"no-restricted-syntax"	2
 "../../src/components/AvatarWithImagePicker.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/AvatarWithImagePicker.tsx"	"react-hooks/set-state-in-effect"	2
+"../../src/components/BookTravelButton.tsx"	"no-restricted-imports"	1
 "../../src/components/Button/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/Button/validateSubmitShortcut/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/ButtonComposed/Button.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -249,7 +250,7 @@
 "../../src/components/MapView/MapViewImpl.web.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MapView/MapViewImpl.web.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/components/MapView/ToggleDistanceUnitButton/index.android.tsx"	"no-restricted-syntax"	1
-"../../src/components/MenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/components/MenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/components/Modal/BaseModal.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/components/Modal/Global/ConfirmModalWrapper.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/components/Modal/Global/ModalContext.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -276,10 +277,9 @@
 "../../src/components/MoneyRequestConfirmationListFooter/sections/DistanceMapSection.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MoneyRequestConfirmationListFooter/sections/ReceiptSection.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"no-restricted-imports"	1
 "../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"react-hooks/refs"	3
 "../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"react-hooks/set-state-in-effect"	3
-"../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MultiGestureCanvas/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -296,8 +296,8 @@
 "../../src/components/MultifactorAuthentication/config/scenarios/ChangePIN.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MultifactorAuthentication/config/scenarios/DefaultUserInterface.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Navigation/NavigationTabBar/SearchTabButton.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/components/Navigation/NavigationTabBar/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/components/Navigation/QuickCreationActionsBar/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/components/Navigation/QuickCreationActionsBar/index.tsx"	"no-restricted-imports"	1
 "../../src/components/Navigation/TopLevelNavigationTabBar/index.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/components/NavigationDeferredMount.tsx"	"no-restricted-imports"	1
 "../../src/components/NumberWithSymbolForm.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -377,6 +377,8 @@
 "../../src/components/Search/SearchList/ListItem/ChatListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/components/Search/SearchList/ListItem/GroupHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/components/Search/SearchList/ListItem/MemberListItemHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/components/Search/SearchList/ListItem/TaskListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -408,7 +410,6 @@
 "../../src/components/Search/hooks/useOptimisticSearchTracking.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/components/Search/hooks/useStableOptimisticSortedData.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Search/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	14
-"../../src/components/Search/index.tsx"	"no-restricted-imports"	1
 "../../src/components/Search/index.tsx"	"react-hooks/preserve-manual-memoization"	2
 "../../src/components/Search/index.tsx"	"react-hooks/refs"	5
 "../../src/components/Search/index.tsx"	"react-hooks/set-state-in-effect"	1
@@ -423,6 +424,7 @@
 "../../src/components/SelectionList/utils/getListboxRole/index.web.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/SettlementButton/AnimatedSettlementButton.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/SettlementButton/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	11
+"../../src/components/SettlementButton/index.tsx"	"no-restricted-imports"	1
 "../../src/components/SidePanel/SidePanelOverlay.tsx"	"no-restricted-syntax"	1
 "../../src/components/SidePanel/SidePanelReport/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/SignInButtons/IconButton.tsx"	"no-restricted-syntax"	1
@@ -446,11 +448,10 @@
 "../../src/components/Table/TableContext.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/components/Table/TableFilterButtons/buildFilterItems.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/Table/middlewares/filtering.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
-"../../src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TagPicker/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TaxPicker.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TestDrive/Modal/AdminTestDriveModal.tsx"	"no-restricted-imports"	1
-"../../src/components/TestDrive/Modal/EmployeeTestDriveModal.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/components/TestDrive/TestDriveDemo.tsx"	"no-restricted-imports"	1
 "../../src/components/TextInput/BaseTextInput/implementation/index.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TextInput/BaseTextInput/implementation/index.native.tsx"	"react-hooks/refs"	2
@@ -503,6 +504,7 @@
 "../../src/hooks/useAdvancedSearchFilters.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useAnimatedHighlightStyle/index.ts"	"react-hooks/set-state-in-effect"	2
 "../../src/hooks/useAssignCard.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/hooks/useAutoCreateTrackWorkspace.ts"	"no-restricted-imports"	1
 "../../src/hooks/useAutoFocusInput.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/hooks/useAutoUpdateTimezone.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useAutocompleteSuggestions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -514,7 +516,9 @@
 "../../src/hooks/useCachedImageSource.ts"	"react-hooks/set-state-in-effect"	1
 "../../src/hooks/useCancellationType.ts"	"react-hooks/refs"	2
 "../../src/hooks/useCancellationType.ts"	"react-hooks/set-state-in-effect"	1
+"../../src/hooks/useCardFeedsForActivePolicies.ts"	"no-restricted-imports"	1
 "../../src/hooks/useCardFeedsForDisplay.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/hooks/useCardFeedsForDisplay.ts"	"no-restricted-imports"	1
 "../../src/hooks/useCreateReport.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useDebounce.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useDebounceNonReactive.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -526,18 +530,18 @@
 "../../src/hooks/useDomainGroupFilter.ts"	"react-hooks/set-state-in-effect"	1
 "../../src/hooks/useDragAndDrop/types.ts"	"@typescript-eslint/no-deprecated/React.MutableRefObject"	1
 "../../src/hooks/useDynamicBackPath.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/hooks/useExpenseActions.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	3
+"../../src/hooks/useExpenseActions.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/hooks/useExportActions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useExportedToFilterOptions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useFilesValidation.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/hooks/useFilterFormValues.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/hooks/useGeographicalStateAndCountryFromRoute.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
-"../../src/hooks/useHRSyncResultsModal.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useHtmlPaste/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/hooks/useImportSpreadsheetConfirmModal.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useInitial.ts"	"react-hooks/refs"	4
 "../../src/hooks/useIsBlockedToAddFeed.ts"	"react-hooks/set-state-in-effect"	1
 "../../src/hooks/useIsOwnWorkspaceChatRef.ts"	"react-hooks/refs"	2
+"../../src/hooks/useIsPaidPolicyAdmin.ts"	"no-restricted-imports"	1
 "../../src/hooks/useKeyboardShortcut.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useLazyAsset.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/hooks/useLazyAsset.ts"	"react-hooks/refs"	2
@@ -647,6 +651,7 @@
 "../../src/libs/Middleware/Pagination.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/libs/Middleware/SaveResponseInOnyx.ts"	"no-restricted-syntax"	1
 "../../src/libs/ModifiedExpenseMessage.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
+"../../src/libs/MoneyRequestReportUtils.ts"	"no-restricted-imports"	1
 "../../src/libs/Navigation/AppNavigator/AuthScreens.tsx"	"no-restricted-syntax"	1
 "../../src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx"	"no-restricted-syntax"	6
 "../../src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx"	"react-hooks/refs"	1
@@ -657,6 +662,7 @@
 "../../src/libs/Navigation/AppNavigator/KeyboardShortcutsHandler/ShortcutsOverviewHandler.tsx"	"no-restricted-syntax"	1
 "../../src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/libs/Navigation/AppNavigator/Navigators/Overlay/BaseOverlay.tsx"	"no-restricted-syntax"	2
+"../../src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx"	"no-restricted-imports"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx"	"no-restricted-syntax"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx"	"no-restricted-imports"	1
@@ -665,9 +671,8 @@
 "../../src/libs/Navigation/AppNavigator/Navigators/SettingsSplitNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/TabNavigator.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/TestToolsModalNavigator.tsx"	"no-restricted-syntax"	1
-"../../src/libs/Navigation/AppNavigator/Navigators/WorkspaceNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
-"../../src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts"	"@typescript-eslint/no-unsafe-type-assertion"	17
+"../../src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts"	"@typescript-eslint/no-unsafe-type-assertion"	15
 "../../src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/restoreTabNavigatorRoutes.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -688,7 +693,6 @@
 "../../src/libs/Navigation/guards/OnboardingGuard.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/Navigation/helpers/createNormalizedConfigs.ts"	"@typescript-eslint/no-deprecated/escape"	1
 "../../src/libs/Navigation/helpers/createNormalizedConfigs.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/libs/Navigation/helpers/dismissModalAndOpenReportInInboxTab.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/Navigation/helpers/dynamicRoutesUtils/getDynamicRouteAdaptedState.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/helpers/dynamicRoutesUtils/getDynamicRouteQueryParams.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -725,6 +729,7 @@
 "../../src/libs/NextStepUtils.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	2
 "../../src/libs/Notification/LocalNotification/BrowserNotifications.ts"	"@typescript-eslint/no-deprecated/translateLocal"	1
 "../../src/libs/Notification/LocalNotification/BrowserNotifications.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/libs/Notification/LocalNotification/BrowserNotifications.ts"	"no-restricted-imports"	1
 "../../src/libs/Notification/LocalNotification/BrowserNotifications.ts"	"no-restricted-syntax"	2
 "../../src/libs/Notification/PushNotification/parsePushNotificationPayload.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/libs/Notification/PushNotification/shouldShowPushNotification.ts"	"no-restricted-syntax"	2
@@ -758,10 +763,11 @@
 "../../src/libs/ReportActionItemEventHandler/index.android.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/ReportActionsUtils.ts"	"@typescript-eslint/no-deprecated/reportAction.sequenceNumber"	1
 "../../src/libs/ReportActionsUtils.ts"	"@typescript-eslint/no-deprecated/reportAction?.originalMessage"	2
-"../../src/libs/ReportActionsUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	110
+"../../src/libs/ReportActionsUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	111
 "../../src/libs/ReportActionsUtils.ts"	"rulesdir/no-onyx-connect"	3
 "../../src/libs/ReportNameUtils.ts"	"@typescript-eslint/no-deprecated/translateLocal"	12
 "../../src/libs/ReportNameUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/ReportPrimaryActionUtils.ts"	"no-restricted-imports"	1
 "../../src/libs/ReportTitleUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/ReportUtils.ts"	"@typescript-eslint/no-deprecated/getPolicy"	28
 "../../src/libs/ReportUtils.ts"	"@typescript-eslint/no-deprecated/translateLocal"	34
@@ -770,6 +776,7 @@
 "../../src/libs/SearchAutocompleteUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/libs/SearchQueryUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	73
 "../../src/libs/SearchUIUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	69
+"../../src/libs/SearchUIUtils.ts"	"no-restricted-imports"	1
 "../../src/libs/SelectionScraper/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/libs/SidebarUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Sound/index.native.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -782,6 +789,7 @@
 "../../src/libs/TransactionPreviewUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/TransactionUtils/index.ts"	"@typescript-eslint/no-deprecated/translateLocal"	5
 "../../src/libs/TransactionUtils/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
+"../../src/libs/UnreadIndicatorUpdater/index.ts"	"no-restricted-imports"	1
 "../../src/libs/UnreadIndicatorUpdater/index.ts"	"no-restricted-syntax"	1
 "../../src/libs/Url.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/libs/UserAvatarUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
@@ -800,6 +808,7 @@
 "../../src/libs/actions/Chronos.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/ClearReportActionErrors.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/actions/CompanyCards.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/libs/actions/CompanyCards.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/CompanyCards.ts"	"no-restricted-syntax"	5
 "../../src/libs/actions/Delegate.ts"	"no-restricted-syntax"	4
 "../../src/libs/actions/Domain.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
@@ -823,6 +832,7 @@
 "../../src/libs/actions/IOU/MoneyRequestBuilder.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/actions/IOU/PayMoneyRequest.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	3
 "../../src/libs/actions/IOU/PayMoneyRequest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/actions/IOU/PayMoneyRequest.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/IOU/PayMoneyRequest.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/IOU/PerDiem.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	1
 "../../src/libs/actions/IOU/PerDiem.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
@@ -834,6 +844,7 @@
 "../../src/libs/actions/IOU/RejectMoneyRequest.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/IOU/ReportWorkflow.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	7
 "../../src/libs/actions/IOU/ReportWorkflow.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/libs/actions/IOU/ReportWorkflow.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/IOU/ReportWorkflow.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/IOU/SearchUpdate.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/actions/IOU/SendInvoice.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -864,13 +875,13 @@
 "../../src/libs/actions/ImportTransactions.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/InputFocus/index.web.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/InputFocus/index.web.ts"	"no-restricted-syntax"	1
-"../../src/libs/actions/Link.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/actions/Link.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/libs/actions/Link.ts"	"no-restricted-syntax"	3
 "../../src/libs/actions/MapboxToken.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/MergeAccounts.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/MergeTransaction.ts"	"@typescript-eslint/no-deprecated/getPolicyTagsData"	1
 "../../src/libs/actions/MergeTransaction.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/actions/MergeTransaction.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/MergeTransaction.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/OdometerTransactionUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/actions/Onboarding.ts"	"no-restricted-syntax"	1
@@ -889,6 +900,7 @@
 "../../src/libs/actions/Policy/Category.ts"	"no-restricted-syntax"	5
 "../../src/libs/actions/Policy/DistanceRate.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/Policy/Member.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/actions/Policy/Member.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Policy/Member.ts"	"no-restricted-syntax"	8
 "../../src/libs/actions/Policy/Member.ts"	"rulesdir/no-onyx-connect"	1
 "../../src/libs/actions/Policy/PerDiem.ts"	"no-restricted-syntax"	1
@@ -896,11 +908,14 @@
 "../../src/libs/actions/Policy/Policy.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	1
 "../../src/libs/actions/Policy/Policy.ts"	"@typescript-eslint/no-deprecated/translateLocal"	1
 "../../src/libs/actions/Policy/Policy.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
+"../../src/libs/actions/Policy/Policy.ts"	"no-restricted-imports"	2
 "../../src/libs/actions/Policy/Policy.ts"	"no-restricted-syntax"	10
 "../../src/libs/actions/Policy/Policy.ts"	"rulesdir/no-onyx-connect"	2
+"../../src/libs/actions/Policy/ReportField.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Policy/ReportField.ts"	"no-restricted-syntax"	4
 "../../src/libs/actions/Policy/Rules.ts"	"no-restricted-syntax"	3
 "../../src/libs/actions/Policy/Tag.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/actions/Policy/Tag.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Policy/Tag.ts"	"no-restricted-syntax"	4
 "../../src/libs/actions/Policy/Travel.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/PolicyConnections.ts"	"no-restricted-syntax"	1
@@ -908,7 +923,6 @@
 "../../src/libs/actions/ReimbursementAccount/resetNonUSDBankAccount.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/ReimbursementAccount/resetUSDBankAccount.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/Report/MarkAllMessageAsRead.tsx"	"no-restricted-syntax"	1
-"../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	3
 "../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-deprecated/reportAction.originalMessage"	1
 "../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
@@ -921,7 +935,6 @@
 "../../src/libs/actions/Search.ts"	"@typescript-eslint/no-unsafe-type-assertion"	19
 "../../src/libs/actions/Search.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/Session/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
-"../../src/libs/actions/Session/index.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Session/index.ts"	"no-restricted-syntax"	9
 "../../src/libs/actions/Session/index.ts"	"rulesdir/no-onyx-connect"	2
 "../../src/libs/actions/SplitExpenses.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -931,6 +944,7 @@
 "../../src/libs/actions/Subscription.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/Tab.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/actions/Task.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../src/libs/actions/Task.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Task.ts"	"no-restricted-syntax"	7
 "../../src/libs/actions/TaxRate.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/TeachersUnite.ts"	"no-restricted-syntax"	1
@@ -943,6 +957,7 @@
 "../../src/libs/actions/TravelInvoicing.ts"	"no-restricted-syntax"	3
 "../../src/libs/actions/UnreportedExpenses.tsx"	"no-restricted-syntax"	1
 "../../src/libs/actions/User.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
+"../../src/libs/actions/User.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/User.ts"	"no-restricted-syntax"	8
 "../../src/libs/actions/VacationDelegate.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/Wallet.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -960,8 +975,10 @@
 "../../src/libs/actions/connections/QuickbooksOnline.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/connections/SageIntacct.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/connections/Xero.ts"	"no-restricted-syntax"	2
+"../../src/libs/actions/connections/index.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/connections/index.ts"	"no-restricted-syntax"	3
 "../../src/libs/actions/getCompanyCardBankConnection/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/libs/actions/getCompanyCardBankConnection/index.tsx"	"no-restricted-imports"	1
 "../../src/libs/actions/getCompanyCardBankConnection/index.tsx"	"no-restricted-syntax"	2
 "../../src/libs/actions/replaceOptimisticReportWithActualReport.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/actions/replaceOptimisticReportWithActualReport.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1032,10 +1049,14 @@
 "../../src/pages/MissingPersonalDetails/subPages/Address.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/pages/MissingPersonalDetails/subPages/Address.tsx"	"react-hooks/refs"	4
 "../../src/pages/MultifactorAuthentication/RevokePage.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
+"../../src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx"	"no-restricted-imports"	1
 "../../src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx"	"no-restricted-imports"	1
 "../../src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx"	"react-hooks/preserve-manual-memoization"	2
 "../../src/pages/OnboardingPrivateDomain/BaseOnboardingPrivateDomain.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/OnboardingWorkspaceConfirmation/BaseOnboardingWorkspaceConfirmation.tsx"	"no-restricted-imports"	1
 "../../src/pages/OnboardingWorkspaceCurrency/BaseOnboardingWorkspaceCurrency.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/OnboardingWorkspaceOptional/BaseOnboardingWorkspaceOptional.tsx"	"no-restricted-imports"	1
 "../../src/pages/ProfilePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/ReimbursementAccount/AddressFormFields.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/ReimbursementAccount/EnterSignerInfo/index.tsx"	"@typescript-eslint/no-deprecated/useSubStep"	1
@@ -1069,6 +1090,7 @@
 "../../src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/BankAccountValidationForm.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlowPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/pages/ReimbursementAccount/utils/getSubStepValues.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/pages/ReportDescriptionPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/ReportDescriptionPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/ReportParticipantDetailsPage.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/pages/ReportParticipantDetailsPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1095,6 +1117,7 @@
 "../../src/pages/ShareCodePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/TeachersUnite/SaveTheWorldPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/TransactionDuplicate/Confirmation.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/TransactionDuplicate/Confirmation.tsx"	"no-restricted-imports"	1
 "../../src/pages/TransactionDuplicate/Confirmation.tsx"	"react-hooks/refs"	12
 "../../src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/TransactionMerge/ConfirmationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1102,6 +1125,7 @@
 "../../src/pages/TransactionMerge/MergeTransactionItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/TransactionMerge/MergeTransactionsListContent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/Travel/DynamicTravelTerms.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/Travel/DynamicTravelUpgrade.tsx"	"no-restricted-imports"	1
 "../../src/pages/Travel/TravelUpgrade.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/Travel/WorkspaceConfirmationForTravelPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/UnreportedExpenseListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1110,9 +1134,11 @@
 "../../src/pages/domain/Saml/SamlLoginSectionContent.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/pages/home/ForYouSection/EmptyState.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/home/GettingStartedSection/hooks/useGettingStartedItems.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/home/GettingStartedSection/hooks/useGettingStartedItems.ts"	"no-restricted-imports"	1
 "../../src/pages/home/SpendOverTimeSection/useSpendOverTimeData.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/home/TimeSensitiveSection/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/home/TimeSensitiveSection/items/FixCompanyCardConnection.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/home/YourSpendSection/useYourSpendData.ts"	"no-restricted-imports"	1
 "../../src/pages/inbox/DeleteTransactionNavigateBackHandler.tsx"	"no-restricted-imports"	1
 "../../src/pages/inbox/ReactionListWrapper.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/inbox/ReportFetchHandler.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	2
@@ -1149,7 +1175,6 @@
 "../../src/pages/inbox/report/ReportActionItemMessageEdit.tsx"	"react-hooks/refs"	5
 "../../src/pages/inbox/report/ReportActionItemMessageEdit.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/inbox/report/ReportActionsList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/pages/inbox/report/ReportActionsList.tsx"	"no-restricted-imports"	1
 "../../src/pages/inbox/report/ReportActionsList.tsx"	"react-hooks/refs"	2
 "../../src/pages/inbox/report/TripSummary.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/inbox/report/UserTypingEventListener.tsx"	"no-restricted-imports"	1
@@ -1166,24 +1191,23 @@
 "../../src/pages/inbox/sidebar/FABPopoverContent/menuItems/InvoiceMenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/inbox/sidebar/FABPopoverContent/menuItems/NewWorkspaceMenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../src/pages/inbox/sidebar/FABPopoverContent/menuItems/TravelMenuItem.tsx"	"no-restricted-imports"	1
 "../../src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/inbox/sidebar/SidebarLinksData.tsx"	"react-hooks/refs"	1
-"../../src/pages/inbox/usePusherDraftPacing.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/MoneyRequestAmountForm.tsx"	"react-hooks/set-state-in-effect"	3
 "../../src/pages/iou/SplitExpensePage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/iou/SplitExpensePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/SplitExpensePage.tsx"	"react-hooks/set-state-in-effect"	3
 "../../src/pages/iou/SplitList/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/request/MoneyRequestAttendeeSelector.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/iou/request/MoneyRequestAttendeeSelector.tsx"	"no-restricted-imports"	1
 "../../src/pages/iou/request/ParticipantSearchResults.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/pages/iou/request/step/DistanceManualTabContent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/pages/iou/request/step/DynamicIOURequestStepCategoryPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
-"../../src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
-"../../src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/request/step/IOURequestEditReport.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/iou/request/step/IOURequestEditReportCommon.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/pages/iou/request/step/IOURequestEditReportCommon.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/iou/request/step/IOURequestStepAmount.tsx"	"react-hooks/set-state-in-effect"	1
+"../../src/pages/iou/request/step/IOURequestStepCategory.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/iou/request/step/IOURequestStepConfirmation.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/pages/iou/request/step/IOURequestStepConfirmation.tsx"	"react-hooks/preserve-manual-memoization"	1
 "../../src/pages/iou/request/step/IOURequestStepDestination.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
@@ -1209,6 +1233,8 @@
 "../../src/pages/iou/request/step/IOURequestStepSubrate.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/iou/request/step/IOURequestStepSubrate.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/iou/request/step/IOURequestStepSubrate.tsx"	"react-hooks/set-state-in-effect"	1
+"../../src/pages/iou/request/step/IOURequestStepUpgrade.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
+"../../src/pages/iou/request/step/IOURequestStepUpgrade.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/request/step/IOURequestStepWaypoint.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/request/step/StepScreenWrapper.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/iou/request/step/confirmation/submitDismissStrategies.ts"	"no-restricted-imports"	1
@@ -1286,6 +1312,7 @@
 "../../src/pages/settings/Wallet/UnshareBankAccount/UnshareBankAccount.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/settings/Wallet/UpdatePersonalBankAccountPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/settings/Wallet/WalletPage/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/settings/Wallet/WalletPage/index.tsx"	"no-restricted-imports"	1
 "../../src/pages/settings/Wallet/WalletPage/index.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/signin/LoginForm/BaseLoginForm.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/signin/SAMLSignInPage/index.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1298,7 +1325,6 @@
 "../../src/pages/signin/SignInPageLayout/FooterRow/index.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx"	"react-hooks/set-state-in-effect"	4
 "../../src/pages/tasks/NewTaskPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
-"../../src/pages/tasks/TaskAssigneeSelectorModal.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	2
 "../../src/pages/tasks/TaskShareDestinationSelectorModal.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/wallet/WalletStatementPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/DynamicWorkspaceOverviewPlanTypePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1306,6 +1332,7 @@
 "../../src/pages/workspace/WorkspaceConfirmationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/workspace/WorkspaceInitialPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/workspace/WorkspaceMembersPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/workspace/WorkspaceMembersPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/WorkspaceMembersPage.tsx"	"react-hooks/exhaustive-deps"	1
 "../../src/pages/workspace/WorkspaceMembersPage.tsx"	"react-hooks/refs"	1
 "../../src/pages/workspace/WorkspaceNewRoomPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
@@ -1366,12 +1393,16 @@
 "../../src/pages/workspace/accounting/qbd/export/DynamicQuickbooksDesktopOutOfPocketExpenseEntitySelectPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopChartOfAccountsPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopChartOfAccountsPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx"	"no-restricted-syntax"	3
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx"	"no-restricted-syntax"	3
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage.tsx"	"no-restricted-syntax"	3
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/qbo/advanced/DynamicQuickbooksOnlineAccountingMethodPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1382,15 +1413,18 @@
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/reconciliation/CardReconciliationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/accounting/utils.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/workspace/accounting/xero/XeroImportPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/xero/XeroImportPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/workspace/accounting/xero/XeroImportPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx"	"no-restricted-syntax"	4
 "../../src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1399,10 +1433,11 @@
 "../../src/pages/workspace/accounting/xero/export/DynamicXeroPurchaseBillStatusSelectorPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx"	"no-restricted-syntax"	3
 "../../src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/categories/CategorySettingsPage.tsx"	"react-hooks/preserve-manual-memoization"	1
-"../../src/pages/workspace/categories/WorkspaceCategoriesPage.tsx"	"react-hooks/set-state-in-effect"	2
+"../../src/pages/workspace/categories/WorkspaceCategoriesPage.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/companyCards/BankConnection/index.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/workspace/companyCards/WorkspaceCompanyCardDetailsPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1420,7 +1455,6 @@
 "../../src/pages/workspace/copyPolicySettings/CopyPolicySettingsConfirmPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/copyPolicySettings/CopyPolicySettingsSelectFeaturesPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx"	"react-hooks/preserve-manual-memoization"	1
-"../../src/pages/workspace/downgrade/WorkspaceDowngradePage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/workspace/duplicate/WorkspaceDuplicateSelectFeaturesForm.tsx"	"react-hooks/preserve-manual-memoization"	2
 "../../src/pages/workspace/duplicate/WorkspaceDuplicateSelectFeaturesForm.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1434,10 +1468,10 @@
 "../../src/pages/workspace/hr/HRProviderCard.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/hr/utils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/workspace/members/ImportMembersPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/members/ImportMembersPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/workspace/members/ImportMembersPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/members/ImportedMembersConfirmationPage.tsx"	"react-hooks/refs"	7
-"../../src/pages/workspace/members/ImportedMembersPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -1456,6 +1490,7 @@
 "../../src/pages/workspace/travel/WorkspaceTravelInvoicingSection.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	3
 "../../src/pages/workspace/travel/WorkspaceTravelInvoicingSettlementAccountPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/upgrade/UpgradeIntro.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/withPolicy.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/pages/workspace/withPolicyAndFullscreenLoading.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1467,6 +1502,7 @@
 "../../src/selectors/AdvancedSearchFiltersForm.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/selectors/Domain.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/selectors/Policy.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/selectors/Policy.ts"	"no-restricted-imports"	1
 "../../src/setup/addUtilsToWindow.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
 "../../src/setup/moduleInitPolyfill.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/setup/telemetry/index.web.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1551,19 +1587,29 @@
 "../../tests/actions/BankAccountsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/actions/CopyPolicySettingsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	18
 "../../tests/actions/DomainTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
+"../../tests/actions/EnforceActionExportRestrictions.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/BuildOnyxDataForMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	17
+"../../tests/actions/IOU/CreateDraftTransactionTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/GetMoneyRequestInformationTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../tests/actions/IOU/MoneyRequestBuilderTest.ts"	"no-restricted-imports"	1
+"../../tests/actions/IOU/MoneyRequestSettersTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/PerDiemTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
 "../../tests/actions/IOU/RequestMoneyTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
+"../../tests/actions/IOU/RequestMoneyTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/SearchUpdateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../tests/actions/IOU/SearchUpdateTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/SplitReportTotalsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
+"../../tests/actions/IOU/SplitReportTotalsTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/BulkEditTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	25
 "../../tests/actions/IOUTest/DeleteMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/actions/IOUTest/DuplicateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	23
 "../../tests/actions/IOUTest/GetUpdateMoneyRequestParamsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/actions/IOUTest/HoldTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../tests/actions/IOUTest/HoldTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/PayMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
+"../../tests/actions/IOUTest/PayMoneyRequestTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/ReceiptTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9
+"../../tests/actions/IOUTest/ReceiptTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/RejectMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/IOUTest/ReportWorkflowTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	64
 "../../tests/actions/IOUTest/SendInvoiceTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	7
@@ -1571,27 +1617,37 @@
 "../../tests/actions/IOUTest/SplitSelfDMTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/actions/IOUTest/SplitTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	21
 "../../tests/actions/IOUTest/TrackExpenseTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
+"../../tests/actions/IOUTest/TrackExpenseTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/UpdateMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
-"../../tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../tests/actions/IOUTest/UpdateMoneyRequestTest.ts"	"no-restricted-imports"	1
+"../../tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/actions/MergeTransactionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
+"../../tests/actions/OdometerTransactionUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/OnyxUpdateManagerTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/actions/PersonalDetailsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
 "../../tests/actions/PolicyCategoryTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/PolicyMemberTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9
 "../../tests/actions/PolicyProfileTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../tests/actions/PolicyProfileTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/PolicyTagTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/PolicyTaxTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/PolicyTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	86
+"../../tests/actions/PolicyTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/QueuedOnyxUpdatesTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/ReimbursementAccountTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/actions/ReplaceOptimisticReportWithActualReportTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/actions/ReportFieldTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../tests/actions/ReportFieldTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/ReportPreviewActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	28
+"../../tests/actions/ReportPreviewActionUtilsTest.ts"	"no-restricted-imports"	2
 "../../tests/actions/ReportTest.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	1
 "../../tests/actions/ReportTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	80
+"../../tests/actions/ReportTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/SessionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	12
 "../../tests/actions/SubscriptionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/actions/TaskTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	44
+"../../tests/actions/TaskTest.ts"	"no-restricted-imports"	1
+"../../tests/actions/TransactionTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/UserTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	45
 "../../tests/actions/WorkflowTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	13
 "../../tests/actions/connections/NetSuite.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
@@ -1625,7 +1681,7 @@
 "../../tests/perf-test/ReportUtils.perf-test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/perf-test/SelectionList.perf-test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/perf-test/useFilterFormValues.perf-test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	15
-"../../tests/ui/AgentsPromoBannersTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../tests/ui/AgentsPromoBannersTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/ui/AssignCardFeed.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/ui/AuthScreensInitHandlerTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	7
 "../../tests/ui/AvatarSelector.test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	7
@@ -1655,6 +1711,7 @@
 "../../tests/ui/MoneyReportViewTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/MoneyRequestReportActionsListRejectModalTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/ui/MoneyRequestReportFooter.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
+"../../tests/ui/MoneyRequestReportPreview.test.tsx"	"no-restricted-imports"	1
 "../../tests/ui/MoneyRequestViewTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/MonthListItemHeaderTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/ui/MultifactorAuthenticationRevokePageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	8
@@ -1694,6 +1751,7 @@
 "../../tests/ui/WorkspaceInviteMessageApproverPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/WorkspaceMembersTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/WorkspaceMoreFeaturesPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../tests/ui/WorkspaceMoreFeaturesPageTest.tsx"	"no-restricted-imports"	1
 "../../tests/ui/WorkspaceOnboarding.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/WorkspaceTagsTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/ui/WorkspaceUpgradeTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1712,9 +1770,9 @@
 "../../tests/ui/components/SettlementButtonTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/ui/components/TimePickerTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/hooks/useHtmlPasteTest/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	10
-"../../tests/unit/APITest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	74
+"../../tests/unit/APITest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	61
 "../../tests/unit/AddExistingExpenseSearchTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
-"../../tests/unit/AgentActionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	61
+"../../tests/unit/AgentActionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	53
 "../../tests/unit/AgentZeroStatusContextTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/AvatarButtonWithIconTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/AvatarUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1727,7 +1785,7 @@
 "../../tests/unit/CIGitLogicTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/CLIVariadicTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/CardFeedErrorsDerivedValueTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/CardFeedUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	16
+"../../tests/unit/CardFeedUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/CardUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	152
 "../../tests/unit/CardsSectionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/CategoryUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1758,14 +1816,17 @@
 "../../tests/unit/FlashListTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/FocusTrapForModalTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/FormulaTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	78
+"../../tests/unit/FormulaTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/FraudProtectionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/GitTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/GithubUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/HomePage/YourSpendSection/YourSpendSectionTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/HomePage/YourSpendSection/useYourSpendDataTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
+"../../tests/unit/HomePage/YourSpendSection/useYourSpendDataTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/HrUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	61
 "../../tests/unit/HybridAppActionsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/IOUUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
+"../../tests/unit/IOUUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/ImageSVGCachePolicyTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/ImportTransactions.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	17
 "../../tests/unit/LHNAvatarPipelineTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1776,7 +1837,8 @@
 "../../tests/unit/MentionUserRendererTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/MentionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/MiddlewareTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
-"../../tests/unit/ModifiedExpenseMessageTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
+"../../tests/unit/ModifiedExpenseMessageTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
+"../../tests/unit/ModifiedExpenseMessageTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/MoneyRequestReportTransactionListActiveTransactionIDsTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/MoneyRequestReportUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/MoneyRequestUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
@@ -1808,6 +1870,7 @@
 "../../tests/unit/PopoverMenuV2Test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/PressResponderTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/QuickActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	7
+"../../tests/unit/QuickActionUtilsTest.ts"	"no-restricted-imports"	2
 "../../tests/unit/ReceiptAlternativeMethodsTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/RefreshCardFeedConnectionPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/ReimbursementAccountUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1816,13 +1879,17 @@
 "../../tests/unit/ReportActionsListPaddingViewTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/ReportActionsUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	35
 "../../tests/unit/ReportLayoutUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
+"../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	23
 "../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	168
-"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	450
+"../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"no-restricted-imports"	1
+"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	466
+"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"no-restricted-imports"	2
 "../../tests/unit/ReportSubmitUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportTitleUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../tests/unit/ReportTitleUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/ReportUtilsGetIconsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/ReportUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	98
+"../../tests/unit/ReportUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	105
+"../../tests/unit/ReportUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/ReportWelcomeTextTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/RequestConflictUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/RequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1831,7 +1898,7 @@
 "../../tests/unit/Search/SearchListRenderCountTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/Search/SearchQueryUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9
 "../../tests/unit/Search/SearchSingleSelectionPickerTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/Search/SearchUIUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	133
+"../../tests/unit/Search/SearchUIUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	136
 "../../tests/unit/Search/buildCardFilterDataTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
 "../../tests/unit/Search/buildSubstitutionsMapTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/Search/getSpendOverTimeStateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1846,7 +1913,8 @@
 "../../tests/unit/SelectFeaturesEmptyTagGroupTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/SettlementButtonUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/SidebarTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
-"../../tests/unit/SidebarUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	31
+"../../tests/unit/SidebarUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	35
+"../../tests/unit/SidebarUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/SplitExpenseAutoAdjustmentTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/SubscriptionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/SuggestedFollowupTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1869,6 +1937,7 @@
 "../../tests/unit/ViolationUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
 "../../tests/unit/WhisperContentMentionContextTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/WorkflowUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
+"../../tests/unit/WorkspaceReportFieldUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/WorkspacesSettingsUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	15
 "../../tests/unit/awaitStagingDeploysTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/canEditFieldOfMoneyRequestTest.ts"	"@typescript-eslint/no-deprecated/randomReportAction.originalMessage"	3
@@ -1920,7 +1989,7 @@
 "../../tests/unit/hooks/useDraftMessageVideoAttributeCache.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/hooks/useEditComposerToggle.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/hooks/useEditMessage.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
-"../../tests/unit/hooks/useExpenseSubmission.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../tests/unit/hooks/useExpenseSubmission.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/hooks/useExpensifyCardFeedsForFeedSelector.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/hooks/useExportedToFilterOptions.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/hooks/useFilterFeedDataTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1930,7 +1999,6 @@
 "../../tests/unit/hooks/useFreeTrial.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/hooks/useGettingStartedItems.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/hooks/useHasAnyAdminExpensifyCardFeed.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/hooks/useHoldRejectActionsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/hooks/useIsAllowedToIssueCompanyCard.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/hooks/useIsBlockedToAddFeed.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/hooks/useIsSidebarRouteActive.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1978,10 +2046,12 @@
 "../../tests/unit/markPullRequestsAsDeployedTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/navigateAfterExpenseCreateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/navigateAfterOnboardingTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../tests/unit/navigateAfterOnboardingTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/navigateToWorkspacesPageTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	14
+"../../tests/unit/navigateToWorkspacesPageTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/pages/home/GettingStartedSection/GettingStartedSectionTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	11
-"../../tests/unit/pages/inbox/ConciergeDraftContext.test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/pages/inbox/report/ReportActionEditMessageContext.test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../tests/unit/pages/inbox/report/ReportActionEditMessageContext.test.tsx"	"no-restricted-imports"	1
 "../../tests/unit/pages/settings/AddAgentAvatarPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/pages/settings/AddAgentPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/pages/settings/AgentsListRowTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -2017,6 +2087,7 @@
 "../../tests/unit/useGroupDraftRestoreTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	14
 "../../tests/unit/useIndicatorStatusTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/useLastWorkspaceNumberTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../tests/unit/useMarkAsReadTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/usePersonalDetailSearchSelectorTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/usePolicyIndicatorChecksTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/usePopoverPositionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
diff --git a/contributingGuides/CONTRIBUTING.md b/contributingGuides/CONTRIBUTING.md
index 449f5ff7a125..8e0cd9a65e59 100644
--- a/contributingGuides/CONTRIBUTING.md
+++ b/contributingGuides/CONTRIBUTING.md
@@ -4,10 +4,13 @@ Welcome! Thanks for checking out the New Expensify app and taking the time to co
 ## Getting Started
 If you would like to become an Expensify contributor, the first step is to read this document in its **entirety**. The second step is to review the README guidelines [here](https://github.com/Expensify/App/blob/main/README.md) to understand our coding philosophy and for a general overview of the code repository (i.e. how to run the app locally, testing, storage, our app philosophy, etc). Please read both documents before asking questions, as it may be covered within the documentation.
 
+### MelvinBot issues (read this)
+Many App jobs use [MelvinBot](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md) (Melvin), our AI agent that posts the first proposal on an issue. **Do not open a pull request until a proposal is accepted.** Contributors, C+, and internal engineers each have specific responsibilities on these jobs. See **[How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md)** before working on any issue where Melvin has posted a proposal.
+
 ### Test Accounts
 You can create as many accounts as needed in order to test your changes directly from [the app](https://new.expensify.com/). An initial account can be created when logging in for the first time, and additional accounts can be created by opening the "New Chat" or "Group Chat" pages via the Global Create menu, inputting a valid email or phone number, and tapping the user's avatar. Do not use Expensify employee or customer accounts for testing.
 
-**Notes**: 
+**Notes**:
 
 1. When creating test accounts:
   - Include a `+` (plus sign) in the email address (e.g., matt+1@gmail.com). This marks the account and their associated workspaces as test accounts in Expensify, ensuring Expensify Guides are not assigned to help with account setup.
@@ -21,7 +24,7 @@ You can generate multiple test accounts by using a `+` postfix, for example if y
 
 #### High Traffic Accounts
 
-All internal engineers, contributors, and C+ members are required to test with a “high traffic” account against the staging or production web servers. Use these Google forms to manage your high-traffic accounts. You'll need to authenticate via Google first. 
+All internal engineers, contributors, and C+ members are required to test with a “high traffic” account against the staging or production web servers. Use these Google forms to manage your high-traffic accounts. You'll need to authenticate via Google first.
 1. [Make an account high-traffic](https://docs.google.com/forms/d/e/1FAIpQLScpiS0Mo-HA5xHPsvDow79yTsMBgF0wjuqc0K37lTK5fheB8Q/viewform)
 2. [Remove a high-traffic account](https://docs.google.com/forms/d/e/1FAIpQLSd9_FDav83pnhhtu1KGAKIpf2yttQ_0Bvq1b9nuFM1-wbL11Q/viewform)
 
@@ -40,7 +43,7 @@ We have a shared Slack channel called #expensify-open-source — this channel is
 
 That said, we have a small issue with adding users at the moment and we’re working with Slack to try and get this resolved. If you would like to join, [fill out this form](https://forms.gle/Q7hnhUJPnQCK7Fe56) with your email and Upwork profile link. Once resolved, we’ll add you.
 
-Note: Do not send direct messages to the Expensify team in Slack or Expensify Chat, they will not be able to respond. 
+Note: Do not send direct messages to the Expensify team in Slack or Expensify Chat, they will not be able to respond.
 
 Note: if you are hired for an Upwork job and have any job-specific questions, please ask in the GitHub issue or pull request. This will ensure that the person addressing your question has as much context as possible.
 
@@ -48,9 +51,9 @@ Note: if you are hired for an Upwork job and have any job-specific questions, pl
 If you've found a vulnerability, please email security@expensify.com with the subject `Vulnerability Report` instead of creating an issue.
 
 ## Payment for Contributions
-We hire and pay external contributors via [Upwork.com](https://www.upwork.com). If you'd like to be paid for contributing, please create an Upwork account, apply for an available job in [GitHub](https://github.com/Expensify/App/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22), and finally apply for the job in Upwork once your proposal gets selected in GitHub. Please make sure your Upwork profile is **fully verified** before applying, otherwise you run the risk of not being paid. If you think your compensation should be increased for a specific job, you can request a reevaluation by commenting in the Github issue where the Upwork job was posted. 
+We hire and pay external contributors via [Upwork.com](https://www.upwork.com). If you'd like to be paid for contributing, please create an Upwork account, apply for an available job in [GitHub](https://github.com/Expensify/App/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22), and finally apply for the job in Upwork once your proposal gets selected in GitHub. Please make sure your Upwork profile is **fully verified** before applying, otherwise you run the risk of not being paid. If you think your compensation should be increased for a specific job, you can request a reevaluation by commenting in the Github issue where the Upwork job was posted.
 
-Please add your Upwork profile link in your GitHub Bio to help ensure prompt payment.  If you're using Slack or Expensify for discussions, please add your Upwork profile link **and** your GitHub username in your Slack Title and Expensify Status. 
+Please add your Upwork profile link in your GitHub Bio to help ensure prompt payment.  If you're using Slack or Expensify for discussions, please add your Upwork profile link **and** your GitHub username in your Slack Title and Expensify Status.
 
 Payment for your contributions will be made no less than 7 days after the pull request is deployed to production to allow for [regression](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions) testing. If you have not received payment after 8 days of the PR being deployed to production, and there are no [regressions](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions), please add a comment to the issue mentioning the team member assigned to pay (Look for the melvin-bot "Triggered auto assignment to... (`Awaiting Payment`)" to see who this is).
 
@@ -58,13 +61,13 @@ New contributors are limited to working on one job at a time, **do not submit pr
 
 Please be aware that compensation for any support in solving an issue is provided **entirely at Expensify’s discretion**. Personal time or resources applied towards investigating a proposal **will not guarantee compensation**. Compensation is only guaranteed to those who **[propose a solution and get hired for that job](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#propose-a-solution-for-the-job)**. We understand there may be cases where a selected proposal may take inspiration from a previous proposal. Unfortunately, it’s not possible for us to evaluate every individual case and we have no process that can efficiently do so. Issues with higher rewards come with higher risk factors so try to keep things civil and make the best proposal you can. Once again, **any information provided may not necessarily lead to you getting hired for that issue or compensated in any way.**
 
-**Important:** Payment amounts are variable, dependent on if there are any [regressions](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions). Your PR will be reviewed by a [Contributor+ (C+)](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) team member and an internal engineer.  All tests must pass and all code must pass lint checks before a merge. 
+**Important:** Payment amounts are variable, dependent on if there are any [regressions](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions). Your PR will be reviewed by a [Contributor+ (C+)](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) team member and an internal engineer.  All tests must pass and all code must pass lint checks before a merge.
 
 Contributors are eligible to be paid via Expensify 18 months after they were first assigned to a job. More details at [PAYMENT_VIA_EXPENSIFY.md](https://github.com/Expensify/App/blob/main/contributingGuides/PAYMENT_VIA_EXPENSIFY.md)
 
 ### Regressions
 
-If a PR causes a regression at any point within the regression period (starting when the code is merged and ending 168 hours (that's 7 days) after being deployed to production): 
+If a PR causes a regression at any point within the regression period (starting when the code is merged and ending 168 hours (that's 7 days) after being deployed to production):
 - payments will be issued 7 days after all regressions are fixed (ie: deployed to production)
 - a 50% penalty will be applied to the Contributor and [Contributor+](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) for each regression on an issue
 
@@ -88,7 +91,7 @@ In short, a good problem statement makes no mention whatsoever of the desired so
 
 **Bad:**
 > **Problem:** We don't have a car
-> 
+>
 > **Solution:** Buy a car.
 
 
@@ -152,8 +155,9 @@ This helps future investigators understand the history and current status of err
 3. If you cannot reproduce the problem, pause on this step and add a comment to the issue explaining where you are stuck or that you don't think the issue can be reproduced.
 
 ### Propose a solution for the job
-4. Proposals must only be posted after the `Help Wanted` label is added. Any proposals submitted beforehand will be ignored and not reviewed. Do not post proposals in Slack.
-5. Contributors should **not** submit proposals on issues when they have assigned issues or PRs that are awaiting an action from them. If so, they will be in violation of Rule #1 (Get Shit Done) in our [Code of Conduct](https://github.com/Expensify/App/blob/main/CODE_OF_CONDUCT.md) and will receive a warning. Multiple warnings can lead to removal from the program. 
+4. Proposals must only be posted after the `Help Wanted` label is added. Any proposals submitted beforehand will be ignored and not reviewed. Do not post proposals in Slack. MelvinBot is an exception: it may post a proposal before `Help Wanted` is applied.
+    - On issues where [MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) has posted a proposal, review Melvin's proposal using the same standards as contributor proposals. Melvin's proposal is not guaranteed to be the earliest, but it should always be reviewed first because we are spending the money to run it. Follow first-come-first-serve review order for all other proposals after `Help Wanted`. **Do not open a PR** until a proposal is accepted. See [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) for more details.
+5. Contributors should **not** submit proposals on issues when they have assigned issues or PRs that are awaiting an action from them. If so, they will be in violation of Rule #1 (Get Shit Done) in our [Code of Conduct](https://github.com/Expensify/App/blob/main/CODE_OF_CONDUCT.md) and will receive a warning. Multiple warnings can lead to removal from the program.
 6. After you reproduce the issue, complete the [proposal template here](./PROPOSAL_TEMPLATE.md) and post it as a comment in the corresponding GitHub issue (linked in the Upwork job).
     - Note: Before submitting a proposal on an issue, be sure to read any other existing proposals. ALL NEW PROPOSALS MUST BE DIFFERENT FROM EXISTING PROPOSALS. The *difference* should be important, meaningful or considerable.
 7. Refrain from leaving additional comments until someone from the Contributor-Plus team and / or someone from Expensify provides feedback on your proposal (do not create a pull request yet).
@@ -197,18 +201,18 @@ This helps future investigators understand the history and current status of err
 
 ### Completing the final checklist
 20. Once your PR has been deployed to production, a checklist will automatically be commented in the GH issue. You're required to complete the steps that have your name mentioned before payment will be issued.
-21. The items requiring your completion consist of: 
+21. The items requiring your completion consist of:
     1. Proposing steps to take for a regression test to ensure the bug doesn't occur again (For information on how to successfully complete this, head [here](https://github.com/Expensify/App/blob/main/contributingGuides/REGRESSION_TEST_BEST_PRACTICES.md)).
     2. Identifying and noting the offending PR that caused the bug (if any).
     3. Commenting on the offending PR to note the bug it caused and why (if applicable).
-    4. Starting a conversation on if any additional steps should be taken to prevent further bugs similar to the one fixed from occurring again. 
-22. Once the above items have been successfully completed, then payments will begin to be issued. 
+    4. Starting a conversation on if any additional steps should be taken to prevent further bugs similar to the one fixed from occurring again.
+22. Once the above items have been successfully completed, then payments will begin to be issued.
 
 ### Timeline expectations and asking for help along the way
 - If you have made a change to your pull request and are ready for another review, leave a comment that says "Updated" on the pull request  itself.
 - Please keep the conversation in GitHub, and do not ping individual reviewers in Slack or Upwork to get their attention.
 - Pull Request reviews can sometimes take a few days. If your pull request has not been addressed after four days, please let us know via the #expensify-open-source Slack channel.
-- On occasion, our engineers will need to focus on a feature release and choose to place a hold on the review of your PR. 
+- On occasion, our engineers will need to focus on a feature release and choose to place a hold on the review of your PR.
 
 ### Important note about JavaScript Style
 - Read our official [JavaScript and React style guide](https://github.com/Expensify/App/blob/main/contributingGuides/STYLE.md). Please refer to our Style Guide before asking for a review.
@@ -219,9 +223,9 @@ This helps future investigators understand the history and current status of err
 ### For external agencies that Expensify partners with
 Follow all the above above steps and processes. When you find a job you'd like to work on:
 - Post “I’m from [agency], I’d like to work on this job”
-  - If no proposals have been submitted by other contributors, BugZero (BZ) team member or an internal engineer will assign the issue to you. 
-  - If there are existing proposals, BZ will put the issue on hold. [Contributor+](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) will review the existing proposals.  If a contributor’s proposal is accepted then the contributor will be assigned to the issue.  If not the issue will be assigned to the agency-employee. 
-- Once assigned follow the steps [here](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#propose-a-solution-for-the-job) to submit your proposal 
+  - If no proposals have been submitted by other contributors, BugZero (BZ) team member or an internal engineer will assign the issue to you.
+  - If there are existing proposals, BZ will put the issue on hold. [Contributor+](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) will review the existing proposals.  If a contributor’s proposal is accepted then the contributor will be assigned to the issue.  If not the issue will be assigned to the agency-employee.
+- Once assigned follow the steps [here](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#propose-a-solution-for-the-job) to submit your proposal
 
 ## Guide on Acronyms used within Expensify Communication
 During communication with Expensify, you will come across a variety of acronyms used by our team. While acronyms can be useful, they cease to be the moment they are not known to the receiver. As such, we wanted to create a list here of our most commonly used acronyms and what they're referring to. Lastly, please never hesitate to ask in Slack or the GH issue if there are any that are not understood/known!
@@ -231,8 +235,8 @@ During communication with Expensify, you will come across a variety of acronyms
 - **LHN:** Left Hand Navigation (Primary navigation modal in Expensify Chat, docked on the left-hand side)
 - **OP:** Original Post (Most commonly the post in E/App GH issues that reports the bug)
 - **FAB** Floating Action Button (the + Button that is used to launch flows like 'New Chat', 'Request Money')
-- **GBR:** Green Brick Road (UX Design Principle that utilizes green indicators on action items to encourage the user down the optimal path for a given process or task) 
-- **RBR:** Red Brick Road (UX Design Principle that utilizes red indicators on action items to encourage the user down the optimal path for handling and discovering errors) 
+- **GBR:** Green Brick Road (UX Design Principle that utilizes green indicators on action items to encourage the user down the optimal path for a given process or task)
+- **RBR:** Red Brick Road (UX Design Principle that utilizes red indicators on action items to encourage the user down the optimal path for handling and discovering errors)
 - **VBA:** Verified Bank Account (Bank account that has been verified as real and belonging to the correct business/individual)
 - **NAB:** Not a Blocker (An issue that doesn't block progress, but would be nice to not have)
 - **IOU:** I owe you (used to describe payment requests between users)
@@ -241,3 +245,4 @@ During communication with Expensify, you will come across a variety of acronyms
 - **QA:** Quality Assurance
 - **GH:** GitHub
 - **LGTM:*** Looks good to me
+- **MelvinBot:** Expensify's AI agent for App GitHub issues (posts proposals, implements accepted solutions). See [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md).
diff --git a/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md b/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md
index 9993755274e5..9922324c1ea8 100644
--- a/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md
+++ b/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md
@@ -2,6 +2,7 @@
 C+ are contributors who are experienced at working with Expensify and have gained the confidence of the internal Expensify team. Accordingly, they are allocated additional opportunities and responsibilities:
   - They review proposed solutions in external GitHub issues, validate them, and make recommendations to an internal Contributor Manager Engineer (CME).
   - Once a proposal has been accepted by a CME, the C+ will be the first person to review the pull request associated with that proposal.
+  - On [MelvinBot issues](./HOW_TO_WORK_WITH_MELVINBOT.md), the C+ reviews Melvin's proposal, recommends it to the CME, asks Melvin to implement after CME approval, and owns the PR as the human author before CME PR review.
 
 ## Why would someone want to be a C+
 - C+ are compensated the same price as the contributor for reviewing proposals and the associated PR. (ie. if a job is listed at $250, that’s how much the C+ will make if they review both the proposals and PR).  If regressions are found that should have* been caught after the PR has been approved, C+ payment is reduced by 50% for each regression found.
diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
new file mode 100644
index 000000000000..da3b0101a5d9
--- /dev/null
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -0,0 +1,105 @@
+# Working with MelvinBot on App Issues
+
+MelvinBot (Melvin) is Expensify's AI agent for App GitHub issues. On many open-source jobs, Melvin posts the first proposal automatically. This guide explains how contributors, Contributor+ (C+), and internal engineers work together on those issues.
+
+Clearly documenting the process helps us move efficiently by preventing all of us from wasting time on incorrect solutions. Internal engineering approval is required on Melvinbot proposals because we usually have the most context to know whether a solution aligns with our best practices.
+
+For general contributor workflow (proposals, payment, PR standards), see [CONTRIBUTING.md](./CONTRIBUTING.md). For C+ responsibilities, see [HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md](./HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md).
+
+## Roles
+
+| Role | Responsibility on Melvin issues |
+|------|----------------------------------|
+| **MelvinBot** | Posts the first proposal on the issue. Implements the accepted solution when asked. Opens a draft PR with MelvinBot as the GitHub author. |
+| **Contributor** | May submit their own proposal if they have a meaningfully different approach. Must not open a PR until a proposal is accepted and they are hired on the job. |
+| **Contributor+ (C+)** | Reviews proposals (Melvin's and any contributor proposals) using the same standards as any other job. Recommends acceptance to the CME. After the CME approves, asks Melvin to implement, then owns the PR as the human author before sending it for final review. |
+| **Contributor Manager Engineer (CME)** | Reviews and approves proposals (same as any other App job). After implementation, reviews and merges the PR. |
+
+Only Expensify employees, C+ members, and backend contributors can trigger Melvin with `@MelvinBot` comments on GitHub.
+
+## Workflow overview
+
+```
+Issue opened → Melvin posts proposal → C+ reviews proposal(s)
+    → C+ recommends acceptance (🎀👀🎀) → CME approves proposal
+    → C+ asks Melvin to implement (only after CME approval)
+    → Not accepted: C+ or CME explains why
+→ Melvin opens draft PR → C+ tweaks, tests, posts PR body/checklist in a PR comment, asks Melvin to apply it, self-reviews (including Reviewer checklist)
+→ C+ submits PR for review as human author → CME reviews and merges (PR body and/or C+ PR comment)
+```
+
+## Phase 1: Proposal review
+
+Follow the **same proposal review process** as any other App job, but remember to review the MelvinBot proposal first, and then review in first-come-first-serve review order for proposals posted after the `Help Wanted` is applied (see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
+
+1. Use the [proposal template](./PROPOSAL_TEMPLATE.md) criteria: clear root cause, concrete solution, no code diffs.
+2. C+ reviews Melvin's proposal with the same rigor as a contributor proposal. Do not approve proposals that lack a satisfying root-cause explanation.
+3. Contributors may still post proposals if they have a **meaningfully different** approach (see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
+4. **No one opens a pull request** until a proposal is accepted by the CME (same as any other App job; see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
+5. If Melvin's proposal is not acceptable, the C+ can review proposals from other contributors, or iterate with Melvin by tagging `@MelvinBot` on the issue, explaining the needed changes, and asking it to update its proposal or post a new one until it is satisfactory.
+
+### C+ reviews and recommends
+
+The C+ reviews Melvin's proposal with the same rigor as a contributor proposal. Follow the [proposal template](./PROPOSAL_TEMPLATE.md) review instructions.
+
+When the C+ is satisfied with Melvin's proposal, they recommend it to the CME by posting `🎀👀🎀` on the issue. That triggers CME assignment for the job.
+
+### After the CME approves the proposal
+
+Once the assigned CME has approved Melvin's proposal (the same acceptance step as for any contributor proposal), the C+ comments on the issue asking Melvin to implement. Include a link to the specific proposal comment so Melvin implements the latest version (Melvin may post a new proposal when asked to update). For example:
+
+```
+@MelvinBot please implement your proposal at https://github.com/Expensify/App/issues/12345#issuecomment-6789012345
+```
+
+Adjust the wording if needed, but the comment must mention `@MelvinBot`, link to the proposal comment, and clearly request implementation.
+
+## Phase 2: C+ owns the pull request
+
+Melvin opens a draft PR linked to the issue. MelvinBot remains the GitHub author but the C+ is the human author. Most C+ members will **not be able to edit the PR description directly** (GitHub only allows the author or users with write access to edit a pull request body).
+
+Before requesting final review, the assigned C+ must:
+
+1. **Manually tweak the PR** if Melvin's implementation needs corrections. Comment on the pull request, tag `@MelvinBot`, and explain the needed changes so Melvin can update the code.
+2. **Test the change** on all required platforms (see [CONTRIBUTING.md](./CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)).
+3. **Complete every step** in the PR Author Checklist (see [Updating the PR description and checklist](#updating-the-pr-description-and-checklist) below). Screenshots and videos may live only in the Reviewer Checklist section of your PR comment; you do not need to duplicate them in the Author Checklist.
+4. **Self-review the code** against [PR Review Guidelines](./PR_REVIEW_GUIDELINES.md), [PR Authoring & Reviewing Best Practices](./PR_AUTHOR_REVIEWER_BEST_PRACTICES.md), and complete the [Reviewer Checklist](./REVIEWER_CHECKLIST.md) as part of that self-review.
+
+The C+ is accountable for the PR quality, the same as any contributor who authored a PR.
+
+### Updating the PR description and checklist
+
+C+ members who cannot edit the PR body directly should use this workaround:
+
+1. On the **pull request**, post a comment with the exact content you want in the PR description. Put the full body inside a `<details>` block so the PR thread stays readable. Include the complete [PR template](https://github.com/Expensify/App/blob/main/.github/PULL_REQUEST_TEMPLATE.md) when possible: Explanation of Change, Fixed Issues, Tests, Offline tests, QA Steps, a fully checked PR Author Checklist, and Screenshots/Videos sections as needed.
+2. In the same comment, ask Melvin to copy that content into the pull request body, for example:
+
+```
+@MelvinBot please set the PR body to the content in the details section above
+```
+
+To update only the checklist, etc, post the section in a `<details>` block and ask Melvin to set just that portion of the PR body.
+
+3. Confirm Melvin updated the PR description before marking the pull request ready for review.
+
+The C+ PR comment is the **source of truth** for what was tested and checked. CMEs may review that comment directly when the PR body is incomplete, out of date, or hard to verify.
+
+## Phase 3: CME review and merge
+
+After the C+ submits the PR for review:
+
+1. A **CME** (internal engineer) is assigned to review and merge.
+2. The CME follows the normal internal review process. Review the **PR body** when Melvin has applied the C+ content, or failing that, review the C+ **PR comment** (with the `<details>` block) directly for testing steps and checklist completion.
+3. Payment and regression checklists follow the standard rules in [CONTRIBUTING.md](./CONTRIBUTING.md).
+
+### No additional contributor or C+ PR review
+
+We intentionally do **not** add a second round of contributor or C+ PR review on top of the CME review. Prior discussions did not surface a problem that extra review would solve, and an additional review step would add cost and delay without clear benefit. The C+ self-review before submission, combined with CME review, is the intended quality gate.
+
+## Related documentation
+
+- [CONTRIBUTING.md](./CONTRIBUTING.md) — full contributor workflow
+- [PROPOSAL_TEMPLATE.md](./PROPOSAL_TEMPLATE.md) — proposal format and C+ review instructions
+- [Reviewer Checklist](./REVIEWER_CHECKLIST.md) — C+ completes this during self-review before submitting for CME review
+- [AI Etiquette](./AI_ETIQUETTE.md) — accountability for AI-assisted work
+- [AI Reviewer philosophy](./philosophies/AI-REVIEWER.md) — automated PR feedback vs human review
diff --git a/contributingGuides/INTERACTION_MANAGER.md b/contributingGuides/INTERACTION_MANAGER.md
index 08008b0b42ad..5d152fc04532 100644
--- a/contributingGuides/INTERACTION_MANAGER.md
+++ b/contributingGuides/INTERACTION_MANAGER.md
@@ -29,7 +29,37 @@ On top of TransitionTracker, existing APIs gain transition-aware callbacks:
 
 This makes the code self-descriptive: instead of a generic `runAfterInteractions`, each call site says exactly what it's waiting for and why.
 
-> **Note:** `TransitionTracker.runAfterTransitions` is an internal primitive. Application code should use the higher-level APIs (`Navigation`, `useConfirmModal`, etc.) rather than importing TransitionTracker directly.
+### What TransitionTracker actually tracks
+
+TransitionTracker registers transitions **only** in the following cases:
+
+1. **Navigation transitions** — screen push/pop/replace animations (via `transitionStart`/`transitionEnd` events in `ScreenLayout`)
+2. **Modal transitions** — modal open/close animations (via `ReanimatedModal`)
+3. **Keyboard transitions** — keyboard dismiss animations (via `KeyboardUtils.dismiss`)
+
+### When to use `runAfterTransitions` directly
+
+Prefer higher-level APIs (`Navigation` with `afterTransition`/`waitForTransition`, `KeyboardUtils`, `useConfirmModal`) whenever possible. Use `TransitionTracker.runAfterTransitions` directly **only** when:
+
+- There is no specific navigation/keyboard/modal action you can attach a callback to, or
+- There are too many concurrent actions and it's impossible to bind the callback to a particular one.
+
+### When NOT to use `runAfterTransitions`
+
+If you are not waiting for any of the tracked events (navigation, modal, keyboard), adding `runAfterTransitions` is meaningless - TransitionTracker will have no active transitions and the callback will fire synchronously in the same tick. For example, scroll events, layout animations, or Lottie playback are **not** tracked, so wrapping post-scroll logic in `runAfterTransitions` provides no benefit.
+
+### How `runAfterTransitions` works
+
+1. If there are ongoing transitions at the time of the call, the callback is enqueued and waits until all current transitions complete.
+2. If there are no ongoing transitions, the callback executes in the same tick.
+
+### The same-tick race condition
+
+Sometimes a transition starts in the same tick as the `runAfterTransitions` call. Because TransitionTracker hasn't registered the transition yet, the callback fires immediately - before the transition even begins.
+
+To fix this, pass the `waitForUpcomingTransition` flag along with the callback. This tells TransitionTracker to wait for a transition that hasn't started yet, ensuring the callback truly runs after the transition completes.
+
+> **Important:** `waitForUpcomingTransition` waits up to 1 second for a transition to begin. If no transition starts within that window, the callback fires anyway — effectively acting as a 1-second timeout. When using this flag, always make sure that TransitionTracker actually picks up the transition (i.e. the transition is registered within the 1-second window). Otherwise you're not waiting for a real transition, just adding an arbitrary delay.
 
 ## How
 The migration is split into 9 issues. Current status of the migration can be found in the parent Github issue [here](https://github.com/Expensify/App/issues/71913). 
diff --git a/cspell.json b/cspell.json
index 8f866b8f6afb..80ef1951f2c2 100644
--- a/cspell.json
+++ b/cspell.json
@@ -203,6 +203,8 @@
         "Marqeta",
         "McAfee",
         "Michelina",
+        "Melvin",
+        "MelvinBot",
         "Menlo",
         "Microtransaction",
         "Miniwarehouses",
diff --git a/docs/articles/expensify-classic/connections/VAT-IT.md b/docs/articles/expensify-classic/connections/VAT-IT.md
index 29465eaeb874..f55b6e7d6e9f 100644
--- a/docs/articles/expensify-classic/connections/VAT-IT.md
+++ b/docs/articles/expensify-classic/connections/VAT-IT.md
@@ -27,13 +27,13 @@ Businesses can reclaim VAT on various expenses, including:
 
 # How VAT Refunds Work
 
-VAT refund regulations vary by country and expense type, making the process complex. Global VaTax simplifies this by handling:
+VAT refund regulations vary by country and expense type, making the process complex. VAT IT simplifies this by handling:
 
 - VAT analysis and calculation  
 - Expense classification based on VAT eligibility  
 - Report preparation and submission to tax authorities  
 
-By syncing Expensify with Global VaTax, businesses can automate VAT reporting and reclaim eligible expenses efficiently.
+By syncing Expensify with VAT IT, businesses can automate VAT reporting and reclaim eligible expenses efficiently.
 
 ---
 
@@ -52,6 +52,6 @@ Once VAT IT prepares your VAT reclaim documents in the required languages, they
 
 # Tracking Your VAT Reclaim
 
-After submission, you can monitor the progress of your VAT reclaim via the **Submission Analysis Report** in Global VaTax.
+After submission, you can monitor the progress of your VAT reclaim via the **Submission Analysis Report** in VAT IT.
 
 By integrating Expensify with VAT IT, businesses can maximize VAT recovery while reducing administrative burden.
diff --git a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
index 5ccfe82e069b..2ce67abacb34 100644
--- a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
+++ b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
@@ -28,15 +28,19 @@ If you haven’t set up a feed yet, learn how to set one up:
 3. Select the card connection name. 
 4. Click **Assign card** on the card you want to assign. 
 5. Enter the assignee's name, email address, or phone number. 
-6. Review the details and click **Assign card** to finalize the assignment.
+6. If needed, update the **Transaction start date** to choose the date from which Expensify starts importing transactions for the card.
+7. Click **Assign card** to finalize the assignment.
 
 ---
 
 ## What happens after you assign company cards
 
  - Posted transactions from the assigned card import automatically into the member's account as expenses.
+ - Expensify imports transactions from the **Transaction start date** onward.
  - The imported company card expenses are added to reports and submitted according to Workspace rules.
 
+---
+
 # FAQ
 
 ## Can I assign a company card to someone who is not a member of the Workspace? 
@@ -50,3 +54,7 @@ Yes. A member can have multiple company cards assigned. Each card’s transactio
 ## Can members unassign their own company cards?
 
 No. Only Workspace Admins and their Copilots can assign or reassign company cards.
+
+## Can I change the transaction start date on an assigned card?
+
+Yes. You can update the **Transaction start date** at any time from the assigned card's details. The **Transaction start date** determines the date from which Expensify imports transactions for the card.
diff --git a/docs/articles/new-expensify/connections/quickbooks-online/Configure-Quickbooks-Online.md b/docs/articles/new-expensify/connections/quickbooks-online/Configure-Quickbooks-Online.md
index b7d71247a78b..1c55091863b7 100644
--- a/docs/articles/new-expensify/connections/quickbooks-online/Configure-Quickbooks-Online.md
+++ b/docs/articles/new-expensify/connections/quickbooks-online/Configure-Quickbooks-Online.md
@@ -75,8 +75,8 @@ To manage automation and other connection preferences:
 - **Sync reimbursed reports**:
   - If marked as paid in QuickBooks Online, the report will show as reimbursed in Expensify
   - If reimbursed via ACH in Expensify, the status will sync to paid in QuickBooks
-- **QuickBooks bill payment account**: Select where paid expense reports are stored
-- **QuickBooks invoice collections account**: Select where paid invoices are stored
+- **QuickBooks bill payment account**: Select where payments for expense reports are recorded
+- **QuickBooks invoice collections account**: Select where payments for invoices are recorded
 
 ---
 
diff --git a/docs/articles/new-expensify/domains/Domain-Migration.md b/docs/articles/new-expensify/domains/Domain-Migration.md
index 04f7247bc12d..7d06e6adbdcc 100644
--- a/docs/articles/new-expensify/domains/Domain-Migration.md
+++ b/docs/articles/new-expensify/domains/Domain-Migration.md
@@ -21,7 +21,7 @@ This is the recommended approach when possible.
 
 Concierge can typically perform an automatic Domain Migration if:
 
-- The old domain or new domain is verified
+- The old domain is verified
 - Email addresses match a 1:1 format, such as `name@olddomain.com` to `name@newdomain.com`
 - Members have not already created separate accounts under the new email address
 
@@ -65,7 +65,8 @@ Yes. If done correctly, members keep their full expense history, reports, and ap
 
 ## Do I need to verify the new domain before migrating?
 
-Yes. You must claim and verify the new domain before transferring domain control or updating member login emails.
+- If you are migrating your domain automatically with assistance from Concierge, you will not need to verify the new domain. It is preferred that you do not add or verify the new domain in Expensify.
+- If you are migrating your domain manually, you will need to verify the new domain.
 
 ## What happens to the Expensify Card during Domain Migration?
 
diff --git a/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md b/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md
index 819b9d95edf9..dd39d268f9c1 100644
--- a/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md
+++ b/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md
@@ -104,9 +104,9 @@ Filters help you narrow down expenses or reports so you can find exactly what yo
 
 You can filter your **expenses** and **reports** using dropdowns, search bars, and chips. 
 
-- **Expenses:** can be filtered by `Date`, `Merchant`, `Category`, `Tag`, `Amount`, `Reimbursable`, `Billable`, `Status` (e.g. Unreported, Deleted)
+- **Expenses:** can be filtered by `Date`, `Merchant`, `Category`, `Tag`, `Amount`, `Reimbursable`, `Billable`, `Status` (e.g. Unreported, Deleted), and `Exported to`.
 
-- **Reports**: can be filtered by `Submitter`, `Workspace`, `Report Status` (e.g. Draft, Outstanding, Approved, Paid), `Date`
+- **Reports**: can be filtered by `Submitter`, `Workspace`, `Report Status` (e.g. Draft, Outstanding, Approved, Paid), `Date`, and `Exported to`.
 
 To view other available filters, click into the **search box** on the **Spend** page while viewing **Reports** or **Expenses** under **Explore**.
 
diff --git a/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md b/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
index e17e44e77517..b69b1547a41f 100644
--- a/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
+++ b/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
@@ -38,16 +38,12 @@ You'll receive the exported CSV file in a message from Concierge.
 
 ## What export templates can I choose from? 
 
-Expensify offers pre-built export templates, or you can build your own custom export template. All available templates will appear in the menu when you export an expense. 
+Expensify offers pre-built export templates, or you can build your own custom export template. 
 
    - **Basic export** - Essential fields including date, amount, merchant, category, and receipt URL.
    - **All Data - expense level** - One row per expense with all available data fields.
-   - **custom templates** - Any custom template created by you or your Workspace Admin, if available.
-
    - **Custom templates** - Any custom template created by you or your Workspace Admin, if available.
 
-**Note** Currently, it's not possible to build custom export templates on New Expensify, they can only be created on Expensify Classic. However, once built they will be available on New Expensify when exporting expenses. [Learn how to build a custom export template in Expensify Classic](/articles/expensify-classic/spending-insights/Export-Expenses-And-Reports#create-a-custom-export-template).  
-
 ## Where do I find the exported file?
 
 For the Basic Export template, the file downloads directly to your device. For all other templates, Concierge sends the file to you in a direct message. Open your Concierge chat in the **Inbox** to find it.
@@ -58,8 +54,6 @@ If your Workspace Admin has created custom export templates, you can select one
 
 ## Why don't I see certain export templates?
 
-Report-level templates (such as All Data - Report Level Export) only appear when exporting from **Spend > Reports** page with full reports selected. When exporting individual expenses from the Expenses page, only expense-level templates are available.
-
 If all selected expenses are deleted, only the **Basic export** template is available. Other export templates require a report, and deleted expenses are not associated with any report.
 
 ## The data looks wrong in Excel. How can I fix it?
diff --git a/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md b/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md
index 13f38e6c5ed3..f06cbb0880b4 100644
--- a/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md
+++ b/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md
@@ -77,6 +77,7 @@ You can use the following operators to filter reports:
 - `report-id:` – unique report reference
 - `status:` – draft, outstanding, approved, paid, done
 - `submitted:` / `approved:` / `paid:` / `exported:` – supports absolute or relative dates, and comparisons for date ranges (e.g., `submitted>=2024-01-01 submitted<=2024-01-31`)
+- `exported-to:` – filter by where reports or expenses were exported, such as a connected accounting integration.
 - `title:` – report title
 - `total:` – total amount with relative comparisons
 - `withdrawn:` – ACH withdrawal date
@@ -84,7 +85,7 @@ You can use the following operators to filter reports:
 - `action:` – blocking report action, e.g. `action:approve`
 
 **Example query:**
-`status:paid exported<=2026-01-01`
+`status:paid exported<=2026-01-01 exported-to:xero`
 
 ---
 
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index f21fb37f5600..785a864e6500 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -23,7 +23,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>9.4.5</string>
+	<string>9.4.6</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleURLTypes</key>
@@ -44,7 +44,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.0</string>
+	<string>9.4.6.0</string>
 	<key>FullStory</key>
 	<dict>
 		<key>OrgId</key>
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index f0541fc79c1c..e721b9d49276 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -11,9 +11,9 @@
 	<key>CFBundleName</key>
 	<string>$(PRODUCT_NAME)</string>
 	<key>CFBundleShortVersionString</key>
-	<string>9.4.5</string>
+	<string>9.4.6</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.0</string>
+	<string>9.4.6.0</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionPointIdentifier</key>
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 1d385f71f0f0..480cdc510747 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -4088,7 +4088,7 @@ PODS:
     - ReactCommon/turbomodule/core
     - SocketRocket
     - Yoga
-  - RNSVG (15.12.1):
+  - RNSVG (15.15.5):
     - boost
     - DoubleConversion
     - fast_float
@@ -4114,10 +4114,10 @@ PODS:
     - ReactCodegen
     - ReactCommon/turbomodule/bridging
     - ReactCommon/turbomodule/core
-    - RNSVG/common (= 15.12.1)
+    - RNSVG/common (= 15.15.5)
     - SocketRocket
     - Yoga
-  - RNSVG/common (15.12.1):
+  - RNSVG/common (15.15.5):
     - boost
     - DoubleConversion
     - fast_float
@@ -4808,7 +4808,7 @@ SPEC CHECKSUMS:
   GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
   GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
   GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa
-  hermes-engine: c57209f580d9916632aeb0aa3851b1b90b47859f
+  hermes-engine: a0c087309de5ae9b2297a2cd8acfa9c53de099ee
   libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
   libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
   libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
@@ -4938,7 +4938,7 @@ SPEC CHECKSUMS:
   RNScreens: 2b6107925ee4e14a9b2eb0dfb52fe25223aa64d7
   RNSentry: f73f4da92e4c20841ab16e1fa22fc289bc2f9f4e
   RNShare: 1c1fde2c4134b9cf220ffebbd6df9c414036d382
-  RNSVG: 74eb75bd44d62ba9969941e80d8f9832971c681f
+  RNSVG: 14e21dacbded6cfa51becd6076c5921aa52a6992
   RNWorklets: 165079e6aa8caad7a05156ec2161fd4c52f9b745
   SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
   SDWebImageAVIFCoder: afe194a084e851f70228e4be35ef651df0fc5c57
diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist
index 44d8056abf00..bef8c163e2df 100644
--- a/ios/ShareViewController/Info.plist
+++ b/ios/ShareViewController/Info.plist
@@ -11,9 +11,9 @@
 	<key>CFBundleName</key>
 	<string>$(PRODUCT_NAME)</string>
 	<key>CFBundleShortVersionString</key>
-	<string>9.4.5</string>
+	<string>9.4.6</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.0</string>
+	<string>9.4.6.0</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionAttributes</key>
diff --git a/knip.json b/knip.json
index 2df7e9791c2d..1f6121995c89 100644
--- a/knip.json
+++ b/knip.json
@@ -28,7 +28,7 @@
                 ".storybook/**/*.{js,ts,tsx}",
                 ".github/actions/javascript/**/*.ts"
             ],
-            "ignore": [".github/actions/**/index.js", "tests/perf-test/**", "web/snippets/gib.js"],
+            "ignore": [".github/actions/**/index.js", "tests/perf-test/**", "web/snippets/gib.js", "src/libs/actions/connections/FinancialForce.ts"],
             "eslint": {
                 "config": ["config/eslint/eslint.config.mjs", "eslint.changed.config.mjs"]
             },
diff --git a/package-lock.json b/package-lock.json
index 620ab9bee353..c66c94d2fc9b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-0",
+  "version": "9.4.6-0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "new.expensify",
-      "version": "9.4.5-0",
+      "version": "9.4.6-0",
       "hasInstallScript": true,
       "license": "MIT",
       "workspaces": [
@@ -120,7 +120,7 @@
         "react-native-localize": "^3.5.4",
         "react-native-nitro-modules": "0.35.0",
         "react-native-nitro-sqlite": "9.6.0",
-        "react-native-onyx": "3.0.80",
+        "react-native-onyx": "3.0.83",
         "react-native-pager-view": "8.0.0",
         "react-native-pdf": "7.0.2",
         "react-native-permissions": "^5.4.0",
@@ -132,7 +132,7 @@
         "react-native-safe-area-context": "5.6.2",
         "react-native-screens": "4.25.0",
         "react-native-share": "11.0.2",
-        "react-native-svg": "15.12.1",
+        "react-native-svg": "15.15.5",
         "react-native-tab-view": "^4.3.0",
         "react-native-url-polyfill": "^2.0.0",
         "react-native-view-shot": "5.1.0",
@@ -243,7 +243,7 @@
         "dotenv": "^16.0.3",
         "eslint": "^9.36.0",
         "eslint-config-airbnb-typescript": "^18.0.0",
-        "eslint-config-expensify": "3.0.2",
+        "eslint-config-expensify": "3.0.3",
         "eslint-config-prettier": "^9.1.0",
         "eslint-plugin-file-progress": "3.0.1",
         "eslint-plugin-jest": "^29.0.1",
@@ -23200,14 +23200,13 @@
       }
     },
     "node_modules/eslint-config-expensify": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-3.0.2.tgz",
-      "integrity": "sha512-ulH1Gl3Uu2fh0E918Rt2R76nMidY1BuxezBBtT20+v2K8O/bFs5v83oX1cwvg3Kz97anhf64aqpA2h2KIG8p9w==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-3.0.3.tgz",
+      "integrity": "sha512-xPsrTYCE/6AthZ5rIyXCh5HjNdUXNrDnfpz3AoUmbepTAa6XS51ulZjuyoyGnAfy092RLuKi2dXgOZLmkHN1CA==",
       "dev": true,
       "license": "ISC",
       "dependencies": {
         "@babel/eslint-parser": "^7.28.4",
-        "@lwc/eslint-plugin-lwc": "^3.2.0",
         "@typescript-eslint/parser": "^8.44.1",
         "@typescript-eslint/utils": "^8.44.1",
         "confusing-browser-globals": "^1.0.11",
@@ -35673,9 +35672,9 @@
       }
     },
     "node_modules/react-native-onyx": {
-      "version": "3.0.80",
-      "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-3.0.80.tgz",
-      "integrity": "sha512-rXcHgLi0V7LkkPsim7P+ULQKHCWzWqER+Hx4fDmt+omwtVD3n0LpuV63Fq91/g8cEl6PT4okmYseMVDUUSQPLA==",
+      "version": "3.0.83",
+      "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-3.0.83.tgz",
+      "integrity": "sha512-/OIwvQeXkVaKNsdHWbS1T/16o0iWOlX5KOMF6USKq3ePRVfhBzEOczNgtchAZ5MDStqnZMLNbOsTLwFjLJu56w==",
       "license": "MIT",
       "dependencies": {
         "ascii-table": "0.0.9",
@@ -35942,14 +35941,13 @@
       }
     },
     "node_modules/react-native-svg": {
-      "version": "15.12.1",
-      "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.12.1.tgz",
-      "integrity": "sha512-vCuZJDf8a5aNC2dlMovEv4Z0jjEUET53lm/iILFnFewa15b4atjVxU6Wirm6O9y6dEsdjDZVD7Q3QM4T1wlI8g==",
+      "version": "15.15.5",
+      "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.15.5.tgz",
+      "integrity": "sha512-L4go5jA+GWutdJ/JucuN20cjAbMg1HmMtAP+wZ+3JLCf6Jd0bhXQHxciRP/AQm/FlrIEZwkMcHNZP+FXAiic0w==",
       "license": "MIT",
       "dependencies": {
         "css-select": "^5.1.0",
-        "css-tree": "^1.1.3",
-        "warn-once": "0.1.1"
+        "css-tree": "^1.1.3"
       },
       "peerDependencies": {
         "react": "*",
diff --git a/package.json b/package.json
index a6238f2779c4..f6370118ed66 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-0",
+  "version": "9.4.6-0",
   "author": "Expensify, Inc.",
   "homepage": "https://new.expensify.com",
   "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
@@ -193,7 +193,7 @@
     "react-native-localize": "^3.5.4",
     "react-native-nitro-modules": "0.35.0",
     "react-native-nitro-sqlite": "9.6.0",
-    "react-native-onyx": "3.0.80",
+    "react-native-onyx": "3.0.83",
     "react-native-pager-view": "8.0.0",
     "react-native-pdf": "7.0.2",
     "react-native-permissions": "^5.4.0",
@@ -205,7 +205,7 @@
     "react-native-safe-area-context": "5.6.2",
     "react-native-screens": "4.25.0",
     "react-native-share": "11.0.2",
-    "react-native-svg": "15.12.1",
+    "react-native-svg": "15.15.5",
     "react-native-tab-view": "^4.3.0",
     "react-native-url-polyfill": "^2.0.0",
     "react-native-view-shot": "5.1.0",
@@ -316,7 +316,7 @@
     "dotenv": "^16.0.3",
     "eslint": "^9.36.0",
     "eslint-config-airbnb-typescript": "^18.0.0",
-    "eslint-config-expensify": "3.0.2",
+    "eslint-config-expensify": "3.0.3",
     "eslint-config-prettier": "^9.1.0",
     "eslint-plugin-file-progress": "3.0.1",
     "eslint-plugin-jest": "^29.0.1",
diff --git a/patches/react-native-draggable-flatlist/details.md b/patches/react-native-draggable-flatlist/details.md
index 8afd4dc971c9..0f72087f6309 100644
--- a/patches/react-native-draggable-flatlist/details.md
+++ b/patches/react-native-draggable-flatlist/details.md
@@ -14,3 +14,11 @@
 - Upstream PR/issue: https://github.com/computerjazz/react-native-draggable-flatlist/pull/544
 - E/App issue: 🛑
 - PR Introducing Patch: [#55066](https://github.com/Expensify/App/pull/55066)
+
+
+### [react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch](react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch)
+
+- Reason: On iOS, `scrollToOffset({animated: true})` does not emit intermediate `onScroll` events, so the `scrollOffset` shared value never updates mid-scroll. This blocks the autoscroll feedback loop (`hasScrolledToTarget` stays false), preventing waypoint reordering beyond the visible viewport. The fix manually advances `scrollOffset` after each `scrollToOffset` call to keep the loop alive.
+- Upstream PR/issue: https://github.com/computerjazz/react-native-draggable-flatlist/issues/509
+- E/App issue: [#87362](https://github.com/Expensify/App/issues/87362)
+- PR Introducing Patch: [#90617](https://github.com/Expensify/App/pull/90617)
diff --git a/patches/react-native-draggable-flatlist/react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch b/patches/react-native-draggable-flatlist/react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch
new file mode 100644
index 000000000000..4e331c5b7383
--- /dev/null
+++ b/patches/react-native-draggable-flatlist/react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch
@@ -0,0 +1,13 @@
+diff --git a/node_modules/react-native-draggable-flatlist/src/hooks/useAutoScroll.tsx b/node_modules/react-native-draggable-flatlist/src/hooks/useAutoScroll.tsx
+index 4e30bca..b1a2f3e 100644
+--- a/node_modules/react-native-draggable-flatlist/src/hooks/useAutoScroll.tsx
++++ b/node_modules/react-native-draggable-flatlist/src/hooks/useAutoScroll.tsx
+@@ -89,6 +89,8 @@ export function useAutoScroll() {
+   function scrollToInternal(offset: number) {
+     if (flatlistRef && "current" in flatlistRef) {
+       flatlistRef.current?.scrollToOffset({ offset, animated: true });
++      // Manually advance scrollOffset so the autoscroll feedback loop is not blocked on iOS.
++      scrollOffset.value = offset;
+     }
+   }
+
diff --git a/patches/react-native/details.md b/patches/react-native/details.md
index 4d5f5e2dc67c..58b04ce0b32e 100644
--- a/patches/react-native/details.md
+++ b/patches/react-native/details.md
@@ -284,3 +284,11 @@
 - Upstream PR/issue: https://github.com/facebook/react-native/issues/53128
 - E/App issue: https://github.com/Expensify/App/issues/91292
 - PR introducing patch: https://github.com/Expensify/App/pull/91736
+
+
+### [react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch](react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch)
+
+- Reason: Fixes a fatal iOS crash (APP-8BM) in HybridApp where `RCTNetworking`'s default URL-request-handler provider builds its handler list using an Objective-C array literal (`@[...]`) with `[moduleRegistry moduleForName:"BlobModule"]` at index 3. During OldDot↔NewDot bridge transitions, the `__weak _turboModuleRegistry` in `RCTModuleRegistry` is zeroed by ARC at the start of `TurboModuleManager` dealloc — before `[RCTNetworking invalidate]` clears the handler cache — leaving a window where a concurrent in-flight network request calls `prioritizedHandlers`, finds the cache empty, and tries to rebuild it with a nil `BlobModule`. Since `@[…]` compiles to `+[NSArray arrayWithObjects:count:]` which raises `NSInvalidArgumentException` on any nil element, the crash is fatal. The fix replaces the literal with an `NSMutableArray` built from the three always-non-nil handlers (`RCTHTTPRequestHandler`, `RCTDataRequestHandler`, `RCTFileRequestHandler`) and conditionally appends `BlobModule` only when the registry lookup is non-nil, turning a guaranteed crash into a graceful "no blob handler for this window".
+- Upstream PR/issue: 🛑
+- E/App issue: https://github.com/Expensify/App/issues/92413
+- PR introducing patch: https://github.com/Expensify/App/pull/92918
\ No newline at end of file
diff --git a/patches/react-native/react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch b/patches/react-native/react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch
new file mode 100644
index 000000000000..d0a50ce8c581
--- /dev/null
+++ b/patches/react-native/react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch
@@ -0,0 +1,24 @@
+diff --git a/node_modules/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm b/node_modules/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm
+index fabfff3..cefa0fa 100644
+--- a/node_modules/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm
++++ b/node_modules/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm
+@@ -103,11 +103,16 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled)
+         initWithHandlersProvider:^NSArray<id<RCTURLRequestHandler>> *(RCTModuleRegistry *moduleRegistry) {
+           NSArray *URLRequestHandlerModules =
+               extractModuleConformingToProtocol(moduleRegistry, @protocol(RCTURLRequestHandler));
+-          return [@[
++          NSMutableArray<id<RCTURLRequestHandler>> *defaultHandlers = [NSMutableArray arrayWithObjects:
+             [RCTHTTPRequestHandler new],
+             [RCTDataRequestHandler new],
+             [RCTFileRequestHandler new],
+-            [moduleRegistry moduleForName:"BlobModule"],
+-          ] arrayByAddingObjectsFromArray:URLRequestHandlerModules];
++            nil
++          ];
++          id blobModule = [moduleRegistry moduleForName:"BlobModule"];
++          if (blobModule != nil) {
++            [defaultHandlers addObject:blobModule];
++          }
++          return [defaultHandlers arrayByAddingObjectsFromArray:URLRequestHandlerModules];
+         }];
+   }
diff --git a/rock.config.mjs b/rock.config.mjs
index 3f441f1ac5a3..fd354e8f6832 100644
--- a/rock.config.mjs
+++ b/rock.config.mjs
@@ -22,7 +22,7 @@ export default {
         android: platformAndroid({sourceDir: isHybrid ? './Mobile-Expensify/Android' : './android'}),
     },
     fingerprint: {
-        extraSources: ['android/gradle.properties', 'ios/Podfile', 'scripts/compute-patches-hash.sh'],
+        extraSources: ['android/gradle.properties', 'ios/Podfile', 'scripts/compute-patches-hash.sh', 'patches', ...(isHybrid ? ['Mobile-Expensify/patches'] : [])],
         env: ['USE_WEB_PROXY', 'PUSHER_DEV_SUFFIX', 'SECURE_NGROK_URL', 'NGROK_URL', 'USE_NGROK', 'FORCE_NATIVE_BUILD'],
         ignorePaths: ['Mobile-Expensify/Android/assets/app/shared/bundle.js'],
     },
diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 93e47db3b810..23dcba5a2b1f 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -259,6 +259,7 @@ const CONST = {
     COMPOSER_FOCUS_DELAY: 150,
     MAX_TRANSITION_DURATION_MS: 1000,
     MAX_TRANSITION_START_WAIT_MS: 1000,
+    EXPENSE_REPORT_DELETE_DELAY_MS: 300,
     ANIMATION_DIRECTION: {
         IN: 'in',
         OUT: 'out',
@@ -369,6 +370,8 @@ const CONST = {
 
     API_TRANSACTION_TAG_MAX_LENGTH: 255,
 
+    TRANSACTION_TAG_AND_CATEGORY_PICKER_MAX_TITLE_LINES: 5,
+
     AUTO_AUTH_STATE: {
         NOT_STARTED: 'not-started',
         SIGNING_IN: 'signing-in',
@@ -1645,6 +1648,7 @@ const CONST = {
                 MARK_REIMBURSED_FROM_INTEGRATION: 'ACTIONMARKEDREIMBURSEDFROMINTEGRATION', // OldDot Action
                 MERGED_WITH_CASH_TRANSACTION: 'MERGEDWITHCASHTRANSACTION',
                 MODIFIED_EXPENSE: 'MODIFIEDEXPENSE',
+                CONCIERGE_AUTO_MATCH_VENDOR: 'CONCIERGEAUTOMATCHVENDOR',
                 MOVED: 'MOVED',
                 MOVED_TRANSACTION: 'MOVEDTRANSACTION',
                 UNREPORTED_TRANSACTION: 'UNREPORTEDTRANSACTION',
@@ -1742,6 +1746,7 @@ const CONST = {
                     UPDATE_AUTO_REPORTING_FREQUENCY: 'POLICYCHANGELOG_UPDATE_AUTOREPORTING_FREQUENCY',
                     UPDATE_BUDGET: 'POLICYCHANGELOG_UPDATE_BUDGET',
                     UPDATE_CATEGORY: 'POLICYCHANGELOG_UPDATE_CATEGORY',
+                    UPDATE_CATEGORY_TAX_RATE: 'POLICYCHANGELOG_UPDATE_CATEGORY_TAX_RATE',
                     UPDATE_CATEGORIES: 'POLICYCHANGELOG_UPDATE_CATEGORIES',
                     UPDATE_CURRENCY: 'POLICYCHANGELOG_UPDATE_CURRENCY',
                     UPDATE_CUSTOM_UNIT: 'POLICYCHANGELOG_UPDATE_CUSTOM_UNIT',
@@ -1962,6 +1967,7 @@ const CONST = {
         MESSAGE_KEY: {
             WAITING_TO_ADD_TRANSACTIONS: 'waitingToAddTransactions',
             WAITING_TO_SUBMIT: 'waitingToSubmit',
+            WAITING_TO_MARK_AS_DONE: 'waitingToMarkAsDone',
             NO_FURTHER_ACTION: 'noFurtherAction',
             WAITING_FOR_SUBMITTER_ACCOUNT: 'waitingForSubmitterAccount',
             WAITING_FOR_AUTOMATIC_SUBMIT: 'waitingForAutomaticSubmit',
@@ -2328,6 +2334,11 @@ const CONST = {
         GSD: 'gsd',
         DEFAULT: 'default',
     },
+    INBOX_TAB: {
+        ALL: 'all',
+        TODO: 'todo',
+        UNREAD: 'unread',
+    },
     THEME: {
         DEFAULT: 'system',
         FALLBACK: 'dark',
@@ -2995,6 +3006,7 @@ const CONST = {
         REPORT_EXPORT_STATUS: 'reportExportStatus',
         TAX_NON_BILLABLE: 'taxNonBillable',
         EXPORT_FOREIGN_CURRENCY: 'exportForeignCurrency',
+        COMPANY: 'company',
     },
 
     CERTINIA_EXPORT_STATUS: {
@@ -3089,6 +3101,7 @@ const CONST = {
             MANAGER: 'manager',
             CUSTOM: 'custom',
         },
+        COOKIE_CLEAR_DELAY_MS: 500,
         SYNC_STATUS: {
             SYNCING: 'SYNCING',
             DONE: 'DONE',
@@ -3683,6 +3696,8 @@ const CONST = {
 
     IOU: {
         MAX_RECENT_REPORTS_TO_SHOW: 5,
+        MAX_RECENT_ATTENDEES: 40,
+
         // This will guranatee that the quantity input will not exceed 9,007,199,254,740,991 (Number.MAX_SAFE_INTEGER).
         QUANTITY_MAX_LENGTH: 12,
         // This is the transactionID used when going through the create expense flow so that it mimics a real transaction (like the edit flow)
@@ -3967,6 +3982,7 @@ const CONST = {
             MAKE_MEMBER: 'makeMember',
             MAKE_ADMIN: 'makeAdmin',
             MAKE_AUDITOR: 'makeAuditor',
+            MAKE_CARD_ADMIN: 'makeCardAdmin',
         },
         BULK_ACTION_TYPES: {
             DELETE: 'delete',
@@ -3981,7 +3997,6 @@ const CONST = {
             ARE_DISTANCE_RATES_ENABLED: 'areDistanceRatesEnabled',
             ARE_WORKFLOWS_ENABLED: 'areWorkflowsEnabled',
             ARE_REPORT_FIELDS_ENABLED: 'areReportFieldsEnabled',
-            ARE_INVOICE_FIELDS_ENABLED: 'areInvoiceFieldsEnabled',
             ARE_CONNECTIONS_ENABLED: 'areConnectionsEnabled',
             ARE_RECEIPT_PARTNERS_ENABLED: 'receiptPartners',
             ARE_COMPANY_CARDS_ENABLED: 'areCompanyCardsEnabled',
@@ -4035,7 +4050,6 @@ const CONST = {
             AUTOREPORTING_FREQUENCY: 'autoReportingFrequency',
             AUTOREPORTING_OFFSET: 'autoReportingOffset',
             GENERAL_SETTINGS: 'generalSettings',
-            ADD_AGENT: 'addAgent',
         },
         EXPENSE_REPORT_RULES: {
             PREVENT_SELF_APPROVAL: 'preventSelfApproval',
@@ -4282,6 +4296,12 @@ const CONST = {
         FAKE_P2P_ID: '_FAKE_P2P_ID_',
         MILES_TO_KILOMETERS: 1.609344,
         KILOMETERS_TO_MILES: 0.621371,
+        RATE_STATUS: {
+            ACTIVE: 'active',
+            FUTURE: 'future',
+            EXPIRED: 'expired',
+            INACTIVE: 'inactive',
+        },
         RATE_FIELD: {
             START_DATE: 'startDate',
             END_DATE: 'endDate',
@@ -7248,14 +7268,6 @@ const CONST = {
                 description: 'workspace.upgrade.reportFields.description' as const,
                 icon: 'Pencil',
             },
-            invoiceFields: {
-                id: 'invoiceFields' as const,
-                alias: 'invoice-fields',
-                name: 'Invoice Fields',
-                title: 'workspace.upgrade.invoiceFields.title' as const,
-                description: 'workspace.upgrade.invoiceFields.description' as const,
-                icon: 'Pencil',
-            },
             policyPreventMemberChangingTitle: {
                 id: 'policyPreventMemberChangingTitle' as const,
                 alias: 'policy-prevent-member-changing-title',
@@ -7429,12 +7441,12 @@ const CONST = {
                 description: 'workspace.upgrade.distanceRates.description' as const,
                 icon: 'CarIce',
             },
-            auditor: {
-                id: 'auditor' as const,
-                alias: 'auditor',
-                name: 'Auditor',
-                title: 'workspace.upgrade.auditor.title' as const,
-                description: 'workspace.upgrade.auditor.description' as const,
+            controlPolicyRoles: {
+                id: 'controlPolicyRoles' as const,
+                alias: 'control-policy-roles',
+                name: 'Control policy roles',
+                title: 'workspace.upgrade.controlPolicyRoles.title' as const,
+                description: 'workspace.upgrade.controlPolicyRoles.description' as const,
                 icon: 'BlueShield',
             },
             reports: {
@@ -7517,10 +7529,6 @@ const CONST = {
         LIST: 'dropdown',
         FORMULA: 'formula',
     },
-    REPORT_FIELD_TARGETS: {
-        EXPENSE: 'expense',
-        INVOICE: 'invoice',
-    },
 
     NAVIGATION_ACTIONS: {
         RESET: 'RESET',
@@ -7753,7 +7761,6 @@ const CONST = {
         HAS_FILTER_NEGATION: 'hasFilterNegation',
     },
     CHANGE_POLICY_TRAINING_MODAL: 'changePolicyModal',
-    AGENTS_WORKFLOWS_BANNER: 'agentsWorkflowsBanner',
     AGENTS_RULES_BANNER: 'agentsRulesBanner',
     SMART_BANNER_HEIGHT: 152,
 
@@ -7900,9 +7907,6 @@ const CONST = {
         HIGH_CONTRAST_MODE_SWITCHER: {
             TOGGLE: 'HighContrastModeSwitcher-Toggle',
         },
-        AGENTS_WORKFLOWS_BANNER: {
-            DISMISS: 'AgentsWorkflowsBanner-Dismiss',
-        },
         AGENTS_RULES_BANNER: {
             CTA: 'AgentsRulesBanner-CTA',
             DISMISS: 'AgentsRulesBanner-Dismiss',
@@ -8464,6 +8468,7 @@ const CONST = {
                 BULK_ACTIONS_DROPDOWN: 'WorkspaceTaxes-BulkActionsDropdown',
             },
             DISTANCE_RATES: {
+                ROW: 'WorkspaceDistanceRates-Row',
                 ADD_BUTTON: 'WorkspaceDistanceRates-AddButton',
                 MORE_DROPDOWN: 'WorkspaceDistanceRates-MoreDropdown',
                 BULK_ACTIONS_DROPDOWN: 'WorkspaceDistanceRates-BulkActionsDropdown',
@@ -8684,6 +8689,8 @@ const CONST = {
             DELEGATE_ITEM: 'SettingsSecurity-DelegateItem',
             DELEGATE_CHANGE_ACCESS: 'SettingsSecurity-DelegateChangeAccess',
             DELEGATE_REMOVE: 'SettingsSecurity-DelegateRemove',
+            DELEGATOR_ITEM: 'SettingsSecurity-DelegatorItem',
+            DELEGATOR_REMOVE: 'SettingsSecurity-DelegatorRemove',
         },
         SETTINGS_WALLET: {
             ADD_BANK_ACCOUNT: 'SettingsWallet-AddBankAccount',
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index f22984a038b1..4e43a9a5e2c4 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -172,6 +172,9 @@ const ONYXKEYS = {
     /** Contains the user preference for the LHN priority mode */
     NVP_PRIORITY_MODE: 'nvp_priorityMode',
 
+    /** Contains the user preference for the active inbox tab filter */
+    NVP_INBOX_TAB: 'nvp_inboxTab',
+
     /** Contains the users's block expiration (if they have one) */
     NVP_BLOCKED_FROM_CONCIERGE: 'nvp_private_blockedFromConcierge',
 
@@ -599,25 +602,6 @@ const ONYXKEYS = {
     /** Stores the information about currently edited advanced approval workflow */
     APPROVAL_WORKFLOW: 'approvalWorkflow',
 
-    /**
-     * Workflow saves the user committed while a freshly-created agent was still pending. Keyed
-     * by `${policyID}:${firstApproverEmail}`. WorkspaceWorkflowsPage overlays these entries on
-     * top of the regular workflows so the new agent shows up faded in the approver card, and
-     * a watcher fires the actual `updateApprovalWorkflow` once the agent gets its real email
-     * and clears the entry. This lets the admin "Save" before CREATE_AGENT resolves without
-     * the modal blocking on a `This field is required` validation error.
-     */
-    DEFERRED_AGENT_WORKFLOW_SAVES: 'deferredAgentWorkflowSaves',
-
-    /**
-     * Maps optimistic agent account IDs (randomly generated) to the real, server-assigned IDs returned
-     * by CREATE_AGENT. The server echoes this mapping in the response's `onyxData` (and queues
-     * it on the owner's account channel) so the WorkspaceWorkflowsPage and Edit Approvers
-     * reconciliation can swap the pending approver to the real agent without falling back to
-     * matching by prompt — which is ambiguous when multiple agents share the same prompt text.
-     */
-    OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING: 'optimisticAgentAccountIDMapping',
-
     /** Stores the user search value for persistence across the screens */
     ROOM_MEMBERS_USER_SEARCH_PHRASE: 'roomMembersUserSearchPhrase',
 
@@ -1214,6 +1198,7 @@ const ONYXKEYS = {
         TODOS: 'todos',
         RAM_ONLY_SORTED_REPORT_ACTIONS: 'sortedReportActions',
         OPEN_AND_SUBMITTED_REPORTS_BY_POLICY_ID: 'openAndSubmittedReportsByPolicyID',
+        FLAGGED_EXPENSES: 'flaggedExpenses',
     },
 
     /** Stores HybridApp specific state required to interoperate with OldDot */
@@ -1496,6 +1481,7 @@ type OnyxValuesMapping = {
     [ONYXKEYS.BETA_CONFIGURATION]: OnyxTypes.BetaConfiguration;
     [ONYXKEYS.NVP_MUTED_PLATFORMS]: Partial<Record<Platform, true>>;
     [ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf<typeof CONST.PRIORITY_MODE>;
+    [ONYXKEYS.NVP_INBOX_TAB]: ValueOf<typeof CONST.INBOX_TAB>;
     [ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE]: OnyxTypes.BlockedFromConcierge;
     [ONYXKEYS.QUEUE_FLUSHED_DATA]: AnyOnyxUpdate[];
     [ONYXKEYS.TRANSACTIONS_PENDING_3DS_REVIEW]: OnyxTypes.TransactionsPending3DSReview;
@@ -1639,8 +1625,6 @@ type OnyxValuesMapping = {
     [ONYXKEYS.NVP_PRIVATE_CANCELLATION_DETAILS]: OnyxTypes.CancellationDetails[];
     [ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE]: string;
     [ONYXKEYS.APPROVAL_WORKFLOW]: OnyxTypes.ApprovalWorkflowOnyx;
-    [ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES]: Record<string, OnyxTypes.DeferredAgentWorkflowSave>;
-    [ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING]: Record<string, number>;
     [ONYXKEYS.IMPORTED_SPREADSHEET]: OnyxTypes.ImportedSpreadsheet;
     [ONYXKEYS.IMPORTED_SPREADSHEET_MEMBER_DATA]: OnyxTypes.ImportedSpreadsheetMemberData[];
     [ONYXKEYS.IMPORTED_SPREADSHEET_MEMBER_ROLE]: ValueOf<typeof CONST.POLICY.ROLE>;
@@ -1707,6 +1691,7 @@ type OnyxDerivedValuesMapping = {
     [ONYXKEYS.DERIVED.TODOS]: OnyxTypes.TodosDerivedValue;
     [ONYXKEYS.DERIVED.RAM_ONLY_SORTED_REPORT_ACTIONS]: OnyxTypes.SortedReportActionsDerivedValue;
     [ONYXKEYS.DERIVED.OPEN_AND_SUBMITTED_REPORTS_BY_POLICY_ID]: OnyxTypes.OpenAndSubmittedReportsByPolicyIDDerivedValue;
+    [ONYXKEYS.DERIVED.FLAGGED_EXPENSES]: OnyxTypes.FlaggedExpensesDerivedValue;
 };
 
 type OnyxValues = OnyxValuesMapping & OnyxCollectionValuesMapping & OnyxFormValuesMapping & OnyxFormDraftValuesMapping & OnyxDerivedValuesMapping;
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index f8e65e8cc72b..03d6054d2a70 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -180,126 +180,6 @@ const DYNAMIC_ROUTES = {
         entryScreens: ['*'],
         getRoute: (accountID: number) => `avatar/${accountID}` as const,
     },
-    MONEY_REQUEST_STEP_TAX_RATE: {
-        path: 'money-request/tax-rate/:action/:iouType/:transactionID/:reportID?',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID?: string) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_RATE dynamic route');
-            }
-
-            return `money-request/tax-rate/${action as string}/${iouType as string}/${transactionID}${reportID ? `/${reportID}` : ''}` as const;
-        },
-    },
-    MONEY_REQUEST_STEP_TAX_AMOUNT: {
-        path: 'money-request/tax-amount/:action/:iouType/:transactionID/:reportID?',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID?: string) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_AMOUNT dynamic route');
-            }
-
-            return `money-request/tax-amount/${action as string}/${iouType as string}/${transactionID}${reportID ? `/${reportID}` : ''}` as const;
-        },
-    },
-    MONEY_REQUEST_STEP_CATEGORY: {
-        path: 'money-request/category/:action/:iouType/:transactionID/:reportID/:reportActionID?',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.MONEY_REQUEST.SPLIT_EXPENSE_EDIT,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, reportActionID?: string) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_CATEGORY dynamic route');
-            }
-
-            return `money-request/category/${action as string}/${iouType as string}/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}` as const;
-        },
-    },
-    MONEY_REQUEST_ATTENDEE: {
-        path: 'money-request/attendees/:action/:iouType/:transactionID/:reportID',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_ATTENDEE dynamic route');
-            }
-
-            return `money-request/attendees/${action as string}/${iouType as string}/${transactionID}/${reportID}` as const;
-        },
-    },
-    MONEY_REQUEST_ACCOUNTANT: {
-        path: 'money-request/accountant/:action/:iouType/:transactionID/:reportID',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.REPORT,
-            SCREENS.REPORT_DETAILS.DYNAMIC_ROOT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_ACCOUNTANT dynamic route');
-            }
-
-            return `money-request/accountant/${action as string}/${iouType as string}/${transactionID}/${reportID}` as const;
-        },
-    },
-    MONEY_REQUEST_UPGRADE: {
-        path: 'money-request/upgrade/:action/:iouType/:transactionID/:reportID/:upgradePath?',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.MONEY_REQUEST.SPLIT_EXPENSE_EDIT,
-            SCREENS.HOME,
-            SCREENS.INBOX,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-            SCREENS.SEARCH.ROOT,
-            SCREENS.SEARCH.TRANSACTIONS_CHANGE_REPORT_SEARCH_RHP,
-        ],
-        getRoute: (params: {action: IOUAction; iouType: IOUType; transactionID: string; reportID: string; upgradePath?: string; shouldSubmitExpense?: boolean}) => {
-            const {action, iouType, transactionID, reportID, upgradePath, shouldSubmitExpense} = params;
-            const upgradePathParam = upgradePath ? `/${upgradePath}` : '';
-            const basePath = `money-request/upgrade/${action as string}/${iouType as string}/${transactionID}/${reportID}${upgradePathParam}` as const;
-
-            if (shouldSubmitExpense) {
-                return `${basePath}?shouldSubmitExpense=true` as const;
-            }
-
-            return basePath;
-        },
-        queryParams: ['shouldSubmitExpense'],
-    },
     NEW_REPORT_WORKSPACE_SELECTION: {
         path: 'new-report-workspace-selection',
         entryScreens: ['*'],
@@ -342,6 +222,14 @@ const DYNAMIC_ROUTES = {
         path: 'certinia/advanced',
         entryScreens: [SCREENS.WORKSPACE.ACCOUNTING.ROOT],
     },
+    POLICY_ACCOUNTING_CERTINIA_REPORT_EXPORT_STATUS: {
+        path: 'certinia-report-status/select',
+        entryScreens: [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_EXPORT],
+    },
+    POLICY_ACCOUNTING_CERTINIA_COMPANY_SELECTOR: {
+        path: 'certinia/company',
+        entryScreens: [SCREENS.WORKSPACE.ACCOUNTING.ROOT],
+    },
     POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_VENDOR_SELECT: {
         path: 'vendor/select',
         entryScreens: [SCREENS.WORKSPACE.ACCOUNTING.DYNAMIC_NETSUITE_EXPORT_EXPENSES],
@@ -1427,14 +1315,11 @@ const ROUTES = {
     SETTINGS_AGENTS: 'settings/agents',
     SETTINGS_AGENTS_ADD: {
         route: 'settings/agents/new',
-        getRoute: ({policyID, workflowApproverEmail}: {policyID?: string; workflowApproverEmail?: string} = {}) => {
+        getRoute: ({policyID}: {policyID?: string} = {}) => {
             const params = new URLSearchParams();
             if (policyID) {
                 params.set('policyID', policyID);
             }
-            if (workflowApproverEmail) {
-                params.set('workflowApproverEmail', workflowApproverEmail);
-            }
             const query = params.toString();
             return `settings/agents/new${query ? `?${query}` : ''}` as const;
         },
@@ -1749,6 +1634,26 @@ const ROUTES = {
             return getUrlWithBackToParam(`${action as string}/${iouType as string}/amount/${transactionID}/${reportID}/${reportActionID ? `${reportActionID}/` : ''}${pageIndex}`, backTo);
         },
     },
+    MONEY_REQUEST_STEP_TAX_RATE: {
+        route: ':action/:iouType/taxRate/:transactionID/:reportID?',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_RATE route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/taxRate/${transactionID}/${reportID}`, backTo);
+        },
+    },
+    MONEY_REQUEST_STEP_TAX_AMOUNT: {
+        route: ':action/:iouType/taxAmount/:transactionID/:reportID?',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_AMOUNT route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/taxAmount/${transactionID}/${reportID}`, backTo);
+        },
+    },
     MONEY_REQUEST_STEP_CATEGORY_CREATE: {
         route: ':action/:iouType/category/new/:transactionID/:reportID/:reportActionID?',
         getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, reportActionID?: string, backTo = '') => {
@@ -1759,6 +1664,60 @@ const ROUTES = {
             return getUrlWithBackToParam(`${action as string}/${iouType as string}/category/new/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
         },
     },
+    MONEY_REQUEST_STEP_CATEGORY: {
+        route: ':action/:iouType/category/:transactionID/:reportID/:reportActionID?',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '', reportActionID?: string) => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_CATEGORY route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
+        },
+    },
+    MONEY_REQUEST_ATTENDEE: {
+        route: ':action/:iouType/attendees/:transactionID/:reportID',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_ATTENDEE route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/attendees/${transactionID}/${reportID}`, backTo);
+        },
+    },
+    MONEY_REQUEST_ACCOUNTANT: {
+        route: ':action/:iouType/accountant/:transactionID/:reportID',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_ACCOUNTANT route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/accountant/${transactionID}/${reportID}`, backTo);
+        },
+    },
+    MONEY_REQUEST_UPGRADE: {
+        route: ':action/:iouType/upgrade/:transactionID/:reportID/:upgradePath?',
+        getRoute: (params: {action: IOUAction; iouType: IOUType; transactionID: string; reportID: string; backTo?: string; shouldSubmitExpense?: boolean; upgradePath?: string}) => {
+            const {action, iouType, transactionID, reportID, backTo = '', shouldSubmitExpense = false, upgradePath} = params;
+            const upgradePathParam = upgradePath ? `/${upgradePath}` : '';
+            const baseURL = `${action as string}/${iouType as string}/upgrade/${transactionID}/${reportID}${upgradePathParam}` as const;
+
+            if (shouldSubmitExpense) {
+                return getUrlWithBackToParam(`${baseURL}?shouldSubmitExpense=${shouldSubmitExpense}` as const, backTo);
+            }
+
+            return getUrlWithBackToParam(baseURL, backTo);
+        },
+    },
+    MONEY_REQUEST_STEP_VENDOR: {
+        route: ':action/:iouType/vendor/:transactionID/:reportID/:reportActionID?',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, reportActionID?: string) => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_VENDOR route');
+            }
+
+            return `${action as string}/${iouType as string}/vendor/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}` as const;
+        },
+    },
     MONEY_REQUEST_STEP_DESTINATION: {
         route: ':action/:iouType/destination/:transactionID/:reportID',
         getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>
@@ -2353,11 +2312,7 @@ const ROUTES = {
     },
     WORKSPACE_WORKFLOWS_APPROVALS_EDIT: {
         route: 'workspaces/:policyID/workflows/approvals/:firstApproverEmail/edit',
-        getRoute: (policyID: string, firstApproverEmail: string, seedApproverEmail?: string, seedApproverAccountID?: number) =>
-            getUrlWithParams(`workspaces/${policyID}/workflows/approvals/${encodeURIComponent(firstApproverEmail)}/edit`, {
-                seedApproverEmail,
-                seedApproverAccountID: seedApproverAccountID !== undefined ? String(seedApproverAccountID) : undefined,
-            }),
+        getRoute: (policyID: string, firstApproverEmail: string) => `workspaces/${policyID}/workflows/approvals/${encodeURIComponent(firstApproverEmail)}/edit` as const,
     },
     WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM: {
         route: 'workspaces/:policyID/workflows/approvals/expenses-from',
@@ -2380,11 +2335,6 @@ const ROUTES = {
         route: 'workspaces/:policyID/workflows/approvals/over-limit-approver',
         getRoute: (policyID: string, approverIndex: number) => `workspaces/${policyID}/workflows/approvals/over-limit-approver?approverIndex=${approverIndex}` as const,
     },
-    WORKSPACE_WORKFLOWS_ADD_AGENT: {
-        route: 'workspaces/:policyID/workflows/add-agent',
-        getRoute: ({policyID, workflowApproverEmail}: {policyID: string; workflowApproverEmail?: string}) =>
-            getUrlWithParams(`workspaces/${policyID}/workflows/add-agent`, {workflowApproverEmail}),
-    },
     WORKSPACE_WORKFLOWS_PAYER: {
         route: 'workspaces/:policyID/workflows/payer',
         getRoute: (policyId: string) => `workspaces/${policyId}/workflows/payer` as const,
@@ -2428,35 +2378,6 @@ const ROUTES = {
         route: 'workspaces/:policyID/invoices/company-website',
         getRoute: (policyID: string) => `workspaces/${policyID}/invoices/company-website` as const,
     },
-    WORKSPACE_INVOICE_FIELDS_CREATE: {
-        route: 'workspaces/:policyID/invoices/newInvoiceField',
-        getRoute: (policyID: string) => `workspaces/${policyID}/invoices/newInvoiceField` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_SETTINGS: {
-        route: 'workspaces/:policyID/invoices/:reportFieldID/edit',
-        getRoute: (policyID: string, reportFieldID: string) => `workspaces/${policyID}/invoices/${encodeURIComponent(reportFieldID)}/edit` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_LIST_VALUES: {
-        route: 'workspaces/:policyID/invoices/listValues/:reportFieldID?',
-        getRoute: (policyID: string, reportFieldID?: string) => `workspaces/${policyID}/invoices/listValues/${reportFieldID ? encodeURIComponent(reportFieldID) : ''}` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_ADD_VALUE: {
-        route: 'workspaces/:policyID/invoices/addValue/:reportFieldID?',
-        getRoute: (policyID: string, reportFieldID?: string) => `workspaces/${policyID}/invoices/addValue/${reportFieldID ? encodeURIComponent(reportFieldID) : ''}` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_VALUE_SETTINGS: {
-        route: 'workspaces/:policyID/invoices/:valueIndex/:reportFieldID?',
-        getRoute: (policyID: string, valueIndex: number, reportFieldID?: string) =>
-            `workspaces/${policyID}/invoices/${valueIndex}/${reportFieldID ? encodeURIComponent(reportFieldID) : ''}` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_EDIT_VALUE: {
-        route: 'workspaces/:policyID/invoices/newInvoiceField/:valueIndex/edit',
-        getRoute: (policyID: string, valueIndex: number) => `workspaces/${policyID}/invoices/newInvoiceField/${valueIndex}/edit` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_EDIT_INITIAL_VALUE: {
-        route: 'workspaces/:policyID/invoices/:reportFieldID/edit/initialValue',
-        getRoute: (policyID: string, reportFieldID: string) => `workspaces/${policyID}/invoices/${encodeURIComponent(reportFieldID)}/edit/initialValue` as const,
-    },
     WORKSPACE_MEMBERS: {
         route: 'workspaces/:policyID/members',
         getRoute: (policyID: string | undefined) => {
@@ -4019,6 +3940,33 @@ const ROUTES = {
             return `workspaces/${policyID}/accounting/certinia/advanced` as const;
         },
     },
+    POLICY_ACCOUNTING_CERTINIA_TAGS_MAPPING: {
+        route: 'workspaces/:policyID/accounting/certinia/import/tags-mapping',
+        getRoute: (policyID: string | undefined) => {
+            if (!policyID) {
+                Log.warn('Invalid policyID is used to build the POLICY_ACCOUNTING_CERTINIA_TAGS_MAPPING route');
+            }
+            return `workspaces/${policyID}/accounting/certinia/import/tags-mapping` as const;
+        },
+    },
+    POLICY_ACCOUNTING_CERTINIA_REPORT_EXPORT_STATUS: {
+        route: 'workspaces/:policyID/accounting/certinia/export/report-status',
+        getRoute: (policyID: string | undefined) => {
+            if (!policyID) {
+                Log.warn('Invalid policyID is used to build the POLICY_ACCOUNTING_CERTINIA_REPORT_EXPORT_STATUS route');
+            }
+            return `workspaces/${policyID}/accounting/certinia/export/report-status` as const;
+        },
+    },
+    POLICY_ACCOUNTING_CERTINIA_COMPANY_SELECTOR: {
+        route: 'workspaces/:policyID/accounting/certinia/company',
+        getRoute: (policyID: string | undefined) => {
+            if (!policyID) {
+                Log.warn('Invalid policyID is used to build the POLICY_ACCOUNTING_CERTINIA_COMPANY_SELECTOR route');
+            }
+            return `workspaces/${policyID}/accounting/certinia/company` as const;
+        },
+    },
     ADD_EXISTING_EXPENSE: {
         route: 'search/r/:reportID/add-existing-expense/:backToReport?',
         getRoute: (reportID: string | undefined, backToReport?: string) => `search/r/${reportID}/add-existing-expense/${backToReport ?? ''}` as const,
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 6066e17d3967..cc9c10d594ad 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -373,9 +373,9 @@ const SCREENS = {
         STEP_CONFIRMATION: 'Money_Request_Step_Confirmation',
         STEP_CONFIRMATION_VERIFY_ACCOUNT: 'Money_Request_Step_Confirmation_Verify_Account',
         START: 'Money_Request_Start',
-        DYNAMIC_STEP_UPGRADE: 'Dynamic_Money_Request_Step_Upgrade',
+        STEP_UPGRADE: 'Money_Request_Step_Upgrade',
         STEP_AMOUNT: 'Money_Request_Step_Amount',
-        DYNAMIC_STEP_CATEGORY: 'Dynamic_Money_Request_Step_Category',
+        STEP_CATEGORY: 'Money_Request_Step_Category',
         STEP_CATEGORY_CREATE: 'Money_Request_Step_Category_Create',
         STEP_DATE: 'Money_Request_Step_Date',
         STEP_DESCRIPTION: 'Money_Request_Step_Description',
@@ -386,8 +386,9 @@ const SCREENS = {
         STEP_SCAN: 'Money_Request_Step_Scan',
         STEP_TAG: 'Money_Request_Step_Tag',
         STEP_WAYPOINT: 'Money_Request_Step_Waypoint',
-        DYNAMIC_STEP_TAX_AMOUNT: 'Dynamic_Money_Request_Step_Tax_Amount',
-        DYNAMIC_STEP_TAX_RATE: 'Dynamic_Money_Request_Step_Tax_Rate',
+        STEP_TAX_AMOUNT: 'Money_Request_Step_Tax_Amount',
+        STEP_TAX_RATE: 'Money_Request_Step_Tax_Rate',
+        STEP_VENDOR: 'Money_Request_Step_Vendor',
         RECEIPT_VIEW: 'Money_Request_Receipt_View',
         STEP_SEND_FROM: 'Money_Request_Step_Send_From',
         STEP_COMPANY_INFO: 'Money_Request_Step_Company_Info',
@@ -396,8 +397,8 @@ const SCREENS = {
         EDIT_WAYPOINT: 'Money_Request_Edit_Waypoint',
         RECEIPT: 'Money_Request_Receipt',
         STATE_SELECTOR: 'Money_Request_State_Selector',
-        DYNAMIC_STEP_ATTENDEES: 'Dynamic_Money_Request_Attendee',
-        DYNAMIC_STEP_ACCOUNTANT: 'Dynamic_Money_Request_Step_Accountant',
+        STEP_ATTENDEES: 'Money_Request_Attendee',
+        STEP_ACCOUNTANT: 'Money_Request_Accountant',
         STEP_DESTINATION: 'Money_Request_Destination',
         STEP_TIME: 'Money_Request_Time',
         STEP_SUBRATE: 'Money_Request_SubRate',
@@ -701,6 +702,9 @@ const SCREENS = {
             CERTINIA_EXPORT_DATE: 'Policy_Accounting_Certinia_Export_Date',
             CERTINIA_DEFAULT_VENDOR: 'Policy_Accounting_Certinia_Default_Vendor',
             CERTINIA_ADVANCED: 'Policy_Accounting_Certinia_Advanced',
+            CERTINIA_TAGS_MAPPING: 'Policy_Accounting_Certinia_Tags_Mapping',
+            CERTINIA_REPORT_EXPORT_STATUS: 'Policy_Accounting_Certinia_Report_Export_Status',
+            CERTINIA_COMPANY_SELECTOR: 'Policy_Accounting_Certinia_Company_Selector',
             CARD_RECONCILIATION: 'Policy_Accounting_Card_Reconciliation',
             CARD_RECONCILIATION_SAGE_INTACCT_AUTO_SYNC: 'Policy_Accounting_Card_Reconciliation_Sage_Intacct_Auto_Sync',
             DYNAMIC_RECONCILIATION_ACCOUNT_SETTINGS: 'Dynamic_Policy_Accounting_Reconciliation_Account_Settings',
@@ -766,13 +770,6 @@ const SCREENS = {
         INVOICES_VERIFY_ACCOUNT: 'Workspace_Invoices_Verify_Account',
         INVOICES_COMPANY_NAME: 'Workspace_Invoices_Company_Name',
         INVOICES_COMPANY_WEBSITE: 'Workspace_Invoices_Company_Website',
-        INVOICE_FIELDS_CREATE: 'Workspace_InvoiceFields_Create',
-        INVOICE_FIELDS_SETTINGS: 'Workspace_InvoiceFields_Settings',
-        INVOICE_FIELDS_LIST_VALUES: 'Workspace_InvoiceFields_ListValues',
-        INVOICE_FIELDS_ADD_VALUE: 'Workspace_InvoiceFields_AddValue',
-        INVOICE_FIELDS_VALUE_SETTINGS: 'Workspace_InvoiceFields_ValueSettings',
-        INVOICE_FIELDS_EDIT_VALUE: 'Workspace_InvoiceFields_EditValue',
-        INVOICE_FIELDS_EDIT_INITIAL_VALUE: 'Workspace_InvoiceFields_EditInitialValue',
         MEMBERS: 'Workspace_Members',
         ROOMS: 'Workspace_Rooms',
         ROOM_CREATE: 'Workspace_Room_Create',
@@ -829,7 +826,6 @@ const SCREENS = {
         WORKFLOWS_APPROVALS_APPROVER_CHANGE: 'Workspace_Workflows_Approvals_Approver_Change',
         WORKFLOWS_APPROVALS_APPROVAL_LIMIT: 'Workspace_Workflows_Approvals_Approval_Limit',
         WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER: 'Workspace_Workflows_Approvals_Over_Limit_Approver',
-        WORKFLOWS_ADD_AGENT: 'Workspace_Workflows_Add_Agent',
         WORKFLOWS_AUTO_REPORTING_FREQUENCY: 'Workspace_Workflows_Auto_Reporting_Frequency',
         WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET: 'Workspace_Workflows_Auto_Reporting_Monthly_Offset',
         DESCRIPTION: 'Workspace_Overview_Description',
diff --git a/src/components/AnimatedSubmitButton/index.tsx b/src/components/AnimatedSubmitButton/index.tsx
index 945d5333fc9b..6e3e010aae1e 100644
--- a/src/components/AnimatedSubmitButton/index.tsx
+++ b/src/components/AnimatedSubmitButton/index.tsx
@@ -28,9 +28,12 @@ type AnimatedSubmitButtonProps = WithSentryLabel & {
 
     // Whether the button should be disabled
     isDisabled?: boolean;
+
+    /** Whether to show "Mark as done" copy instead of "Submit" copy for track-intent users */
+    isMarkAsDone?: boolean;
 };
 
-function AnimatedSubmitButton({success, text, onPress, isSubmittingAnimationRunning, onAnimationFinish, isDisabled, sentryLabel}: AnimatedSubmitButtonProps) {
+function AnimatedSubmitButton({success, text, onPress, isSubmittingAnimationRunning, onAnimationFinish, isDisabled, sentryLabel, isMarkAsDone}: AnimatedSubmitButtonProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const isAnimationRunning = isSubmittingAnimationRunning;
@@ -120,7 +123,7 @@ function AnimatedSubmitButton({success, text, onPress, isSubmittingAnimationRunn
                 >
                     <Button
                         success={success}
-                        text={showLoading ? text : translate('common.submitted')}
+                        text={showLoading ? text : translate(isMarkAsDone ? 'common.markedAsDoneStatus' : 'common.submitted')}
                         isLoading={showLoading}
                         icon={!showLoading ? icon : undefined}
                         isDisabled
diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index bc08e6e96b65..964711ae285f 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -4,7 +4,6 @@ import {View} from 'react-native';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
-import usePermissions from '@hooks/usePermissions';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -12,7 +11,6 @@ import {sortAlphabetically} from '@libs/OptionsListUtils';
 import {getApprovalLimitDescription} from '@libs/WorkflowUtils';
 import CONST from '@src/CONST';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
-import type {Approver} from '@src/types/onyx/ApprovalWorkflow';
 import Button from './Button';
 import Icon from './Icon';
 import MenuItem from './MenuItem';
@@ -31,22 +29,6 @@ type ApprovalWorkflowSectionProps = {
     /** Called when the "+X more" text inside the members row is pressed — deep-links to the members list (skips the Edit RHP). */
     onShowAllMembersPress?: () => void;
 
-    /** A function that is called when the Add agent pill is pressed */
-    onAddAgentPress?: () => void;
-
-    /**
-     * Called when the X is clicked on an approver row that carries `approver.errors`. The page
-     * uses this to discard the failed optimistic agent (clears the deferred-save entry, the
-     * optimistic personal detail / prompt, and the policy-level addAgent error).
-     */
-    onDismissApproverError?: (approver: Approver) => void;
-
-    /**
-     * Whether the Add agent pill is allowed on this card. It is still gated by the
-     * customAgent beta on top of this flag.
-     */
-    canAddAgent?: boolean;
-
     /** Currency used for formatting approval limits */
     currency?: string;
 
@@ -67,25 +49,18 @@ function ApprovalWorkflowSection({
     approvalWorkflow,
     onPress,
     onShowAllMembersPress,
-    onAddAgentPress,
-    onDismissApproverError,
-    canAddAgent = false,
     currency = CONST.CURRENCY.USD,
     isDisabled = false,
     hrProviderName,
     isHRAdvancedMode = false,
     hrFinalApproverEmail,
 }: ApprovalWorkflowSectionProps) {
-    const icons = useMemoizedLazyExpensifyIcons(['ArrowRight', 'Bot', 'Lightbulb', 'Pencil', 'Users', 'UserCheck']);
+    const icons = useMemoizedLazyExpensifyIcons(['ArrowRight', 'Lightbulb', 'Pencil', 'Users', 'UserCheck']);
     const styles = useThemeStyles();
     const theme = useTheme();
     const {translate, toLocaleOrdinal, localeCompare} = useLocalize();
     const {convertToDisplayString} = useCurrencyListActions();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
-    const {isBetaEnabled} = usePermissions();
-    const isCustomAgentEnabled = isBetaEnabled(CONST.BETAS.CUSTOM_AGENT);
-    const shouldShowAddAgentButton = canAddAgent && isCustomAgentEnabled && !isDisabled && !!onAddAgentPress;
-
     const approverTitle = (index: number) => {
         if (isHRAdvancedMode) {
             const isLast = index === approvalWorkflow.approvers.length - 1;
@@ -179,7 +154,6 @@ function ApprovalWorkflowSection({
                         key={`approver-${approver.email || approver.accountID}-${index}`}
                         pendingAction={approver.pendingAction}
                         errors={approver.errors}
-                        onClose={approver.errors && onDismissApproverError ? () => onDismissApproverError(approver) : undefined}
                     >
                         <View>
                             <View style={styles.workflowApprovalVerticalLine} />
@@ -225,16 +199,6 @@ function ApprovalWorkflowSection({
                         accessibilityLabel={translate('workflowsPage.editWorkflowAction')}
                         sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.APPROVAL_WORKFLOW_SECTION}
                     />
-                    {shouldShowAddAgentButton && (
-                        <Button
-                            small
-                            icon={icons.Bot}
-                            text={translate('workflowsPage.addAgentAction')}
-                            onPress={onAddAgentPress}
-                            accessibilityLabel={translate('workflowsPage.addAgentAction')}
-                            sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.APPROVAL_WORKFLOW_SECTION}
-                        />
-                    )}
                 </View>
             )}
         </View>
diff --git a/src/components/BlockingViews/ForceFullScreenView/index.tsx b/src/components/BlockingViews/ForceFullScreenView/index.tsx
index f856794e4a57..a222d69f6816 100644
--- a/src/components/BlockingViews/ForceFullScreenView/index.tsx
+++ b/src/components/BlockingViews/ForceFullScreenView/index.tsx
@@ -1,4 +1,4 @@
-import {useRoute} from '@react-navigation/native';
+import {useIsFocused, useRoute} from '@react-navigation/native';
 import React, {useEffect} from 'react';
 import {View} from 'react-native';
 import {useFullScreenBlockingViewActions} from '@components/FullScreenBlockingViewContextProvider';
@@ -9,16 +9,17 @@ function ForceFullScreenView({children, shouldForceFullScreen = false}: ForceFul
     const route = useRoute();
     const styles = useThemeStyles();
     const {addRouteKey, removeRouteKey} = useFullScreenBlockingViewActions();
+    const isFocused = useIsFocused();
 
     useEffect(() => {
-        if (!shouldForceFullScreen) {
+        if (!shouldForceFullScreen || !isFocused) {
             return;
         }
 
         addRouteKey(route.key);
 
         return () => removeRouteKey(route.key);
-    }, [addRouteKey, removeRouteKey, route.key, shouldForceFullScreen]);
+    }, [addRouteKey, removeRouteKey, route.key, shouldForceFullScreen, isFocused]);
 
     if (shouldForceFullScreen) {
         return <View style={styles.forcedBlockingViewContainer}>{children}</View>;
diff --git a/src/components/CategoryPicker/index.tsx b/src/components/CategoryPicker/index.tsx
index 909a4f7a8353..7253482ff633 100644
--- a/src/components/CategoryPicker/index.tsx
+++ b/src/components/CategoryPicker/index.tsx
@@ -92,7 +92,7 @@ function CategoryPicker({selectedCategory, policyID, onSubmit, addBottomSafeArea
             addBottomSafeAreaPadding={addBottomSafeAreaPadding}
             style={{listItemTitleStyles: styles.w100}}
             isRowMultilineSupported
-            titleNumberOfLines={3}
+            titleNumberOfLines={CONST.TRANSACTION_TAG_AND_CATEGORY_PICKER_MAX_TITLE_LINES}
         />
     );
 }
diff --git a/src/components/Charts/PieChart/PieChartContent.tsx b/src/components/Charts/PieChart/PieChartContent.tsx
index 9f60500949eb..8dac9f1946f0 100644
--- a/src/components/Charts/PieChart/PieChartContent.tsx
+++ b/src/components/Charts/PieChart/PieChartContent.tsx
@@ -131,7 +131,7 @@ function PieChartContent({data, isLoading, valueUnit, valueUnitPosition, onSlice
     const renderLegendItem = (slice: PieSlice) => {
         return (
             <View
-                key={`legend-${slice.label}`}
+                key={`legend-${slice.originalIndex}`}
                 style={[styles.flexRow, styles.alignItemsCenter, styles.mr4, styles.mb2]}
                 onMouseEnter={() => {
                     tooltipPosition.set(slice.tooltipPosition);
diff --git a/src/components/ConnectToHRFlow/index.ios.tsx b/src/components/ConnectToHRFlow/index.ios.tsx
new file mode 100644
index 000000000000..f2d1f800e9f0
--- /dev/null
+++ b/src/components/ConnectToHRFlow/index.ios.tsx
@@ -0,0 +1,90 @@
+import {openAuthSessionAsync} from 'expo-web-browser';
+import React, {useEffect, useRef, useState} from 'react';
+import {StyleSheet, View} from 'react-native';
+import ActivityIndicator from '@components/ActivityIndicator';
+import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import Modal from '@components/Modal';
+import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {getShortLivedAuthTokenURL} from '@userActions/Link';
+import CONST from '@src/CONST';
+import type ConnectToHRFlowProps from './types';
+
+function ConnectToHRFlow({setupLink, onDone}: ConnectToHRFlowProps) {
+    const {translate} = useLocalize();
+    const styles = useThemeStyles();
+    const hasOpened = useRef(false);
+    const isDismissed = useRef(false);
+    const isMounted = useRef(true);
+    const [isModalOpen, setIsModalOpen] = useState(true);
+
+    const dismiss = () => {
+        if (isDismissed.current || !isMounted.current) {
+            return;
+        }
+        isDismissed.current = true;
+        setIsModalOpen(false);
+    };
+
+    const openSession = () => {
+        if (hasOpened.current) {
+            return;
+        }
+        hasOpened.current = true;
+
+        getShortLivedAuthTokenURL(setupLink)
+            // CONST.DEEPLINK_BASE_URL is used as a sentinel so ASWebAuthenticationSession
+            // auto-dismisses when the flow redirects back to the app via deep link.
+            .then((url) => {
+                if (isDismissed.current) {
+                    return;
+                }
+                return openAuthSessionAsync(url, CONST.DEEPLINK_BASE_URL, {preferEphemeralSession: true});
+            })
+            .finally(dismiss);
+    };
+
+    const {isOffline} = useNetwork({onReconnect: openSession});
+
+    useEffect(() => {
+        if (isOffline) {
+            return;
+        }
+        openSession();
+        // eslint-disable-next-line react-hooks/exhaustive-deps -- only the initial setupLink should be used; re-opening the auth session on prop change is not desired
+    }, []);
+
+    useEffect(
+        () => () => {
+            isMounted.current = false;
+        },
+        [],
+    );
+
+    return (
+        <Modal
+            onClose={dismiss}
+            onModalHide={onDone}
+            fullscreen
+            isVisible={isModalOpen}
+            type={CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE}
+        >
+            <HeaderWithBackButton
+                title={translate('workspace.common.hr')}
+                onBackButtonPress={dismiss}
+            />
+            <FullPageOfflineBlockingView>
+                <View style={[StyleSheet.absoluteFill, styles.fullScreenLoading]}>
+                    <ActivityIndicator
+                        size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
+                        reasonAttributes={{context: 'ConnectToHRFlow'}}
+                    />
+                </View>
+            </FullPageOfflineBlockingView>
+        </Modal>
+    );
+}
+
+export default ConnectToHRFlow;
diff --git a/src/components/ConnectToHRFlow/index.native.tsx b/src/components/ConnectToHRFlow/index.native.tsx
index db54e473fa04..27fbeac343eb 100644
--- a/src/components/ConnectToHRFlow/index.native.tsx
+++ b/src/components/ConnectToHRFlow/index.native.tsx
@@ -1,25 +1,58 @@
-import React, {useRef, useState} from 'react';
+import React, {useEffect, useRef, useState} from 'react';
 import {StyleSheet, View} from 'react-native';
 import type {WebViewNavigation} from 'react-native-webview';
 import {WebView} from 'react-native-webview';
+import type {WebViewOpenWindowEvent} from 'react-native-webview/lib/WebViewTypes';
 import ActivityIndicator from '@components/ActivityIndicator';
 import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import Modal from '@components/Modal';
 import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
+import useNetwork from '@hooks/useNetwork';
 import useThemeStyles from '@hooks/useThemeStyles';
+import {getShortLivedAuthTokenURL} from '@userActions/Link';
 import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type ConnectToHRFlowProps from './types';
 
-function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
+function ConnectToHRFlow({setupLink, onDone}: ConnectToHRFlowProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
-    const webViewRef = useRef<WebView>(null);
     const [isWebViewOpen, setIsWebViewOpen] = useState(true);
-    const [session] = useOnyx(ONYXKEYS.SESSION);
+    const [popupUrl, setPopupUrl] = useState<string | null>(null);
+    const [isPopupVisible, setIsPopupVisible] = useState(false);
+    const [authenticatedUrl, setAuthenticatedUrl] = useState<string | null>(null);
+    const [cookiesCleared, setCookiesCleared] = useState(false);
+    const hasFetched = useRef(false);
+    const cookieTimerRef = useRef<NodeJS.Timeout | null>(null);
+
+    const fetchAuthUrl = () => {
+        if (hasFetched.current) {
+            return;
+        }
+        hasFetched.current = true;
+        getShortLivedAuthTokenURL(setupLink).then(setAuthenticatedUrl);
+    };
+
+    const {isOffline} = useNetwork({onReconnect: fetchAuthUrl});
+
+    useEffect(() => {
+        if (isOffline) {
+            return;
+        }
+        fetchAuthUrl();
+        // eslint-disable-next-line react-hooks/exhaustive-deps -- only fetch once on mount when online
+    }, []);
+
+    useEffect(
+        () => () => {
+            if (!cookieTimerRef.current) {
+                return;
+            }
+            clearTimeout(cookieTimerRef.current);
+        },
+        [],
+    );
 
     const renderLoading = () => (
         <View style={[StyleSheet.absoluteFill, styles.fullScreenLoading]}>
@@ -30,40 +63,87 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
         </View>
     );
 
+    const handleOpenWindow = (event: WebViewOpenWindowEvent) => {
+        setPopupUrl(event.nativeEvent.targetUrl);
+        setIsPopupVisible(true);
+    };
+
+    const dismiss = () => {
+        setIsWebViewOpen(false);
+        onDone?.();
+    };
+
+    const handleBackPress = () => {
+        if (isPopupVisible) {
+            // Keep the popup WebView mounted (hidden) so in-flight OAuth redirects
+            // can complete and shared cookies remain intact for Merge Link.
+            setIsPopupVisible(false);
+            return;
+        }
+        dismiss();
+    };
+
     const handleNavigationStateChange = (navState: WebViewNavigation) => {
         if (!navState.url.includes(ROUTES.CONNECTION_COMPLETE)) {
             return;
         }
-        setIsWebViewOpen(false);
+
+        dismiss();
     };
 
-    const authToken = session?.authToken ?? null;
+    const isReady = cookiesCleared && !!authenticatedUrl;
     return (
         <Modal
-            onClose={() => setIsWebViewOpen(false)}
+            onClose={handleBackPress}
             fullscreen
             isVisible={isWebViewOpen}
             type={CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE}
         >
             <HeaderWithBackButton
                 title={translate('workspace.common.hr')}
-                onBackButtonPress={() => setIsWebViewOpen(false)}
-                shouldDisplayHelpButton={false}
+                onBackButtonPress={handleBackPress}
             />
             <FullPageOfflineBlockingView>
-                <WebView
-                    ref={webViewRef}
-                    source={{
-                        uri: setupLink,
-                        headers: {
-                            Cookie: `authToken=${authToken}`,
-                        },
-                    }}
-                    incognito
-                    startInLoadingState
-                    renderLoading={renderLoading}
-                    onNavigationStateChange={handleNavigationStateChange}
-                />
+                <View style={styles.flex1}>
+                    {!cookiesCleared && (
+                        <WebView
+                            source={{uri: 'about:blank'}}
+                            incognito
+                            onLoadEnd={() => {
+                                // Brief delay to ensure the incognito WebView has fully cleared cookies
+                                // before mounting the main WebView. No deterministic completion signal is
+                                // available from the incognito session teardown.
+                                cookieTimerRef.current = setTimeout(() => setCookiesCleared(true), CONST.MERGE_HR.COOKIE_CLEAR_DELAY_MS);
+                            }}
+                            style={styles.opacity0}
+                        />
+                    )}
+                    {!isReady && renderLoading()}
+                    {isReady && (
+                        // Not using incognito here so the popup WebView can share cookies
+                        // with the main flow (required for OAuth handoffs).
+                        <WebView
+                            source={{uri: authenticatedUrl}}
+                            onOpenWindow={handleOpenWindow}
+                            onNavigationStateChange={handleNavigationStateChange}
+                            startInLoadingState
+                            renderLoading={renderLoading}
+                        />
+                    )}
+                    {!!popupUrl && (
+                        <View
+                            style={[StyleSheet.absoluteFill, !isPopupVisible && styles.opacity0]}
+                            pointerEvents={isPopupVisible ? 'auto' : 'none'}
+                        >
+                            <WebView
+                                source={{uri: popupUrl}}
+                                onOpenWindow={handleOpenWindow}
+                                startInLoadingState
+                                renderLoading={renderLoading}
+                            />
+                        </View>
+                    )}
+                </View>
             </FullPageOfflineBlockingView>
         </Modal>
     );
diff --git a/src/components/ConnectToHRFlow/types.ts b/src/components/ConnectToHRFlow/types.ts
index 56f5e1be2809..85b230c23ed8 100644
--- a/src/components/ConnectToHRFlow/types.ts
+++ b/src/components/ConnectToHRFlow/types.ts
@@ -1,6 +1,9 @@
 type ConnectToHRFlowProps = {
     /** The URL to open for the HR provider's connection flow */
     setupLink: string;
+
+    /** Called when the flow is dismissed or completed so the parent can unmount the component */
+    onDone?: () => void;
 };
 
 export default ConnectToHRFlowProps;
diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index 8964cde7658e..64563214a97f 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -2,6 +2,7 @@ import {format, setYear} from 'date-fns';
 import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import {InteractionManager, View} from 'react-native';
+import type {TextInputKeyPressEvent} from 'react-native';
 import TextInput from '@components/TextInput';
 import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
 import useAccessibilityAnnouncement from '@hooks/useAccessibilityAnnouncement';
@@ -10,6 +11,7 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useWindowDimensions from '@hooks/useWindowDimensions';
+import {isNumeric} from '@libs/ValidationUtils';
 import {setDraftValues} from '@userActions/FormActions';
 import CONST from '@src/CONST';
 import DatePickerModal from './DatePickerModal';
@@ -53,8 +55,6 @@ function DatePicker({
     // Whether the user currently intends the picker to be open. Lets a deferred measurement skip opening if the
     // picker was dismissed before it resolved.
     const openIntentRef = useRef(false);
-    // Whether the initial autoFocus has already opened the picker, so later focuses don't reopen it.
-    const hasAutoOpenedRef = useRef(false);
 
     const {inputCallbackRef: autoFocusCallbackRef, cancelAutoFocus} = useAutoFocusInput();
     const autoFocusCallbackRefRef = useRef(autoFocusCallbackRef);
@@ -116,24 +116,16 @@ function DatePicker({
         setIsModalVisible(false);
     }, []);
 
-    const openDatePickerOnPress = useCallback(() => {
-        if (!shouldDeferShowUntilPositioned) {
-            return;
-        }
-        showDatePickerModal();
-    }, [shouldDeferShowUntilPositioned, showDatePickerModal]);
-
-    const handleInputFocus = useCallback(() => {
-        if (!shouldDeferShowUntilPositioned) {
+    const handleInputKeyPress = useCallback(
+        (event: TextInputKeyPressEvent) => {
+            if (!isNumeric(event.nativeEvent.key)) {
+                return;
+            }
+            event.preventDefault();
             showDatePickerModal();
-            return;
-        }
-        if (!autoFocus || hasAutoOpenedRef.current) {
-            return;
-        }
-        hasAutoOpenedRef.current = true;
-        showDatePickerModal();
-    }, [shouldDeferShowUntilPositioned, autoFocus, showDatePickerModal]);
+        },
+        [showDatePickerModal],
+    );
 
     const handleDateSelected = (newDate: string) => {
         onTouched?.();
@@ -191,14 +183,16 @@ function DatePicker({
                     iconContainerStyle={styles.pr0}
                     label={label}
                     accessibilityLabel={label}
-                    role={CONST.ROLE.PRESENTATION}
+                    role={CONST.ROLE.COMBOBOX}
+                    accessibilityState={{expanded: isModalVisible}}
                     value={selectedDate}
                     placeholder={placeholder ?? translate('common.dateFormat')}
                     errorText={errorText}
                     inputStyle={styles.pointerEventsNone}
                     disabled={disabled}
-                    onPress={openDatePickerOnPress}
-                    onFocus={handleInputFocus}
+                    onPress={() => showDatePickerModal()}
+                    onSubmitEditing={() => showDatePickerModal()}
+                    onKeyPress={handleInputKeyPress}
                     textInputContainerStyles={isModalVisible ? styles.borderColorFocus : {}}
                     shouldHideClearButton={shouldHideClearButton}
                     onClearInput={handleClear}
diff --git a/src/components/HighContrastModeSwitcher.tsx b/src/components/HighContrastModeSwitcher.tsx
index 22332e1b220e..0fdf3581724f 100644
--- a/src/components/HighContrastModeSwitcher.tsx
+++ b/src/components/HighContrastModeSwitcher.tsx
@@ -18,10 +18,11 @@ function HighContrastModeSwitcher() {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const [preferredTheme] = useOnyx(ONYXKEYS.PREFERRED_THEME);
+    const [highContrastIntent] = useOnyx(ONYXKEYS.SIGN_IN_HIGH_CONTRAST_INTENT);
     const icons = useMemoizedLazyExpensifyIcons(['Moon']);
 
     const currentTheme = preferredTheme ?? CONST.THEME.DEFAULT;
-    const isHighContrast = isHighContrastTheme(currentTheme);
+    const isHighContrast = highContrastIntent ?? isHighContrastTheme(currentTheme);
     const label = translate(isHighContrast ? 'themePage.disableHighContrast' : 'themePage.enableHighContrast');
 
     const toggleHighContrast = () => {
diff --git a/src/components/Icon/chunks/expensify-icons.chunk.ts b/src/components/Icon/chunks/expensify-icons.chunk.ts
index 078f2de84e42..219348dc4a20 100644
--- a/src/components/Icon/chunks/expensify-icons.chunk.ts
+++ b/src/components/Icon/chunks/expensify-icons.chunk.ts
@@ -207,6 +207,7 @@ import ReceiptMultiple from '@assets/images/receipt-multiple.svg';
 import ReceiptPlaceholderPlus from '@assets/images/receipt-placeholder-plus.svg';
 import ReceiptPlus from '@assets/images/receipt-plus.svg';
 import ReceiptScan from '@assets/images/receipt-scan.svg';
+import ReceiptSearch from '@assets/images/receipt-search.svg';
 import ReceiptSlash from '@assets/images/receipt-slash.svg';
 import Receipt from '@assets/images/receipt.svg';
 import RemoveMembers from '@assets/images/remove-members.svg';
@@ -451,6 +452,7 @@ const Expensicons = {
     ReceiptPlaceholderPlus,
     ReceiptPlus,
     ReceiptScan,
+    ReceiptSearch,
     ReceiptSlash,
     RemoveMembers,
     ReportCopy,
diff --git a/src/components/InteractiveStepSubHeader.tsx b/src/components/InteractiveStepSubHeader.tsx
index f73b17f9ba41..2c0fd86ba028 100644
--- a/src/components/InteractiveStepSubHeader.tsx
+++ b/src/components/InteractiveStepSubHeader.tsx
@@ -3,6 +3,7 @@ import React, {useImperativeHandle, useState} from 'react';
 import type {ViewStyle} from 'react-native';
 import {View} from 'react-native';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import colors from '@styles/theme/colors';
 import variables from '@styles/variables';
@@ -21,6 +22,9 @@ type InteractiveStepSubHeaderProps = {
     /** The index of the step to start with */
     startStepIndex?: number;
 
+    /** Description of the current step, appended to its accessibility label */
+    currentStepAccessibilityDescription: string;
+
     /** Reference to the outer element */
     ref?: ForwardedRef<InteractiveStepSubHeaderHandle>;
 };
@@ -39,8 +43,9 @@ type InteractiveStepSubHeaderHandle = {
 const MIN_AMOUNT_FOR_EXPANDING = 3;
 const MIN_AMOUNT_OF_STEPS = 2;
 
-function InteractiveStepSubHeader({stepNames, startStepIndex = 0, onStepSelected, ref}: InteractiveStepSubHeaderProps) {
+function InteractiveStepSubHeader({stepNames, startStepIndex = 0, currentStepAccessibilityDescription, onStepSelected, ref}: InteractiveStepSubHeaderProps) {
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const containerWidthStyle: ViewStyle = stepNames.length < MIN_AMOUNT_FOR_EXPANDING ? styles.mnw60 : styles.mnw100;
 
     if (stepNames.length < MIN_AMOUNT_OF_STEPS) {
@@ -68,11 +73,7 @@ function InteractiveStepSubHeader({stepNames, startStepIndex = 0, onStepSelected
     const amountOfUnions = stepNames.length - 1;
 
     return (
-        <View
-            style={[styles.interactiveStepHeaderContainer, containerWidthStyle]}
-            accessible={false}
-            aria-hidden
-        >
+        <View style={[styles.interactiveStepHeaderContainer, containerWidthStyle]}>
             {stepNames.map((stepName, index) => {
                 const isCompletedStep = currentStep > index;
                 const isLockedStep = currentStep < index;
@@ -104,9 +105,14 @@ function InteractiveStepSubHeader({stepNames, startStepIndex = 0, onStepSelected
                             ]}
                             disabled={isLockedStep || !onStepSelected}
                             onPress={moveToStep}
-                            accessible={false}
-                            aria-hidden
-                            role={CONST.ROLE.BUTTON}
+                            role={CONST.ROLE.GROUP}
+                            aria-current={currentStep === index ? 'step' : undefined}
+                            accessibilityState={{selected: currentStep === index}}
+                            accessibilityLabel={translate('stepCounter', {
+                                step: index + 1,
+                                total: stepNames.length,
+                                text: currentStep === index ? currentStepAccessibilityDescription : undefined,
+                            })}
                             sentryLabel={CONST.SENTRY_LABEL.INTERACTIVE_STEP_SUB_HEADER.STEP_BUTTON}
                         >
                             {isCompletedStep ? (
diff --git a/src/components/InteractiveStepSubPageHeader.tsx b/src/components/InteractiveStepSubPageHeader.tsx
index 66b5762490c6..e46d9818d2ff 100644
--- a/src/components/InteractiveStepSubPageHeader.tsx
+++ b/src/components/InteractiveStepSubPageHeader.tsx
@@ -2,6 +2,7 @@ import React from 'react';
 import type {ViewStyle} from 'react-native';
 import {View} from 'react-native';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import colors from '@styles/theme/colors';
 import variables from '@styles/variables';
@@ -17,6 +18,9 @@ type InteractiveStepSubPageHeaderProps = {
     /** Current step index (0-based) */
     currentStepIndex: number;
 
+    /** Description of the current step, appended to its accessibility label */
+    currentStepAccessibilityDescription: string;
+
     /** Function to call when a step is selected */
     onStepSelected?: (stepIndex: number) => void;
 };
@@ -24,8 +28,9 @@ type InteractiveStepSubPageHeaderProps = {
 const MIN_AMOUNT_FOR_EXPANDING = 3;
 const MIN_AMOUNT_OF_STEPS = 2;
 
-function InteractiveStepSubPageHeader({stepNames, currentStepIndex, onStepSelected}: InteractiveStepSubPageHeaderProps) {
+function InteractiveStepSubPageHeader({stepNames, currentStepIndex, currentStepAccessibilityDescription, onStepSelected}: InteractiveStepSubPageHeaderProps) {
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const icons = useMemoizedLazyExpensifyIcons(['Checkmark']);
     const containerWidthStyle: ViewStyle = stepNames.length < MIN_AMOUNT_FOR_EXPANDING ? styles.mnw60 : styles.mnw100;
 
@@ -65,8 +70,14 @@ function InteractiveStepSubPageHeader({stepNames, currentStepIndex, onStepSelect
                             disabled={isLockedStep || !onStepSelected}
                             onPress={() => handleStepPress(isLockedStep, index)}
                             accessible
-                            accessibilityLabel={stepName}
-                            role={CONST.ROLE.BUTTON}
+                            role={CONST.ROLE.GROUP}
+                            aria-current={currentStepIndex === index ? 'step' : undefined}
+                            accessibilityState={{selected: currentStepIndex === index}}
+                            accessibilityLabel={translate('stepCounter', {
+                                step: index + 1,
+                                total: stepNames.length,
+                                text: currentStepIndex === index ? currentStepAccessibilityDescription : undefined,
+                            })}
                         >
                             {isCompletedStep ? (
                                 <Icon
diff --git a/src/components/InteractiveStepWrapper.tsx b/src/components/InteractiveStepWrapper.tsx
index 29f6b29ab722..7f4999fdc74c 100644
--- a/src/components/InteractiveStepWrapper.tsx
+++ b/src/components/InteractiveStepWrapper.tsx
@@ -116,6 +116,7 @@ function InteractiveStepWrapper({
                         <InteractiveStepSubHeader
                             startStepIndex={startStepIndex}
                             stepNames={stepNames}
+                            currentStepAccessibilityDescription={headerTitle}
                         />
                     </View>
                 )}
diff --git a/src/components/LHNOptionsList/LHNEmptyState.tsx b/src/components/LHNOptionsList/LHNEmptyState.tsx
index 40fed2097bc6..cb0f4552dbca 100644
--- a/src/components/LHNOptionsList/LHNEmptyState.tsx
+++ b/src/components/LHNOptionsList/LHNEmptyState.tsx
@@ -3,12 +3,16 @@ import {View} from 'react-native';
 import type {BlockingViewProps} from '@components/BlockingViews/BlockingView';
 import BlockingView from '@components/BlockingViews/BlockingView';
 import Icon from '@components/Icon';
+import Text from '@components/Text';
 import TextBlock from '@components/TextBlock';
+import TextLink from '@components/TextLink';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
+import {useSidebarOrderedReportsActions, useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import variables from '@styles/variables';
+import CONST from '@src/CONST';
 import useEmptyLHNIllustration from './useEmptyLHNIllustration';
 
 function LHNEmptyState() {
@@ -16,7 +20,34 @@ function LHNEmptyState() {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['MagnifyingGlass', 'Plus']);
-    const emptyLHNIllustration = useEmptyLHNIllustration();
+    const emptyLHNIllustration = useEmptyLHNIllustration() as BlockingViewProps;
+    const {activeTab} = useSidebarOrderedReportsState();
+    const {setActiveTab} = useSidebarOrderedReportsActions();
+
+    if (activeTab === CONST.INBOX_TAB.UNREAD || activeTab === CONST.INBOX_TAB.TODO) {
+        const title = activeTab === CONST.INBOX_TAB.UNREAD ? translate('common.emptyLHN.noUnreadChats') : translate('common.emptyLHN.noTodos');
+        const caughtUpSubtitle = (
+            <View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>
+                <Text style={[styles.textAlignCenter, styles.textSupporting]}>{translate('common.emptyLHN.caughtUp')}</Text>
+                <TextLink
+                    onPress={() => setActiveTab(CONST.INBOX_TAB.ALL)}
+                    style={[styles.textStrong, styles.mt5, styles.ph4, styles.textAlignCenter]}
+                >
+                    {translate('common.emptyLHN.seeAllChats')}
+                </TextLink>
+            </View>
+        );
+
+        return (
+            <BlockingView
+                {...emptyLHNIllustration}
+                title={title}
+                titleStyles={styles.mb2}
+                CustomSubtitle={caughtUpSubtitle}
+                accessibilityLabel={title}
+            />
+        );
+    }
 
     const subtitle = (
         <View style={[styles.alignItemsCenter, styles.flexRow, styles.justifyContentCenter, styles.flexWrap, styles.textAlignCenter]}>
@@ -56,7 +87,7 @@ function LHNEmptyState() {
 
     return (
         <BlockingView
-            {...(emptyLHNIllustration as BlockingViewProps)}
+            {...emptyLHNIllustration}
             title={translate('common.emptyLHN.title')}
             CustomSubtitle={subtitle}
             accessibilityLabel={translate('common.emptyLHN.title')}
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/ErrorBadge.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/ErrorBadge.tsx
index 011d1202a30b..2c43f54746bb 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/ErrorBadge.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/ErrorBadge.tsx
@@ -2,6 +2,7 @@ import React from 'react';
 import {View} from 'react-native';
 import Badge from '@components/Badge';
 import Icon from '@components/Icon';
+import getActionBadgeText from '@components/utils/getActionBadgeText';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useTheme from '@hooks/useTheme';
@@ -15,9 +16,12 @@ type ErrorBadgeProps = {
 
     /** Action badge key used to derive the badge label. */
     actionBadge: OptionData['actionBadge'];
+
+    /** Whether to show the "Mark as Done" state for this row. */
+    isMarkAsDone?: boolean;
 };
 
-function ErrorBadge({brickRoadIndicator, actionBadge}: ErrorBadgeProps) {
+function ErrorBadge({brickRoadIndicator, actionBadge, isMarkAsDone}: ErrorBadgeProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -27,7 +31,7 @@ function ErrorBadge({brickRoadIndicator, actionBadge}: ErrorBadgeProps) {
         return null;
     }
 
-    const actionBadgeText = actionBadge ? translate(`common.actionBadge.${actionBadge}`) : '';
+    const actionBadgeText = getActionBadgeText(actionBadge, translate, isMarkAsDone);
 
     return (
         <View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/InfoBadge.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/InfoBadge.tsx
index 86d7b6ee160e..b50bc3e269a8 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/InfoBadge.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/InfoBadge.tsx
@@ -2,6 +2,7 @@ import React from 'react';
 import {View} from 'react-native';
 import Badge from '@components/Badge';
 import Icon from '@components/Icon';
+import getActionBadgeText from '@components/utils/getActionBadgeText';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useTheme from '@hooks/useTheme';
@@ -15,9 +16,11 @@ type InfoBadgeProps = {
 
     /** Action badge key used to derive the badge label. */
     actionBadge: OptionData['actionBadge'];
+    /** Whether to show the "Mark as Done" state for this row. */
+    isMarkAsDone?: boolean;
 };
 
-function InfoBadge({brickRoadIndicator, actionBadge}: InfoBadgeProps) {
+function InfoBadge({brickRoadIndicator, actionBadge, isMarkAsDone}: InfoBadgeProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -27,7 +30,7 @@ function InfoBadge({brickRoadIndicator, actionBadge}: InfoBadgeProps) {
         return null;
     }
 
-    const actionBadgeText = actionBadge ? translate(`common.actionBadge.${actionBadge}`) : '';
+    const actionBadgeText = getActionBadgeText(actionBadge, translate, isMarkAsDone);
 
     if (actionBadgeText) {
         return (
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Pressable.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Pressable.tsx
index 73c86874c118..1e0e3d71643b 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Pressable.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Pressable.tsx
@@ -5,6 +5,7 @@ import Hoverable from '@components/Hoverable';
 import {useLHNTooltipContext} from '@components/LHNOptionsList/LHNTooltipContext';
 import useLHNRowProductTrainingTooltip from '@components/LHNOptionsList/OptionRowLHN/useLHNRowProductTrainingTooltip';
 import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction';
+import getActionBadgeText from '@components/utils/getActionBadgeText';
 import getContextMenuAccessibilityHint from '@components/utils/getContextMenuAccessibilityHint';
 import getContextMenuAccessibilityProps from '@components/utils/getContextMenuAccessibilityProps';
 import useLocalize from '@hooks/useLocalize';
@@ -41,9 +42,12 @@ type PressableProps = {
 
     /** Row content. */
     children: ReactNode;
+
+    /** Whether to show the "Mark as Done" state for this row. */
+    isMarkAsDone?: boolean;
 };
 
-function Pressable({optionItem, isOptionFocused, onSelectRow, onLayout, onHoverIn, onHoverOut, children}: PressableProps) {
+function Pressable({optionItem, isOptionFocused, onSelectRow, onLayout, onHoverIn, onHoverOut, children, isMarkAsDone}: PressableProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
@@ -57,7 +61,7 @@ function Pressable({optionItem, isOptionFocused, onSelectRow, onLayout, onHoverI
 
     const reportID = optionItem.reportID;
     const brickRoadIndicator = optionItem.brickRoadIndicator;
-    const actionBadgeText = optionItem.actionBadge ? translate(`common.actionBadge.${optionItem.actionBadge}`) : '';
+    const actionBadgeText = getActionBadgeText(optionItem.actionBadge, translate, isMarkAsDone);
 
     let accessibilityLabelForBadge = '';
     if (brickRoadIndicator) {
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHN.tsx
index 44e8b25fabe2..c787a7e4548e 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHN.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHN.tsx
@@ -5,7 +5,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import OptionRow from './OptionRow';
 import useOptionRowChrome from './useOptionRowChrome';
 
-function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionItem, viewMode = 'default', onLayout = () => {}, hasDraftComment, testID}: OptionRowLHNProps) {
+function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionItem, viewMode = 'default', onLayout = () => {}, hasDraftComment, testID, isMarkAsDone}: OptionRowLHNProps) {
     const styles = useThemeStyles();
     const {setHovered, sidebarInnerRowStyle, contentContainerStyles, avatarBackgroundColor} = useOptionRowChrome({
         isOptionFocused,
@@ -27,6 +27,7 @@ function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionIt
                     onLayout={onLayout}
                     onHoverIn={() => setHovered(true)}
                     onHoverOut={() => setHovered(false)}
+                    isMarkAsDone={isMarkAsDone}
                 >
                     <View style={sidebarInnerRowStyle}>
                         <View style={[styles.flexRow, styles.alignItemsCenter]}>
@@ -55,6 +56,7 @@ function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionIt
                             <OptionRow.ErrorBadge
                                 brickRoadIndicator={brickRoadIndicator}
                                 actionBadge={optionItem.actionBadge}
+                                isMarkAsDone={isMarkAsDone}
                             />
                         </View>
                     </View>
@@ -62,6 +64,7 @@ function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionIt
                         <OptionRow.InfoBadge
                             brickRoadIndicator={brickRoadIndicator}
                             actionBadge={optionItem.actionBadge}
+                            isMarkAsDone={isMarkAsDone}
                         />
                         <OptionRow.DraftIndicator
                             hasDraftComment={hasDraftComment}
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNData.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNData.tsx
index c797dfcef367..0e30da791d95 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNData.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNData.tsx
@@ -1,3 +1,4 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React, {useCallback, useMemo} from 'react';
 import type {ViewStyle} from 'react-native';
 import {StyleSheet, View} from 'react-native';
@@ -12,7 +13,7 @@ import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getLastVisibleActionIncludingTransactionThread, getOriginalMessage, isActionableTrackExpense, isInviteOrRemovedAction} from '@libs/ReportActionsUtils';
-import {canUserPerformWriteAction as canUserPerformWriteActionUtil} from '@libs/ReportUtils';
+import {canUserPerformWriteAction as canUserPerformWriteActionUtil, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import SidebarUtils from '@libs/SidebarUtils';
 import CONST from '@src/CONST';
 import {getMovedReportID} from '@src/libs/ModifiedExpenseMessage';
@@ -121,6 +122,7 @@ function OptionRowLHNData({
     const [movedFromReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastAction, CONST.REPORT.MOVE_TYPE.FROM)}`);
     const [movedToReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastAction, CONST.REPORT.MOVE_TYPE.TO)}`);
     const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fullReport?.policyID}`);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     const card = useGetExpensifyCardFromReportAction({reportAction: lastAction, policyID: fullReport?.policyID});
 
@@ -159,6 +161,7 @@ function OptionRowLHNData({
         reportAttributesDerived,
         policyTags,
         currentUserLogin: login ?? '',
+        isTrackIntentUser,
     });
 
     // For single-sender IOUs, trim to the sender's avatar to match the header.
@@ -190,6 +193,13 @@ function OptionRowLHNData({
         return isReportFocused ? null : <View style={placeholderRowStyle} />;
     }
 
+    const shouldUseMarkAsDone =
+        shouldShowMarkAsDone({
+            report: fullReport,
+            isTrackIntentUser,
+            policy,
+        }) && finalOptionItem?.actionBadge === CONST.REPORT.ACTION_BADGE.SUBMIT;
+
     return (
         <OptionRowLHN
             {...propsToForward}
@@ -197,6 +207,7 @@ function OptionRowLHNData({
             isOptionFocused={isReportFocused}
             optionItem={finalOptionItem}
             hasDraftComment={hasDraftComment}
+            isMarkAsDone={shouldUseMarkAsDone}
         />
     );
 }
diff --git a/src/components/LHNOptionsList/types.ts b/src/components/LHNOptionsList/types.ts
index 829de863508a..f8aad940fdb2 100644
--- a/src/components/LHNOptionsList/types.ts
+++ b/src/components/LHNOptionsList/types.ts
@@ -95,6 +95,8 @@ type OptionRowLHNProps = {
 
     /** The testID of the row */
     testID: number;
+    /** Whether to show "Mark as done" copy instead of "Submit" copy for track-intent users */
+    isMarkAsDone?: boolean;
 };
 
 type RenderItemProps = {item: Report; index: number};
diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx
index a8cfa2e174d0..e55dc0ce878a 100644
--- a/src/components/MenuItem.tsx
+++ b/src/components/MenuItem.tsx
@@ -1112,7 +1112,7 @@ function MenuItem({
                                                 {/* Since subtitle can be of type number, we should allow 0 to be shown */}
                                                 {(subtitle === 0 || !!subtitle) && (
                                                     <View style={[styles.justifyContentCenter, styles.mr1, subtitleStyle]}>
-                                                        <Text style={[styles.textLabelSupporting, ...(combinedStyle as TextStyle[])]}>{subtitle}</Text>
+                                                        <Text style={[styles.textLabelSupporting]}>{subtitle}</Text>
                                                     </View>
                                                 )}
                                                 {(!!rightIconAccountID || !!rightIconReportID) && (
diff --git a/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx b/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx
index c786227ce0b4..98956832a092 100644
--- a/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx
+++ b/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx
@@ -1,6 +1,6 @@
 import {useRoute} from '@react-navigation/native';
 import {delegateEmailSelector, isUserValidatedSelector} from '@selectors/Account';
-import {hasSeenTourSelector} from '@selectors/Onboarding';
+import {hasSeenTourSelector, isTrackIntentUserSelector} from '@selectors/Onboarding';
 import truncate from 'lodash/truncate';
 import React, {useContext} from 'react';
 import type {StyleProp, ViewStyle} from 'react-native';
@@ -54,6 +54,7 @@ import {
     hasViolations as hasViolationsReportUtils,
     isInvoiceReport as isInvoiceReportUtil,
     isIOUReport as isIOUReportUtil,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import shouldPopoverUseScrollView from '@libs/shouldPopoverUseScrollView';
 import {isTransactionPendingDelete} from '@libs/TransactionUtils';
@@ -385,7 +386,15 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
         });
     };
 
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report: moneyRequestReport,
+        isTrackIntentUser,
+    });
     const allExpensesSelected = selectedTransactionIDs.length > 0 && selectedTransactionIDs.length === nonPendingDeleteTransactions.length;
+    const submitButtonText = shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('common.submit');
+    const approveButtonText = shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('iou.approve');
 
     // Ref writes below are inside onSelected callbacks that only fire on user interaction, never during render.
 
@@ -393,7 +402,7 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
         ...(hasSubmitAction && !shouldBlockSubmit
             ? [
                   {
-                      text: translate('common.submit'),
+                      text: submitButtonText,
                       icon: expensifyIcons.Send,
                       value: CONST.REPORT.PRIMARY_ACTIONS.SUBMIT,
                       onSelected: () => handleSubmitReport(true),
@@ -403,7 +412,7 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
         ...(hasApproveAction && !isBlockSubmitDueToPreventSelfApproval
             ? [
                   {
-                      text: translate('iou.approve'),
+                      text: approveButtonText,
                       icon: expensifyIcons.ThumbsUp,
                       value: CONST.REPORT.PRIMARY_ACTIONS.APPROVE,
                       onSelected: () => confirmApproval(true),
diff --git a/src/components/MoneyReportHeaderPrimaryAction/ApprovePrimaryAction.tsx b/src/components/MoneyReportHeaderPrimaryAction/ApprovePrimaryAction.tsx
index d4f2ea916bee..688368ada57c 100644
--- a/src/components/MoneyReportHeaderPrimaryAction/ApprovePrimaryAction.tsx
+++ b/src/components/MoneyReportHeaderPrimaryAction/ApprovePrimaryAction.tsx
@@ -1,10 +1,11 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import Button from '@components/Button';
 import {usePaymentAnimationsContext} from '@components/PaymentAnimationsContext';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
-import {getNextApproverAccountID, isReportOwner} from '@libs/ReportUtils';
+import {getNextApproverAccountID, isReportOwner, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
 import useConfirmApproval from './useConfirmApproval';
 
@@ -18,6 +19,13 @@ function ApprovePrimaryAction({reportID}: ApprovePrimaryActionProps) {
 
     const [moneyRequestReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(moneyRequestReport?.policyID)}`);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        isTrackIntentUser,
+        report: moneyRequestReport,
+        policy,
+    });
 
     const nextApproverAccountID = getNextApproverAccountID(moneyRequestReport);
     const isSubmitterSameAsNextApprover =
@@ -30,7 +38,7 @@ function ApprovePrimaryAction({reportID}: ApprovePrimaryActionProps) {
         <Button
             success
             onPress={confirmApproval}
-            text={translate('iou.approve')}
+            text={shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('iou.approve')}
             isDisabled={isBlockSubmitDueToPreventSelfApproval}
         />
     );
diff --git a/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx b/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx
index f788022b2b1e..c63c326a8356 100644
--- a/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx
+++ b/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx
@@ -1,4 +1,5 @@
 import {delegateEmailSelector} from '@selectors/Account';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import AnimatedSubmitButton from '@components/AnimatedSubmitButton';
 import {usePaymentAnimationsContext} from '@components/PaymentAnimationsContext';
@@ -17,7 +18,7 @@ import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViol
 import {search} from '@libs/actions/Search';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getFilteredReportActionsForReportView} from '@libs/ReportActionsUtils';
-import {hasViolations as hasViolationsReportUtils, shouldBlockSubmitDueToPreventSelfApproval, shouldBlockSubmitDueToStrictPolicyRules} from '@libs/ReportUtils';
+import {hasViolations as hasViolationsReportUtils, shouldBlockSubmitDueToPreventSelfApproval, shouldBlockSubmitDueToStrictPolicyRules, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import {submitReport} from '@userActions/IOU/ReportWorkflow';
 import {markPendingRTERTransactionsAsCash} from '@userActions/Transaction';
@@ -44,6 +45,7 @@ function SubmitPrimaryAction({reportID}: SubmitPrimaryActionProps) {
     const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END);
     const [allTransactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
     const [delegateEmail] = useOnyx(ONYXKEYS.ACCOUNT, {selector: delegateEmailSelector});
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
     const {reportActions: unfilteredReportActions} = usePaginatedReportActions(moneyRequestReport?.reportID);
@@ -70,6 +72,11 @@ function SubmitPrimaryAction({reportID}: SubmitPrimaryActionProps) {
         transactions,
     );
     const shouldBlockSubmit = isBlockSubmitDueToStrictPolicyRules || isBlockSubmitDueToPreventSelfApproval;
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report: moneyRequestReport,
+        isTrackIntentUser,
+    });
 
     const {currentSearchQueryJSON, currentSearchKey} = useSearchQueryContext();
     const {currentSearchResults} = useSearchResultsContext();
@@ -116,7 +123,8 @@ function SubmitPrimaryAction({reportID}: SubmitPrimaryActionProps) {
     return (
         <AnimatedSubmitButton
             success
-            text={translate('common.submit')}
+            text={shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('common.submit')}
+            isMarkAsDone={shouldUseMarkAsDoneCopy}
             onPress={handleSubmit}
             isSubmittingAnimationRunning={isSubmittingAnimationRunning}
             onAnimationFinish={stopAnimation}
diff --git a/src/components/MoneyRequestConfirmationList/sections/AttendeeField.tsx b/src/components/MoneyRequestConfirmationList/sections/AttendeeField.tsx
index 90d4d5cd27a3..2252f0df716f 100644
--- a/src/components/MoneyRequestConfirmationList/sections/AttendeeField.tsx
+++ b/src/components/MoneyRequestConfirmationList/sections/AttendeeField.tsx
@@ -7,13 +7,12 @@ import useAttendees from '@hooks/useAttendees';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {enrichAndSortAttendees} from '@libs/AttendeeUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import {getAttendeesListDisplayString} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
-import {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import {attendeeSliceSelector} from './selectors';
 import useTransactionSelector from './useTransactionSelector';
@@ -68,7 +67,7 @@ function AttendeeField({formattedAmountPerAttendee, isReadOnly, transactionID, a
                     return;
                 }
 
-                Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_ATTENDEE.getRoute(action, iouType, transactionID, reportID)));
+                Navigation.navigate(ROUTES.MONEY_REQUEST_ATTENDEE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute()));
             }}
             interactive={!isReadOnly}
             brickRoadIndicator={shouldDisplayAttendeesError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
diff --git a/src/components/MoneyRequestConfirmationList/sections/CategoryField.tsx b/src/components/MoneyRequestConfirmationList/sections/CategoryField.tsx
index 4f70942ac203..098a4d5225f7 100644
--- a/src/components/MoneyRequestConfirmationList/sections/CategoryField.tsx
+++ b/src/components/MoneyRequestConfirmationList/sections/CategoryField.tsx
@@ -5,12 +5,11 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getDecodedLeafCategoryName} from '@libs/CategoryUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import {categoryStateSelector} from './selectors';
 import useTransactionSelector from './useTransactionSelector';
@@ -79,24 +78,23 @@ function CategoryField({
 
                 if (shouldNavigateToUpgradePath) {
                     Navigation.navigate(
-                        createDynamicRoute(
-                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                action,
-                                iouType,
-                                transactionID,
-                                reportID,
-                                upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                            }),
-                        ),
+                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                            action,
+                            iouType,
+                            transactionID,
+                            reportID,
+                            backTo: ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID),
+                            upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                        }),
                     );
                 } else if (!policy && shouldSelectPolicy) {
                     Navigation.navigate(
                         ROUTES.SET_DEFAULT_WORKSPACE.getRoute(
-                            createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, reportActionID)),
+                            ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID),
                         ),
                     );
                 } else {
-                    Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, reportActionID)));
+                    Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID));
                 }
             }}
             style={[styles.moneyRequestMenuItem]}
diff --git a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx
index da1c2bcfbd0a..46c64a8dafdb 100644
--- a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx
+++ b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx
@@ -6,11 +6,10 @@ import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DistanceRequestUtils from '@libs/DistanceRequestUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import type {Unit} from '@src/types/onyx/Policy';
 
@@ -76,16 +75,15 @@ function RateField({
 
                 if ((!isPolicyExpenseChat && !isTrackExpense) || (shouldNavigateToUpgradePath && isTrackExpense)) {
                     Navigation.navigate(
-                        createDynamicRoute(
-                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                action,
-                                iouType,
-                                transactionID,
-                                reportID,
-                                upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
-                                shouldSubmitExpense: !isTrackExpense,
-                            }),
-                        ),
+                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                            action,
+                            iouType,
+                            transactionID,
+                            reportID,
+                            upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
+                            backTo: Navigation.getActiveRoute(),
+                            shouldSubmitExpense: !isTrackExpense,
+                        }),
                     );
                 } else if (!policy && shouldSelectPolicy && isTrackExpense) {
                     Navigation.navigate(
diff --git a/src/components/MoneyRequestConfirmationList/sections/TaxFields.tsx b/src/components/MoneyRequestConfirmationList/sections/TaxFields.tsx
index fdc67c1ce3c8..c1a23e52decb 100644
--- a/src/components/MoneyRequestConfirmationList/sections/TaxFields.tsx
+++ b/src/components/MoneyRequestConfirmationList/sections/TaxFields.tsx
@@ -12,7 +12,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {setMoneyRequestTaxAmount} from '@libs/actions/IOU/MoneyRequest';
 import {convertToBackendAmount, convertToFrontendAmountAsString, getLocalizedCurrencySymbol} from '@libs/CurrencyUtils';
 import {isMovingTransactionFromTrackExpense} from '@libs/IOUUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import {getCalculatedTaxAmount, getTaxAmount, getTaxRateTitle} from '@libs/TransactionUtils';
 import {setDraftSplitTransaction} from '@userActions/IOU/Split';
@@ -20,7 +19,7 @@ import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import {taxSliceSelector} from './selectors';
 import useTransactionSelector from './useTransactionSelector';
@@ -118,7 +117,7 @@ function TaxFields({policy, policyForMovingExpenses, iouCurrencyCode, canModifyT
                         return;
                     }
 
-                    Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(action, iouType, transactionID, reportID)));
+                    Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute()));
                 }}
                 disabled={didConfirm}
                 interactive={canModifyTaxFields}
@@ -157,7 +156,7 @@ function TaxFields({policy, policyForMovingExpenses, iouCurrencyCode, canModifyT
                             return;
                         }
 
-                        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(action, iouType, transactionID, reportID)));
+                        Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute()));
                     }}
                     disabled={didConfirm}
                     interactive={canModifyTaxFields}
diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx
index 27cfc63a232f..ef57e50d5a42 100644
--- a/src/components/MoneyRequestHeaderSecondaryActions.tsx
+++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx
@@ -3,8 +3,6 @@ import {shouldFailAllRequestsSelector} from '@selectors/Network';
 import {hasSeenTourSelector} from '@selectors/Onboarding';
 import {validTransactionDraftsSelector} from '@selectors/TransactionDraft';
 import React, {useRef, useState} from 'react';
-// eslint-disable-next-line no-restricted-imports
-import {InteractionManager} from 'react-native';
 import type {ValueOf} from 'type-fest';
 import useConfirmModal from '@hooks/useConfirmModal';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
@@ -35,7 +33,6 @@ import initSplitExpense from '@libs/actions/SplitExpenses';
 import {setNameValuePair} from '@libs/actions/User';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getExistingTransactionID} from '@libs/IOUUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {ReportsSplitNavigatorParamList, RightModalNavigatorParamList} from '@libs/Navigation/types';
@@ -67,7 +64,7 @@ import {dismissRejectUseExplanation} from '@userActions/IOU/RejectMoneyRequest';
 import {setDeleteTransactionNavigateBackUrl} from '@userActions/Report';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import SCREENS from '@src/SCREENS';
 import type {Transaction} from '@src/types/onyx';
 import ButtonWithDropdownMenu from './ButtonWithDropdownMenu';
@@ -85,7 +82,7 @@ type MoneyRequestHeaderSecondaryActionsProps = {
     reportID: string | undefined;
 
     /** Method to trigger when pressing close button of the header */
-    onBackButtonPress: (prioritizeBackTo?: boolean) => void;
+    onBackButtonPress: (prioritizeBackTo?: boolean, options?: {afterTransition?: () => void}) => void;
 };
 
 function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: MoneyRequestHeaderSecondaryActionsProps) {
@@ -444,6 +441,8 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                     }
                     const backToRoute = route.params?.backTo ?? Navigation.getActiveRoute();
                     setDeleteTransactionNavigateBackUrl(backToRoute);
+
+                    let afterDelete: (() => void) | undefined;
                     if (isTrackExpenseAction(parentReportAction) && !isExpenseSplit) {
                         deleteTrackExpense({
                             chatReportID: report?.parentReportID,
@@ -466,8 +465,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                             deleteTransactions([transaction.transactionID], duplicateTransactions, duplicateTransactionViolations, currentSearchHash, true);
                             return;
                         }
-                        // eslint-disable-next-line @typescript-eslint/no-deprecated
-                        InteractionManager.runAfterInteractions(() => {
+                        afterDelete = () => {
                             const deleteResult = deleteTransactions(
                                 [transaction.transactionID],
                                 duplicateTransactions,
@@ -481,14 +479,19 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                             }
 
                             removeTransaction(transaction.transactionID);
-                        });
+                        };
                     }
                     if (isInNarrowPaneModal) {
-                        Navigation.navigateBackToLastSuperWideRHPScreen();
+                        // The super wide RHP close animation was changed, and because of that the report was deleted right after
+                        // the animation finished, which caused flickering in the reports list. We want the user to see
+                        // the expense in the list for a little bit longer, so we wait for the animation to finish and then
+                        // add an additional delay before removing it.
+                        // See https://github.com/Expensify/App/issues/92036
+                        Navigation.navigateBackToLastSuperWideRHPScreen({afterTransition: () => setTimeout(() => afterDelete?.(), CONST.EXPENSE_REPORT_DELETE_DELAY_MS)});
                         return;
                     }
 
-                    onBackButtonPress();
+                    onBackButtonPress(false, {afterTransition: afterDelete});
                 });
             },
         },
@@ -522,15 +525,13 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                 const iouType = isExpenseReport(parentReport) ? CONST.IOU.TYPE.SUBMIT : CONST.IOU.TYPE.TRACK;
                 if (shouldNavigateToUpgradePath && reportID) {
                     Navigation.navigate(
-                        createDynamicRoute(
-                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                action: CONST.IOU.ACTION.EDIT,
-                                iouType,
-                                transactionID: transaction.transactionID,
-                                reportID,
-                                upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                            }),
-                        ),
+                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                            action: CONST.IOU.ACTION.EDIT,
+                            iouType,
+                            transactionID: transaction.transactionID,
+                            reportID,
+                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                        }),
                     );
                     return;
                 }
diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
index 333261612976..db0495c0b480 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
@@ -1,5 +1,6 @@
 /* eslint-disable rulesdir/prefer-early-return */
 import {useIsFocused, useRoute} from '@react-navigation/native';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import isEmpty from 'lodash/isEmpty';
 import React, {useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react';
 import type {LayoutChangeEvent, ListRenderItemInfo, NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
@@ -42,7 +43,7 @@ import {
     isReportActionVisible,
     wasMessageReceivedWhileOffline,
 } from '@libs/ReportActionsUtils';
-import {canUserPerformWriteAction, chatIncludesChronosWithID, getReportLastVisibleActionCreated, isHarvestCreatedExpenseReport, isUnread} from '@libs/ReportUtils';
+import {canUserPerformWriteAction, chatIncludesChronosWithID, getReportLastVisibleActionCreated, isHarvestCreatedExpenseReport, isUnread, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import markOpenReportEnd from '@libs/telemetry/markOpenReportEnd';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import Visibility from '@libs/Visibility';
@@ -148,6 +149,7 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
     const shouldShowHarvestCreatedAction = isHarvestCreatedExpenseReport(reportNameValuePairs?.origin, reportNameValuePairs?.originalID);
     const [enableScrollToEnd, setEnableScrollToEnd] = useState<boolean>(false);
     const [lastActionEventId, setLastActionEventId] = useState<string>('');
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     // We are reversing actions because in this View we are starting at the top and don't use Inverted list
     const visibleReportActions = useMemo(() => {
@@ -657,6 +659,12 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
         return null;
     }
 
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report,
+        isTrackIntentUser,
+    });
+
     return (
         <View
             style={[styles.flex1]}
@@ -672,6 +680,7 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
                     hasNewMessages={!!unreadMarkerReportActionID}
                     isActive={isFloatingMessageCounterVisible}
                     onClick={scrollToBottomAndMarkReportAsRead}
+                    isMarkAsDone={shouldUseMarkAsDoneCopy}
                 />
                 {/* Exactly one of these two branches is active at a time:
                     1. showEmptyState — genuinely empty report
diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
index 9aa36783c1a3..8b8f8948b3e0 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
@@ -20,7 +20,6 @@ import SelectionList from '@components/SelectionList';
 import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem';
 import SearchRowSkeleton from '@components/Skeletons/SearchRowSkeleton';
 import Text from '@components/Text';
-import {useWideRHPActions} from '@components/WideRHPContextProvider';
 import useCopySelectionHelper from '@hooks/useCopySelectionHelper';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
@@ -28,6 +27,7 @@ import useHandleSelectionMode from '@hooks/useHandleSelectionMode';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
+import useNavigateToTransactionThread from '@hooks/useNavigateToTransactionThread';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
 import useReportIsArchived from '@hooks/useReportIsArchived';
@@ -38,14 +38,13 @@ import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useWindowDimensions from '@hooks/useWindowDimensions';
 import {turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
-import {setOptimisticTransactionThread} from '@libs/actions/Report';
 import {getReportLayoutGroupBy, getReportLayoutSelection, setReportLayout} from '@libs/actions/ReportLayout';
 import {clearActiveTransactionIDs, setActiveTransactionIDs} from '@libs/actions/TransactionThreadNavigation';
 import {resolveTransactionCardFields} from '@libs/CardUtils';
 import {hasNonReimbursableTransactions, isBillableEnabledOnPolicy} from '@libs/MoneyRequestReportUtils';
 import {navigationRef} from '@libs/Navigation/Navigation';
 import {isPolicyTaxEnabled} from '@libs/PolicyUtils';
-import {getIOUActionForTransactionID, getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
+import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
 import {groupTransactionsByCategory, groupTransactionsByTag} from '@libs/ReportLayoutUtils';
 import {
     canAddTransaction,
@@ -68,9 +67,7 @@ import {getTransactionPendingAction, getVisibleTransactionViolations, isTransact
 import shouldShowTransactionYear from '@libs/TransactionUtils/shouldShowTransactionYear';
 import isReportOpenInSuperWideRHP from '@navigation/helpers/isReportOpenInSuperWideRHP';
 import Navigation from '@navigation/Navigation';
-import type {ReportsSplitNavigatorParamList} from '@navigation/types';
 import variables from '@styles/variables';
-import {createTransactionThreadReport} from '@userActions/Report';
 import CONST from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
 import NAVIGATORS from '@src/NAVIGATORS';
@@ -151,8 +148,6 @@ type TransactionWithOptionalHighlight = OnyxTypes.Transaction & {
     shouldBeHighlighted?: boolean;
 };
 
-type ReportScreenNavigationProps = ReportsSplitNavigatorParamList[typeof SCREENS.REPORT];
-
 type SortedTransactions = {
     sortBy: SortableColumnName;
     sortOrder: SortOrder;
@@ -180,7 +175,7 @@ function MoneyRequestReportTransactionList({
     // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
     const {isSmallScreenWidth, isMediumScreenWidth, isInLandscapeMode} = useResponsiveLayout();
     const {shouldUseNarrowLayout} = useResponsiveLayoutOnWideRHP();
-    const {markReportIDAsExpense} = useWideRHPActions();
+    const navigateToTransactionThread = useNavigateToTransactionThread();
     const [isModalVisible, setIsModalVisible] = useState(false);
     const [selectedTransactionID, setSelectedTransactionID] = useState<string>('');
     const {reportPendingAction} = getReportOfflinePendingActionAndErrors(report);
@@ -206,8 +201,6 @@ function MoneyRequestReportTransactionList({
     const [reportLayoutOption] = useOnyx(ONYXKEYS.NVP_REPORT_LAYOUT_OPTION);
     const [amountOwed] = useOnyx(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED);
     const [reportDetailsColumns] = useOnyx(ONYXKEYS.NVP_REPORT_DETAILS_COLUMNS);
-    const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
-    const [betas] = useOnyx(ONYXKEYS.BETAS);
     const [nonPersonalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST);
     const [cardList] = useOnyx(ONYXKEYS.CARD_LIST);
     const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector});
@@ -554,44 +547,15 @@ function MoneyRequestReportTransactionList({
      */
     const navigateToTransaction = useCallback(
         (activeTransactionID: string) => {
-            const iouAction = getIOUActionForTransactionID(reportActions, activeTransactionID);
-            const backTo = Navigation.getActiveRoute();
-            let reportIDToNavigate = iouAction?.childReportID;
-
-            const routeParams = {
-                reportID: reportIDToNavigate,
-                backTo,
-            } as ReportScreenNavigationProps;
-
-            if (!reportIDToNavigate) {
-                const transaction = sortedTransactions.find((t) => t.transactionID === activeTransactionID);
-                const transactionThreadReport = createTransactionThreadReport({
-                    introSelected,
-                    currentUserLogin: currentUserDetails.email ?? '',
-                    currentUserAccountID: currentUserDetails.accountID,
-                    betas,
-                    iouReport: report,
-                    iouReportAction: iouAction,
-                    transaction,
-                });
-                if (transactionThreadReport) {
-                    reportIDToNavigate = transactionThreadReport.reportID;
-                    routeParams.reportID = reportIDToNavigate;
-                }
-            } else {
-                setOptimisticTransactionThread(reportIDToNavigate, report?.reportID, iouAction?.reportActionID, report?.policyID);
-            }
-
-            // Single transaction report will open in RHP, and we need to find every other report ID for the rest of transactions
-            // to display prev/next arrows in RHP for navigation - use visual order from grouped transactions
-            setActiveTransactionIDs(visualOrderTransactionIDs).then(() => {
-                if (reportIDToNavigate) {
-                    markReportIDAsExpense(reportIDToNavigate);
-                }
-                Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(routeParams));
+            navigateToTransactionThread({
+                transactionID: activeTransactionID,
+                reportActions,
+                report,
+                transaction: sortedTransactions.find((t) => t.transactionID === activeTransactionID),
+                siblingTransactionIDs: visualOrderTransactionIDs,
             });
         },
-        [reportActions, visualOrderTransactionIDs, sortedTransactions, report, markReportIDAsExpense, introSelected, betas, currentUserDetails.email, currentUserDetails.accountID],
+        [navigateToTransactionThread, reportActions, sortedTransactions, report, visualOrderTransactionIDs],
     );
 
     const {amountColumnSize, dateColumnSize, taxAmountColumnSize} = useMemo(() => {
diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx
index b4c41f0352ed..5c0d06ffb66c 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx
@@ -93,7 +93,8 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
         };
     }, [nextTransactionID, parentReportActions, prevTransactionID, transactionIDsList]);
 
-    const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${currentTransaction?.reportID}`);
+    const [prevParentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${prevTransaction?.reportID}`);
+    const [nextParentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${nextTransaction?.reportID}`);
     const [prevThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${prevParentReportAction?.childReportID}`);
     const [nextThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${nextParentReportAction?.childReportID}`);
 
@@ -132,7 +133,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
         }
         // We know that the next thread report exists, it just wasn't fetched to Onyx yet, so we set it optimistically.
         if (!nextThreadReport && nextThreadReportID) {
-            setOptimisticTransactionThread(nextThreadReportID, parentReport?.reportID, nextParentReportAction?.reportActionID, parentReport?.policyID);
+            setOptimisticTransactionThread(nextThreadReportID, nextParentReport?.reportID, nextParentReportAction?.reportActionID, nextParentReport?.policyID);
         }
         // The transaction thread doesn't exist yet, so we should create it
         if (!nextThreadReportID) {
@@ -141,7 +142,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
                 currentUserLogin: currentUserEmail ?? '',
                 currentUserAccountID,
                 betas,
-                iouReport: parentReport,
+                iouReport: nextParentReport,
                 iouReportAction: nextParentReportAction,
                 transaction: nextTransaction,
             });
@@ -168,7 +169,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
         }
         // We know that the previous thread report exists, it just wasn't fetched to Onyx yet, so we set it optimistically.
         if (!prevThreadReport && prevThreadReportID) {
-            setOptimisticTransactionThread(prevThreadReportID, parentReport?.reportID, prevParentReportAction?.reportActionID, parentReport?.policyID);
+            setOptimisticTransactionThread(prevThreadReportID, prevParentReport?.reportID, prevParentReportAction?.reportActionID, prevParentReport?.policyID);
         }
         // The transaction thread doesn't exist yet, so we should create it
         if (!prevThreadReportID) {
@@ -177,7 +178,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
                 currentUserLogin: currentUserEmail ?? '',
                 currentUserAccountID,
                 betas,
-                iouReport: parentReport,
+                iouReport: prevParentReport,
                 iouReportAction: prevParentReportAction,
                 transaction: prevTransaction,
             });
diff --git a/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx b/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx
index 4eb2be1a3425..73d105909a67 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx
@@ -15,8 +15,8 @@ import {
     getFieldViolationTranslation,
     getReportFieldKey,
     getReportFieldMaps,
+    isGroupPolicyExpenseReport as isGroupPolicyExpenseReportUtils,
     isInvoiceReport as isInvoiceReportUtils,
-    isPaidGroupPolicyExpenseReport as isPaidGroupPolicyExpenseReportUtils,
     isReportFieldDisabled,
     isReportFieldDisabledForUser,
     isReportFieldOfTypeTitle,
@@ -119,11 +119,10 @@ function MoneyRequestViewReportFields({report, policy, isCombinedReport = false,
         (reportField) => !isReportFieldDisabled(report, reportField, policy) || reportField.type === CONST.REPORT_FIELD_TYPES.FORMULA,
     );
     const isOnlyTitleFieldEnabled = enabledReportFields.length === 1 && isReportFieldOfTypeTitle(enabledReportFields.at(0));
-    const isPaidGroupPolicyExpenseReport = isPaidGroupPolicyExpenseReportUtils(report);
+    const isGroupPolicyExpenseReport = isGroupPolicyExpenseReportUtils(report);
     const isInvoiceReport = isInvoiceReportUtils(report);
-    const areFieldsEnabledForReport = isInvoiceReport ? policy?.areInvoiceFieldsEnabled : policy?.areReportFieldsEnabled;
 
-    const shouldDisplayReportFields = (isPaidGroupPolicyExpenseReport || isInvoiceReport) && !!areFieldsEnabledForReport && (!isOnlyTitleFieldEnabled || !isCombinedReport);
+    const shouldDisplayReportFields = (isGroupPolicyExpenseReport || isInvoiceReport) && !!policy?.areReportFieldsEnabled && (!isOnlyTitleFieldEnabled || !isCombinedReport);
 
     if (!shouldDisplayReportFields || !sortedPolicyReportFields.length) {
         return null;
diff --git a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
new file mode 100644
index 000000000000..7f415b5060ae
--- /dev/null
+++ b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
@@ -0,0 +1,201 @@
+import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
+import type {ValueOf} from 'type-fest';
+import {PressableWithFeedback} from '@components/Pressable';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import useRootNavigationState from '@hooks/useRootNavigationState';
+import {useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
+import navigationRef from '@libs/Navigation/navigationRef';
+import {isDeletedAction} from '@libs/ReportActionsUtils';
+import {startSpan} from '@libs/telemetry/activeSpans';
+import CONST from '@src/CONST';
+import NAVIGATORS from '@src/NAVIGATORS';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import SCREENS from '@src/SCREENS';
+import type {Report, ReportActions} from '@src/types/onyx';
+import getLastRoute from './getLastRoute';
+import NAVIGATION_TABS from './NAVIGATION_TABS';
+import TabBarItem from './TabBarItem';
+
+function getStringParam(params: unknown, key: string): string | undefined {
+    if (!params || typeof params !== 'object') {
+        return undefined;
+    }
+    for (const [k, v] of Object.entries(params)) {
+        if (k === key && typeof v === 'string') {
+            return v;
+        }
+    }
+    return undefined;
+}
+
+function startNavigateToInboxTabSpan() {
+    startSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB, {
+        name: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
+        op: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
+    });
+}
+
+type InboxTabButtonProps = {
+    selectedTab: ValueOf<typeof NAVIGATION_TABS>;
+    isWideLayout: boolean;
+};
+
+function doesLastReportExistSelector(report: OnyxEntry<Report>) {
+    return !!report?.reportID;
+}
+
+function makeDoesLastReportActionExistSelector(actionID: string | undefined) {
+    return (reportActions: OnyxEntry<ReportActions>) => {
+        const reportAction = actionID ? reportActions?.[actionID] : undefined;
+        return !!reportAction && !isDeletedAction(reportAction);
+    };
+}
+
+type WideInboxTabButtonProps = {
+    selectedTab: ValueOf<typeof NAVIGATION_TABS>;
+    statusIndicatorColor: string | undefined;
+    accessibilityLabel: string;
+};
+
+// The last-viewed report deep link only exists in the wide layout, so the report and report-action
+// Onyx subscriptions live here and are only created when the wide layout is rendered. In the narrow
+// layout tapping Inbox always routes to ROUTES.INBOX, so these subscriptions are never set up.
+function WideInboxTabButton({selectedTab, statusIndicatorColor, accessibilityLabel}: WideInboxTabButtonProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const expensifyIcons = useMemoizedLazyExpensifyIcons(['Inbox']);
+
+    const lastReportRouteReportID = useRootNavigationState((rootState) => {
+        if (!rootState) {
+            return undefined;
+        }
+        const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
+        return getStringParam(route?.params, 'reportID');
+    });
+
+    const lastReportRouteReportActionID = useRootNavigationState((rootState) => {
+        if (!rootState) {
+            return undefined;
+        }
+        const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
+        return getStringParam(route?.params, 'reportActionID');
+    });
+
+    const [doesLastReportExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${lastReportRouteReportID}`, {selector: doesLastReportExistSelector}, [lastReportRouteReportID]);
+
+    const doesLastReportActionExistSelector = makeDoesLastReportActionExistSelector(lastReportRouteReportActionID);
+    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector}, [
+        lastReportRouteReportID,
+        lastReportRouteReportActionID,
+    ]);
+
+    const navigateToChats = () => {
+        if (selectedTab === NAVIGATION_TABS.INBOX) {
+            return;
+        }
+
+        startNavigateToInboxTabSpan();
+
+        if (doesLastReportExist) {
+            // Fetch route params on-demand to avoid storing the full route object in render-time state
+            const rootState = navigationRef.getRootState();
+            const lastRoute = rootState ? getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT) : undefined;
+            if (lastRoute) {
+                const reportID = getStringParam(lastRoute.params, 'reportID');
+                const reportActionID = getStringParam(lastRoute.params, 'reportActionID');
+                const referrer = getStringParam(lastRoute.params, 'referrer');
+                const backTo = getStringParam(lastRoute.params, 'backTo');
+                Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, doesLastReportActionExist ? reportActionID : undefined, referrer, backTo));
+                return;
+            }
+        }
+
+        Navigation.navigate(ROUTES.INBOX);
+    };
+
+    return (
+        <PressableWithFeedback
+            onPress={navigateToChats}
+            role={CONST.ROLE.TAB}
+            accessibilityLabel={accessibilityLabel}
+            accessibilityState={{selected: selectedTab === NAVIGATION_TABS.INBOX}}
+            style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
+            sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
+        >
+            {({hovered}) => (
+                <TabBarItem
+                    icon={expensifyIcons.Inbox}
+                    label={translate('common.inbox')}
+                    isSelected={selectedTab === NAVIGATION_TABS.INBOX}
+                    isHovered={hovered}
+                    statusIndicatorColor={statusIndicatorColor}
+                />
+            )}
+        </PressableWithFeedback>
+    );
+}
+
+function InboxTabButton({selectedTab, isWideLayout}: InboxTabButtonProps) {
+    const styles = useThemeStyles();
+    const theme = useTheme();
+    const {translate} = useLocalize();
+    const {chatTabBrickRoad} = useSidebarOrderedReportsState();
+    const expensifyIcons = useMemoizedLazyExpensifyIcons(['Inbox']);
+
+    let statusIndicatorColor: string | undefined;
+    if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO) {
+        statusIndicatorColor = theme.iconSuccessFill;
+    } else if (chatTabBrickRoad) {
+        statusIndicatorColor = theme.danger;
+    }
+
+    const accessibilityLabel = chatTabBrickRoad ? `${translate('common.inbox')}. ${translate('common.yourReviewIsRequired')}` : translate('common.inbox');
+
+    if (isWideLayout) {
+        return (
+            <WideInboxTabButton
+                selectedTab={selectedTab}
+                statusIndicatorColor={statusIndicatorColor}
+                accessibilityLabel={accessibilityLabel}
+            />
+        );
+    }
+
+    const navigateToChats = () => {
+        if (selectedTab === NAVIGATION_TABS.INBOX) {
+            return;
+        }
+
+        startNavigateToInboxTabSpan();
+        Navigation.navigate(ROUTES.INBOX);
+    };
+
+    return (
+        <PressableWithFeedback
+            onPress={navigateToChats}
+            role={CONST.ROLE.TAB}
+            accessibilityLabel={accessibilityLabel}
+            accessibilityState={{selected: selectedTab === NAVIGATION_TABS.INBOX}}
+            wrapperStyle={styles.flex1}
+            style={styles.navigationTabBarItem}
+            sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
+        >
+            <TabBarItem
+                icon={expensifyIcons.Inbox}
+                label={translate('common.inbox')}
+                isSelected={selectedTab === NAVIGATION_TABS.INBOX}
+                statusIndicatorColor={statusIndicatorColor}
+                numberOfLines={1}
+            />
+        </PressableWithFeedback>
+    );
+}
+
+export default InboxTabButton;
diff --git a/src/components/Navigation/NavigationTabBar/index.tsx b/src/components/Navigation/NavigationTabBar/index.tsx
index b6408aa3b02d..12701cdab400 100644
--- a/src/components/Navigation/NavigationTabBar/index.tsx
+++ b/src/components/Navigation/NavigationTabBar/index.tsx
@@ -1,6 +1,5 @@
 import React from 'react';
 import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import FloatingCameraButton from '@components/FloatingCameraButton';
 import FloatingGPSButton from '@components/FloatingGPSButton';
@@ -11,26 +10,16 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
-import useRootNavigationState from '@hooks/useRootNavigationState';
-import {useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
 import useStyleUtils from '@hooks/useStyleUtils';
-import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import interceptAnonymousUser from '@libs/interceptAnonymousUser';
 import Navigation from '@libs/Navigation/Navigation';
-import navigationRef from '@libs/Navigation/navigationRef';
-import {isDeletedAction} from '@libs/ReportActionsUtils';
-import {startSpan} from '@libs/telemetry/activeSpans';
-import type {ReportsSplitNavigatorParamList} from '@navigation/types';
 import NavigationTabBarAvatar from '@pages/inbox/sidebar/NavigationTabBarAvatar';
 import NavigationTabBarFloatingActionButton from '@pages/inbox/sidebar/NavigationTabBarFloatingActionButton';
 import CONST from '@src/CONST';
-import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
-import SCREENS from '@src/SCREENS';
-import type {Report, ReportActions} from '@src/types/onyx';
-import getLastRoute from './getLastRoute';
+import InboxTabButton from './InboxTabButton';
 import NAVIGATION_TABS from './NAVIGATION_TABS';
 import SearchTabButton from './SearchTabButton';
 import TabBarItem from './TabBarItem';
@@ -41,55 +30,16 @@ type NavigationTabBarProps = {
     shouldShowFloatingButtons?: boolean;
 };
 
-function doesLastReportExistSelector(report: OnyxEntry<Report>) {
-    return !!report?.reportID;
-}
-
 function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: NavigationTabBarProps) {
-    const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const {chatTabBrickRoad} = useSidebarOrderedReportsState();
     const [isDebugModeEnabled] = useOnyx(ONYXKEYS.IS_DEBUG_MODE_ENABLED);
-    const expensifyIcons = useMemoizedLazyExpensifyIcons(['ExpensifyAppIcon', 'Home', 'Inbox']);
-
-    const lastReportRouteReportID = useRootNavigationState((rootState) => {
-        if (!rootState) {
-            return undefined;
-        }
-        const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
-        return (route?.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT])?.reportID;
-    });
-
-    const lastReportRouteReportActionID = useRootNavigationState((rootState) => {
-        if (!rootState) {
-            return undefined;
-        }
-        const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
-        return (route?.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT])?.reportActionID;
-    });
-
-    const [doesLastReportExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${lastReportRouteReportID}`, {selector: doesLastReportExistSelector}, [lastReportRouteReportID]);
-
-    const doesLastReportActionExistSelector = (reportActions: OnyxEntry<ReportActions>) => {
-        const reportAction = lastReportRouteReportActionID ? reportActions?.[lastReportRouteReportActionID] : undefined;
-        return !!reportAction && !isDeletedAction(reportAction);
-    };
-    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector});
+    const expensifyIcons = useMemoizedLazyExpensifyIcons(['ExpensifyAppIcon', 'Home']);
 
     const {shouldUseNarrowLayout} = useResponsiveLayout();
 
     const StyleUtils = useStyleUtils();
 
-    let inboxStatusIndicatorColor: string | undefined;
-    if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO) {
-        inboxStatusIndicatorColor = theme.iconSuccessFill;
-    } else if (chatTabBrickRoad) {
-        inboxStatusIndicatorColor = theme.danger;
-    }
-
-    const inboxAccessibilityState = {selected: selectedTab === NAVIGATION_TABS.INBOX};
-
     const navigateToNewDotHome = () => {
         if (selectedTab === NAVIGATION_TABS.HOME) {
             return;
@@ -97,30 +47,6 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
         Navigation.navigate(ROUTES.HOME);
     };
 
-    const navigateToChats = () => {
-        if (selectedTab === NAVIGATION_TABS.INBOX) {
-            return;
-        }
-
-        startSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB, {
-            name: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
-            op: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
-        });
-
-        if (!shouldUseNarrowLayout && doesLastReportExist) {
-            // Fetch route params on-demand to avoid storing the full route object in render-time state
-            const rootState = navigationRef.getRootState();
-            const lastRoute = rootState ? getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT) : undefined;
-            if (lastRoute) {
-                const {reportID, reportActionID, referrer, backTo} = lastRoute.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT];
-                Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, doesLastReportActionExist ? reportActionID : undefined, referrer, backTo));
-                return;
-            }
-        }
-
-        Navigation.navigate(ROUTES.INBOX);
-    };
-
     const navigateToSettings = () => {
         if (selectedTab === NAVIGATION_TABS.SETTINGS) {
             return;
@@ -174,24 +100,10 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
                                 />
                             )}
                         </PressableWithFeedback>
-                        <PressableWithFeedback
-                            onPress={navigateToChats}
-                            role={CONST.ROLE.TAB}
-                            accessibilityLabel={chatTabBrickRoad ? `${translate('common.inbox')}. ${translate('common.yourReviewIsRequired')}` : translate('common.inbox')}
-                            accessibilityState={inboxAccessibilityState}
-                            style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
-                            sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
-                        >
-                            {({hovered}) => (
-                                <TabBarItem
-                                    icon={expensifyIcons.Inbox}
-                                    label={translate('common.inbox')}
-                                    isSelected={selectedTab === NAVIGATION_TABS.INBOX}
-                                    isHovered={hovered}
-                                    statusIndicatorColor={inboxStatusIndicatorColor}
-                                />
-                            )}
-                        </PressableWithFeedback>
+                        <InboxTabButton
+                            selectedTab={selectedTab}
+                            isWideLayout
+                        />
                         <SearchTabButton
                             selectedTab={selectedTab}
                             isWideLayout
@@ -235,23 +147,10 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
                         isSelected={selectedTab === NAVIGATION_TABS.HOME}
                     />
                 </PressableWithFeedback>
-                <PressableWithFeedback
-                    onPress={navigateToChats}
-                    role={CONST.ROLE.TAB}
-                    accessibilityLabel={chatTabBrickRoad ? `${translate('common.inbox')}. ${translate('common.yourReviewIsRequired')}` : translate('common.inbox')}
-                    accessibilityState={inboxAccessibilityState}
-                    wrapperStyle={styles.flex1}
-                    style={styles.navigationTabBarItem}
-                    sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
-                >
-                    <TabBarItem
-                        icon={expensifyIcons.Inbox}
-                        label={translate('common.inbox')}
-                        isSelected={selectedTab === NAVIGATION_TABS.INBOX}
-                        statusIndicatorColor={inboxStatusIndicatorColor}
-                        numberOfLines={1}
-                    />
-                </PressableWithFeedback>
+                <InboxTabButton
+                    selectedTab={selectedTab}
+                    isWideLayout={false}
+                />
                 <SearchTabButton
                     selectedTab={selectedTab}
                     isWideLayout={false}
diff --git a/src/components/Navigation/QuickCreationActionsBar/index.tsx b/src/components/Navigation/QuickCreationActionsBar/index.tsx
index 1b7253be6e06..b48df3c493b0 100644
--- a/src/components/Navigation/QuickCreationActionsBar/index.tsx
+++ b/src/components/Navigation/QuickCreationActionsBar/index.tsx
@@ -17,7 +17,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {startDistanceRequest, startMoneyRequest} from '@libs/actions/IOU/MoneyRequest';
 import {createNewReport} from '@libs/actions/Report';
 import interceptAnonymousUser from '@libs/interceptAnonymousUser';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import getCreateReportRoute, {getReportsRootRoute, navigateToCreateReportWorkspaceSelection} from '@libs/Navigation/helpers/getCreateReportRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import {openTravelDotLink} from '@libs/openTravelDotLink';
@@ -27,7 +26,7 @@ import {generateReportID, hasViolations as hasViolationsReportUtils} from '@libs
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import {primaryLoginSelector} from '@src/selectors/Account';
 import type * as OnyxTypes from '@src/types/onyx';
 
@@ -132,15 +131,13 @@ function QuickCreationActionsBar() {
                     const freshReportID = generateReportID();
                     const freshTransactionID = generateReportID();
                     Navigation.navigate(
-                        createDynamicRoute(
-                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                action: CONST.IOU.ACTION.CREATE,
-                                iouType: CONST.IOU.TYPE.CREATE,
-                                transactionID: freshTransactionID,
-                                reportID: freshReportID,
-                                upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                            }),
-                        ),
+                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                            action: CONST.IOU.ACTION.CREATE,
+                            iouType: CONST.IOU.TYPE.CREATE,
+                            transactionID: freshTransactionID,
+                            reportID: freshReportID,
+                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                        }),
                     );
                     return;
                 }
diff --git a/src/components/ReportActionItem/MoneyReportView.tsx b/src/components/ReportActionItem/MoneyReportView.tsx
index 715931d2adc5..1e8b277803c6 100644
--- a/src/components/ReportActionItem/MoneyReportView.tsx
+++ b/src/components/ReportActionItem/MoneyReportView.tsx
@@ -33,8 +33,8 @@ import {
     getReportFieldMaps,
     hasUpdatedTotal,
     isClosedExpenseReportWithNoExpenses as isClosedExpenseReportWithNoExpensesReportUtils,
+    isGroupPolicyExpenseReport as isGroupPolicyExpenseReportUtils,
     isInvoiceReport as isInvoiceReportUtils,
-    isPaidGroupPolicyExpenseReport as isPaidGroupPolicyExpenseReportUtils,
     isReportFieldDisabled,
     isReportFieldDisabledForUser,
     isReportFieldOfTypeTitle,
@@ -149,13 +149,12 @@ function MoneyReportView({
     );
     const isOnlyTitleFieldEnabled = enabledReportFields.length === 1 && isReportFieldOfTypeTitle(enabledReportFields.at(0));
     const isClosedExpenseReportWithNoExpenses = isClosedExpenseReportWithNoExpensesReportUtils(report);
-    const isPaidGroupPolicyExpenseReport = isPaidGroupPolicyExpenseReportUtils(report);
+    const isGroupPolicyExpenseReport = isGroupPolicyExpenseReportUtils(report);
     const isInvoiceReport = isInvoiceReportUtils(report);
 
-    const areFieldsEnabledForReport = isInvoiceReport ? policy?.areInvoiceFieldsEnabled : policy?.areReportFieldsEnabled;
     const shouldShowReportField =
         !isClosedExpenseReportWithNoExpenses &&
-        (isPaidGroupPolicyExpenseReport || isInvoiceReport) &&
+        (isGroupPolicyExpenseReport || isInvoiceReport) &&
         (!isCombinedReport || !isOnlyTitleFieldEnabled) &&
         !sortedPolicyReportFields.every(shouldHideSingleReportField);
 
@@ -184,8 +183,8 @@ function MoneyReportView({
                 {shouldShowAnimatedBackground && <AnimatedEmptyStateBackground />}
                 {!isClosedExpenseReportWithNoExpenses && (
                     <>
-                        {(isPaidGroupPolicyExpenseReport || isInvoiceReport) &&
-                            areFieldsEnabledForReport &&
+                        {(isGroupPolicyExpenseReport || isInvoiceReport) &&
+                            !!policy?.areReportFieldsEnabled &&
                             (!isCombinedReport || !isOnlyTitleFieldEnabled) &&
                             sortedPolicyReportFields.map((reportField) => {
                                 if (shouldHideSingleReportField(reportField)) {
diff --git a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
index 8a635a558816..36129c2e7247 100644
--- a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
@@ -51,7 +51,7 @@ import {
     canUserPerformWriteAction as canUserPerformWriteActionReportUtils,
     getCreationReportErrors,
     isInvoiceReport,
-    isPaidGroupPolicy,
+    isReportInGroupPolicy,
     isTrackExpenseReportNew,
 } from '@libs/ReportUtils';
 import trackExpenseCreationError from '@libs/telemetry/trackExpenseCreationError';
@@ -347,7 +347,7 @@ function MoneyRequestReceiptView({
         !isTransactionScanning &&
         (hasReceipt || !!receiptRequiredViolation || !!itemizedReceiptRequiredViolation || !!customRulesViolation) &&
         !!(receiptViolations.length || didReceiptScanSucceed) &&
-        isPaidGroupPolicy(report);
+        isReportInGroupPolicy(report);
     const shouldShowReceiptAudit = !isInvoice && (shouldShowReceiptEmptyState || hasReceipt || hasReceiptUploadError);
 
     const fallbackReceiptError = useMemo(() => {
diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx
index c9d7b8684d70..dc4acd7818b0 100644
--- a/src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx
+++ b/src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx
@@ -1,4 +1,5 @@
 import {delegateEmailSelector} from '@selectors/Account';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import AnimatedSubmitButton from '@components/AnimatedSubmitButton';
 import useConfirmModal from '@hooks/useConfirmModal';
@@ -9,7 +10,7 @@ import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
 import usePermissions from '@hooks/usePermissions';
 import useReportTransactionsCollection from '@hooks/useReportTransactionsCollection';
-import {hasViolations as hasViolationsReportUtils} from '@libs/ReportUtils';
+import {hasViolations as hasViolationsReportUtils, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import {submitReport} from '@userActions/IOU/ReportWorkflow';
 import {markPendingRTERTransactionsAsCash} from '@userActions/Transaction';
@@ -40,6 +41,7 @@ function SubmitActionButton({iouReportID, isSubmittingAnimationRunning, stopAnim
     const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END);
     const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
     const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
     const [delegateEmail] = useOnyx(ONYXKEYS.ACCOUNT, {selector: delegateEmailSelector});
     const {isOffline} = useNetwork();
     const reportTransactionsCollection = useReportTransactionsCollection(iouReportID);
@@ -56,11 +58,16 @@ function SubmitActionButton({iouReportID, isSubmittingAnimationRunning, stopAnim
     };
 
     const confirmPendingRTERAndProceed = useConfirmPendingRTERAndProceed(hasAnyPendingRTERViolation, handleMarkPendingRTERTransactionsAsCash);
-
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        isTrackIntentUser,
+        report: iouReport,
+        policy,
+    });
     return (
         <AnimatedSubmitButton
             success
-            text={translate('common.submit')}
+            text={shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('common.submit')}
+            isMarkAsDone={shouldUseMarkAsDoneCopy}
             onPress={() => {
                 if (hasOnlyPendingCardTransactions(transactions)) {
                     showPendingCardTransactionsBlockModal(showConfirmModal, translate);
diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 3f569d589e51..2777962ff331 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -57,7 +57,6 @@ import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getRateFromMerchant} from '@libs/MergeTransactionUtils';
 import {isBillableEnabledOnPolicy, isSingleTransactionReport} from '@libs/MoneyRequestReportUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import {hasEnabledOptions} from '@libs/OptionsListUtils';
 import Parser from '@libs/Parser';
 import {
@@ -65,8 +64,10 @@ import {
     getLengthOfTag,
     getPerDiemCustomUnit,
     getPolicyByCustomUnitID,
+    getQBOVendorByID,
     getTagLists,
     hasDependentTags as hasDependentTagsPolicyUtils,
+    hasVendorFeature,
     isAttendeeTrackingEnabled,
     isGroupPolicyByType,
     isPolicyAccessible,
@@ -85,8 +86,8 @@ import {
     isExpenseReport,
     isInvoiceReport,
     isOpenReport,
-    isPaidGroupPolicy,
     isReportApproved,
+    isReportInGroupPolicy,
     isSettled as isSettledReportUtils,
     isTrackExpenseReportNew,
     shouldEnableNegative,
@@ -131,7 +132,7 @@ import AnimatedEmptyStateBackground from '@pages/inbox/report/AnimatedEmptyState
 import CONST from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import type {TransactionPendingFieldsKey} from '@src/types/onyx/Transaction';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
@@ -461,6 +462,10 @@ function MoneyRequestView({
         });
     const shouldShowAttendees = shouldShowAttendeesTransactionUtils(iouType, policy);
 
+    const transactionVendor = transaction?.comment?.vendor;
+    const transactionVendorName = getQBOVendorByID(policy, transactionVendor?.externalID)?.name ?? '';
+    const shouldShowVendor = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING)) && !(updatedTransaction?.reimbursable ?? !!transactionReimbursable) && !isInvoice;
+
     const tripID = getTripIDFromTransactionParentReportID(parentReport?.parentReportID);
     const shouldShowViewTripDetails = hasReservationList(transaction) && !!tripID;
 
@@ -488,7 +493,7 @@ function MoneyRequestView({
     const tripRoomName = tripRoomInfo?.name;
     const shouldShowTripRoomLink = !!tripRoomReportID && !!tripRoomName;
 
-    const {getViolationsForField} = useViolations(transactionViolations ?? [], isTransactionScanning || !isPaidGroupPolicy(transactionThreadReport));
+    const {getViolationsForField} = useViolations(transactionViolations ?? [], isTransactionScanning || !isReportInGroupPolicy(transactionThreadReport));
     const hasViolations = (field: ViolationField, data?: OnyxTypes.TransactionViolation['data'], policyHasDependentTags = false, tagValue?: string): boolean =>
         getViolationsForField(field, data, policyHasDependentTags, tagValue).length > 0;
     const isMarkAsCash = parentReport && currentUserEmailParam ? isMarkAsCashActionForTransaction(currentUserEmailParam, parentReport, transactionViolations, policy) : false;
@@ -815,15 +820,13 @@ function MoneyRequestView({
                         if (isTrackExpense) {
                             if (shouldNavigateToUpgradePath && transactionThreadReport) {
                                 Navigation.navigate(
-                                    createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                            action: CONST.IOU.ACTION.EDIT,
-                                            iouType,
-                                            transactionID: transaction.transactionID,
-                                            reportID: transactionThreadReport?.reportID,
-                                            upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
-                                        }),
-                                    ),
+                                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                        action: CONST.IOU.ACTION.EDIT,
+                                        iouType,
+                                        transactionID: transaction.transactionID,
+                                        reportID: transactionThreadReport?.reportID,
+                                        upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
+                                    }),
                                 );
                                 return;
                             }
@@ -1121,33 +1124,41 @@ function MoneyRequestView({
                             onPress={() => {
                                 if (shouldNavigateToUpgradePath && transactionThreadReport) {
                                     Navigation.navigate(
-                                        createDynamicRoute(
-                                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                                action: CONST.IOU.ACTION.EDIT,
+                                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                            action: CONST.IOU.ACTION.EDIT,
+                                            iouType,
+                                            transactionID: transaction.transactionID,
+                                            reportID: transactionThreadReport?.reportID,
+                                            upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                                            backTo: ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
+                                                CONST.IOU.ACTION.EDIT,
                                                 iouType,
-                                                transactionID: transaction.transactionID,
-                                                reportID: transactionThreadReport?.reportID,
-                                                upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                                            }),
-                                        ),
+                                                transaction.transactionID,
+                                                transactionThreadReport?.reportID,
+                                                Navigation.getActiveRoute(),
+                                            ),
+                                        }),
                                     );
                                 } else if (!policy && shouldSelectPolicy) {
                                     Navigation.navigate(
                                         ROUTES.SET_DEFAULT_WORKSPACE.getRoute(
-                                            createDynamicRoute(
-                                                DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
-                                                    CONST.IOU.ACTION.EDIT,
-                                                    iouType,
-                                                    transaction.transactionID,
-                                                    transactionThreadReport?.reportID,
-                                                ),
+                                            ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
+                                                CONST.IOU.ACTION.EDIT,
+                                                iouType,
+                                                transaction.transactionID,
+                                                transactionThreadReport?.reportID,
+                                                Navigation.getActiveRoute(),
                                             ),
                                         ),
                                     );
                                 } else {
                                     Navigation.navigate(
-                                        createDynamicRoute(
-                                            DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID),
+                                        ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
+                                            CONST.IOU.ACTION.EDIT,
+                                            iouType,
+                                            transaction.transactionID,
+                                            transactionThreadReport?.reportID,
+                                            Navigation.getActiveRoute(),
                                         ),
                                     );
                                 }
@@ -1159,6 +1170,26 @@ function MoneyRequestView({
                         />
                     </OfflineWithFeedback>
                 )}
+                {shouldShowVendor && (
+                    <OfflineWithFeedback pendingAction={getPendingFieldAction('vendor')}>
+                        <MenuItemWithTopDescription
+                            description={translate('common.vendor')}
+                            title={transactionVendorName}
+                            numberOfLinesTitle={2}
+                            interactive={canEdit}
+                            shouldShowRightIcon={canEdit}
+                            titleStyle={styles.flex1}
+                            onPress={() => {
+                                if (!transactionThreadReport?.reportID) {
+                                    return;
+                                }
+                                Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_VENDOR.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport.reportID));
+                            }}
+                            brickRoadIndicator={getErrorForField('vendor') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
+                            errorText={getErrorForField('vendor')}
+                        />
+                    </OfflineWithFeedback>
+                )}
                 {shouldShowTag && tagList}
                 {!!shouldShowCard && (
                     <OfflineWithFeedback pendingAction={getPendingFieldAction('cardID')}>
@@ -1189,8 +1220,12 @@ function MoneyRequestView({
                                 }
 
                                 Navigation.navigate(
-                                    createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID),
+                                    ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(
+                                        CONST.IOU.ACTION.EDIT,
+                                        iouType,
+                                        transaction.transactionID,
+                                        transactionThreadReport?.reportID,
+                                        getReportRHPActiveRoute(),
                                     ),
                                 );
                             }}
@@ -1217,8 +1252,12 @@ function MoneyRequestView({
                                 }
 
                                 Navigation.navigate(
-                                    createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID),
+                                    ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(
+                                        CONST.IOU.ACTION.EDIT,
+                                        iouType,
+                                        transaction.transactionID,
+                                        transactionThreadReport?.reportID,
+                                        getReportRHPActiveRoute(),
                                     ),
                                 );
                             }}
@@ -1254,11 +1293,7 @@ function MoneyRequestView({
                             style={[styles.moneyRequestMenuItem]}
                             titleStyle={styles.flex1}
                             onPress={() => {
-                                Navigation.navigate(
-                                    createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_ATTENDEE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID),
-                                    ),
-                                );
+                                Navigation.navigate(ROUTES.MONEY_REQUEST_ATTENDEE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID));
                             }}
                             brickRoadIndicator={getErrorForField('attendees') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
                             errorText={getErrorForField('attendees')}
@@ -1339,15 +1374,13 @@ function MoneyRequestView({
                                 }
                                 if (shouldNavigateToUpgradePath) {
                                     Navigation.navigate(
-                                        createDynamicRoute(
-                                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                                iouType,
-                                                action: CONST.IOU.ACTION.EDIT,
-                                                transactionID: transaction?.transactionID,
-                                                reportID: transactionThreadReport?.reportID,
-                                                upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                                            }),
-                                        ),
+                                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                            iouType,
+                                            action: CONST.IOU.ACTION.EDIT,
+                                            transactionID: transaction?.transactionID,
+                                            reportID: transactionThreadReport?.reportID,
+                                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                                        }),
                                     );
                                     return;
                                 }
diff --git a/src/components/ReportWelcomeText.tsx b/src/components/ReportWelcomeText.tsx
index 4ba34b4a3501..09ebc1a84af4 100644
--- a/src/components/ReportWelcomeText.tsx
+++ b/src/components/ReportWelcomeText.tsx
@@ -1,6 +1,8 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import {View} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useEnvironment from '@hooks/useEnvironment';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
@@ -55,6 +57,7 @@ function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) {
     const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`);
     const isReportArchived = useReportIsArchived(report?.reportID);
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
     const isConciergeChat = isConciergeChatReport(report, conciergeReportID);
     const isChatRoom = isChatRoomReportUtils(report);
     const isSelfDM = isSelfDMReportUtils(report);
@@ -65,6 +68,7 @@ function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) {
     const participantAccountIDs = getParticipantsAccountIDsForDisplay(report, undefined, true, true, reportMetadata);
     const moneyRequestOptions = temporary_getMoneyRequestOptions(report, policy, participantAccountIDs, betas, isReportArchived, isRestrictedToPreferredPolicy);
     const policyName = getPolicyName({report});
+    const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
 
     const filteredOptions = moneyRequestOptions.filter(
         (
@@ -125,6 +129,8 @@ function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) {
         reportDetailsLink,
         shouldShowUsePlusButtonText,
         additionalText,
+        isTrackIntentUser: !!isTrackIntentUser,
+        currentUserAccountID,
     });
 
     return (
diff --git a/src/components/ScrollOffsetContextProvider.tsx b/src/components/ScrollOffsetContextProvider.tsx
index f051497606d4..d85691307f2e 100644
--- a/src/components/ScrollOffsetContextProvider.tsx
+++ b/src/components/ScrollOffsetContextProvider.tsx
@@ -61,21 +61,25 @@ function getKey(route: PlatformStackRouteProp<ParamListBase> | NavigationPartial
 
 function ScrollOffsetContextProvider({children}: ScrollOffsetContextProviderProps) {
     const [priorityMode] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
+    const [inboxTab] = useOnyx(ONYXKEYS.NVP_INBOX_TAB);
     const scrollOffsetsRef = useRef<Record<string, number>>({});
     const previousPriorityMode = usePrevious(priorityMode);
+    const previousInboxTab = usePrevious(inboxTab);
 
     useEffect(() => {
-        if (previousPriorityMode === null || previousPriorityMode === priorityMode) {
+        const priorityModeChanged = previousPriorityMode !== null && previousPriorityMode !== priorityMode;
+        const inboxTabChanged = previousInboxTab !== null && previousInboxTab !== inboxTab;
+        if (!priorityModeChanged && !inboxTabChanged) {
             return;
         }
 
-        // If the priority mode changes, we need to clear the scroll offsets for the home and search screens because it affects the size of the elements and scroll positions wouldn't be correct.
+        // If the priority mode or inbox tab changes, we need to clear the scroll offsets for the home and search screens because it affects the size of the elements and scroll positions wouldn't be correct.
         for (const key of Object.keys(scrollOffsetsRef.current)) {
             if (key.includes(SCREENS.INBOX) || key.includes(SCREENS.SEARCH.ROOT)) {
                 delete scrollOffsetsRef.current[key];
             }
         }
-    }, [priorityMode, previousPriorityMode]);
+    }, [priorityMode, previousPriorityMode, inboxTab, previousInboxTab]);
 
     const saveScrollOffset: ScrollOffsetContextValue['saveScrollOffset'] = useCallback((route, scrollOffset) => {
         scrollOffsetsRef.current[getKey(route)] = scrollOffset;
diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx
index b2cb1b5f5293..634925cab1f1 100644
--- a/src/components/Search/SearchAutocompleteList.tsx
+++ b/src/components/Search/SearchAutocompleteList.tsx
@@ -68,8 +68,9 @@ type SearchAutocompleteListProps = {
     /** Whether to subscribe to KeyboardShortcut arrow keys events */
     shouldSubscribeToArrowKeyEvents?: boolean;
 
-    /** Callback to highlight (e.g. scroll to) the first matched item in the list. */
-    onHighlightFirstItem?: () => void;
+    /** Whether to highlight the first matched result so Enter selects it. Only the SearchRouter (Cmd+K) uses this;
+     *  the search page input keeps focus on the search-query row to match production behavior. */
+    shouldHighlightFirstItem?: boolean;
 
     /** Ref for the external text input */
     textInputRef?: RefObject<AnimatedTextInputRef | null>;
@@ -145,7 +146,7 @@ function SearchAutocompleteList({
     getAdditionalSections,
     onListItemPress,
     shouldSubscribeToArrowKeyEvents = true,
-    onHighlightFirstItem,
+    shouldHighlightFirstItem = false,
     textInputRef,
     autocompleteSubstitutions,
     ref,
@@ -273,8 +274,8 @@ function SearchAutocompleteList({
                 // effect can re-fire and correctly focus the first focusable item (skipping section headers).
                 hasSetInitialFocusRef.current = false;
             } else {
-                // When query changes to a non-empty value, focus on the search query item (index 0) and scroll to top
-                // onHighlightFirstItem will switch focus to the first result when there's a good match
+                // When query changes to a non-empty value, focus on the search query item (index 0) and scroll to top.
+                // The highlight effect below switches focus to the first result when there's a good match.
                 innerListRef.current?.updateAndScrollToFocusedIndex(0, true);
             }
         }
@@ -570,8 +571,6 @@ function SearchAutocompleteList({
         reports,
     ]);
 
-    const sectionItemText = sections?.at(1)?.data?.[0]?.text ?? '';
-    const normalizedReferenceText = sectionItemText.toLowerCase();
     const trimmedAutocompleteQueryValue = autocompleteQueryValue.trim();
     const isLoading = !isRecentSearchesDataLoaded;
     const suggestionsAnnouncement = suggestionsCount > 0 ? translate('search.suggestionsAvailable', {count: suggestionsCount}, trimmedAutocompleteQueryValue) : '';
@@ -581,29 +580,37 @@ function SearchAutocompleteList({
     const shouldAnnounceNoResults = !isLoading && suggestionsCount === 0 && !!trimmedAutocompleteQueryValue;
     useDebouncedAccessibilityAnnouncement(noResultsFoundText, shouldAnnounceNoResults, autocompleteQueryValue);
 
-    const firstRecentReportKey = styledRecentReports.at(0)?.keyForList;
+    // Locate the first recent report row in the order it is actually rendered. The two-section switcher sorts the
+    // local "Recent chats" rows by a frozen rank, so the rendered order can differ from styledRecentReports (the
+    // unsorted combined local + server list). Walking sections keeps the focused row, its reference text, and the
+    // initially focused key all pointing at the first row the user actually sees.
+    const recentReportKeys = new Set(styledRecentReports.map((report) => report.keyForList));
+    let firstRecentReportKey: string | undefined;
+    let firstRecentReportText = '';
     let firstRecentReportFlatIndex = -1;
-    if (firstRecentReportKey) {
-        let flatIndex = 0;
-        for (const section of sections) {
-            const hasData = (section.data?.length ?? 0) > 0;
-            const hasHeader = hasData && (section.title !== undefined || ('customHeader' in section && section.customHeader !== undefined));
-            if (hasHeader) {
-                flatIndex++;
-            }
-            for (const item of section.data ?? []) {
-                if (item.keyForList === firstRecentReportKey) {
-                    firstRecentReportFlatIndex = flatIndex;
-                    break;
-                }
-                flatIndex++;
-            }
-            if (firstRecentReportFlatIndex !== -1) {
+    let flatIndex = 0;
+    for (const section of sections) {
+        const hasData = (section.data?.length ?? 0) > 0;
+        const hasHeader = hasData && (section.title !== undefined || ('customHeader' in section && section.customHeader !== undefined));
+        if (hasHeader) {
+            flatIndex++;
+        }
+        for (const item of section.data ?? []) {
+            if (item.keyForList && recentReportKeys.has(item.keyForList)) {
+                firstRecentReportKey = item.keyForList;
+                firstRecentReportText = item.text ?? '';
+                firstRecentReportFlatIndex = flatIndex;
                 break;
             }
+            flatIndex++;
+        }
+        if (firstRecentReportFlatIndex !== -1) {
+            break;
         }
     }
 
+    const normalizedReferenceText = firstRecentReportText.toLowerCase();
+
     // When options initialize after the list is already mounted, initiallyFocusedItemKey has no effect
     // because useState(initialFocusedIndex) in useArrowKeyFocusManager only reads the initial value.
     // Imperatively focus the first recent report once options become available (desktop only).
@@ -619,10 +626,13 @@ function SearchAutocompleteList({
     useEffect(() => {
         const targetText = autocompleteQueryValue;
 
-        if (shouldHighlight(normalizedReferenceText, targetText)) {
-            onHighlightFirstItem?.();
+        if (!shouldHighlightFirstItem || firstRecentReportFlatIndex === -1 || !shouldHighlight(normalizedReferenceText, targetText)) {
+            return;
         }
-    }, [autocompleteQueryValue, onHighlightFirstItem, normalizedReferenceText]);
+        // Focus the header-aware flat index of the first result. A fixed index (e.g. searchQueryItems.length)
+        // lands on the "Recent chats" section header row after the two-section switcher was introduced.
+        innerListRef.current?.updateAndScrollToFocusedIndex(firstRecentReportFlatIndex, true);
+    }, [autocompleteQueryValue, firstRecentReportFlatIndex, normalizedReferenceText, shouldHighlightFirstItem]);
 
     if (isLoading) {
         return (
diff --git a/src/components/Search/SearchList/BaseSearchList/index.native.tsx b/src/components/Search/SearchList/BaseSearchList/index.native.tsx
index ad5d017c708f..a6955e67be8b 100644
--- a/src/components/Search/SearchList/BaseSearchList/index.native.tsx
+++ b/src/components/Search/SearchList/BaseSearchList/index.native.tsx
@@ -18,6 +18,8 @@ function BaseSearchList({
     onViewableItemsChanged,
     onLayout,
     contentContainerStyle,
+    stickyHeaderIndices,
+    getItemType,
 }: BaseSearchListProps) {
     const renderItemWithoutKeyboardFocus = useCallback(
         ({item, index}: {item: SearchListItem; index: number}) => {
@@ -43,6 +45,8 @@ function BaseSearchList({
             drawDistance={250}
             contentContainerStyle={contentContainerStyle}
             maintainVisibleContentPosition={{disabled: true}}
+            stickyHeaderIndices={stickyHeaderIndices}
+            getItemType={getItemType}
         />
     );
 }
diff --git a/src/components/Search/SearchList/BaseSearchList/index.tsx b/src/components/Search/SearchList/BaseSearchList/index.tsx
index cf25b14b1f8b..88c05b5ea273 100644
--- a/src/components/Search/SearchList/BaseSearchList/index.tsx
+++ b/src/components/Search/SearchList/BaseSearchList/index.tsx
@@ -62,6 +62,8 @@ function BaseSearchList({
     selectedTransactions,
     isAttendeesEnabledForMovingPolicy,
     nonPersonalAndWorkspaceCards,
+    stickyHeaderIndices,
+    getItemType,
 }: BaseSearchListProps) {
     const hasKeyBeenPressed = useRef(false);
     const isFocused = useIsFocused();
@@ -183,6 +185,8 @@ function BaseSearchList({
             drawDistance={250}
             contentContainerStyle={contentContainerStyle}
             maintainVisibleContentPosition={{disabled: true}}
+            stickyHeaderIndices={stickyHeaderIndices}
+            getItemType={getItemType}
         />
     );
 }
diff --git a/src/components/Search/SearchList/BaseSearchList/types.ts b/src/components/Search/SearchList/BaseSearchList/types.ts
index 63f60b5da280..f923f8cb736b 100644
--- a/src/components/Search/SearchList/BaseSearchList/types.ts
+++ b/src/components/Search/SearchList/BaseSearchList/types.ts
@@ -17,6 +17,7 @@ type BaseSearchListProps = Pick<
     | 'keyExtractor'
     | 'showsVerticalScrollIndicator'
     | 'onLayout'
+    | 'stickyHeaderIndices'
 > & {
     /** The data to display in the list */
     data: SearchListItem[];
@@ -50,6 +51,9 @@ type BaseSearchListProps = Pick<
 
     /** Non-personal and workspace cards for triggering re-render via extraData */
     nonPersonalAndWorkspaceCards?: CardList;
+
+    /** Function to determine item type for FlashList recycling */
+    getItemType?: (item: SearchListItem, index: number) => string | number | undefined;
 };
 
 export default BaseSearchListProps;
diff --git a/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx b/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
index a8687c6f60ae..7d7c6f015c9e 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
@@ -7,7 +7,9 @@ import ActionCell from '.';
 import type {ActionCellProps} from '.';
 import actionTranslationsMap from './actionTranslationsMap';
 
-function DeferredActionCell(actionCellProps: ActionCellProps) {
+type DeferredActionCellProps = ActionCellProps & {isMarkAsDone?: boolean};
+
+function DeferredActionCell(actionCellProps: DeferredActionCellProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const shouldRender = useDeferredValue(true, false);
@@ -16,7 +18,12 @@ function DeferredActionCell(actionCellProps: ActionCellProps) {
         const action = actionCellProps.action ?? CONST.SEARCH.ACTION_TYPES.VIEW;
         const shouldUseViewAction = action === CONST.SEARCH.ACTION_TYPES.VIEW || action === CONST.SEARCH.ACTION_TYPES.PAID || action === CONST.SEARCH.ACTION_TYPES.DONE;
         const isSuccess = !shouldUseViewAction && action !== CONST.SEARCH.ACTION_TYPES.UNDELETE;
-        const text = shouldUseViewAction ? translate(actionTranslationsMap[CONST.SEARCH.ACTION_TYPES.VIEW]) : translate(actionTranslationsMap[action]);
+        let text: string;
+        if (shouldUseViewAction) {
+            text = translate(actionTranslationsMap[CONST.SEARCH.ACTION_TYPES.VIEW]);
+        } else {
+            text = actionCellProps.isMarkAsDone ? translate('common.done') : translate(actionTranslationsMap[action]);
+        }
 
         return (
             <Button
diff --git a/src/components/Search/SearchList/ListItem/ActionCell/PayActionCell.tsx b/src/components/Search/SearchList/ListItem/ActionCell/PayActionCell.tsx
index b30b63392457..094a994f7fdc 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/PayActionCell.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/PayActionCell.tsx
@@ -1,4 +1,5 @@
 import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
 import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import {SearchScopeProvider} from '@components/Search/SearchScopeProvider';
 import SettlementButton from '@components/SettlementButton';
@@ -17,6 +18,7 @@ import {isInvoiceReport} from '@libs/ReportUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
+import type {Report} from '@src/types/onyx';
 
 type PayActionCellProps = {
     isLoading: boolean;
@@ -26,9 +28,10 @@ type PayActionCellProps = {
     amount?: number;
     extraSmall: boolean;
     shouldDisablePointerEvents?: boolean;
+    chatReport: OnyxEntry<Report>;
 };
 
-function PayActionCell({isLoading, policyID, reportID, hash, amount, extraSmall, shouldDisablePointerEvents}: PayActionCellProps) {
+function PayActionCell({isLoading, policyID, reportID, hash, amount, extraSmall, shouldDisablePointerEvents, chatReport}: PayActionCellProps) {
     const styles = useThemeStyles();
     const {convertToDisplayString} = useCurrencyListActions();
     const {isOffline} = useNetwork();
@@ -37,7 +40,6 @@ function PayActionCell({isLoading, policyID, reportID, hash, amount, extraSmall,
     const [iouReport, transactions] = useReportWithTransactionsAndViolations(reportID);
     const policy = usePolicy(policyID);
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
-    const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`);
     const invoiceReceiverPolicyID = chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined;
     const invoiceReceiverPolicy = usePolicy(invoiceReceiverPolicyID);
     const {
diff --git a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
index 97c1fe4ceda5..aeedc8b69b3e 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
@@ -1,10 +1,17 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
 import Button from '@components/Button';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
+import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
+import {shouldShowMarkAsDone} from '@libs/ReportUtils';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report} from '@src/types/onyx';
 import type {SearchTransactionAction} from '@src/types/onyx/SearchResults';
 import actionTranslationsMap from './actionTranslationsMap';
 import PayActionCell from './PayActionCell';
@@ -21,6 +28,7 @@ type ActionCellProps = {
     amount?: number;
     extraSmall?: boolean;
     shouldDisablePointerEvents?: boolean;
+    chatReport?: OnyxEntry<Report>;
 };
 
 function ActionCell({
@@ -35,10 +43,14 @@ function ActionCell({
     amount,
     extraSmall = false,
     shouldDisablePointerEvents,
+    chatReport,
 }: ActionCellProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const {isOffline} = useNetwork();
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+    const [actionCellPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(policyID)}`);
+    const [actionCellReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportID)}`);
 
     const shouldUseViewAction = action === CONST.SEARCH.ACTION_TYPES.VIEW || action === CONST.SEARCH.ACTION_TYPES.PAID || action === CONST.SEARCH.ACTION_TYPES.DONE;
 
@@ -75,11 +87,18 @@ function ActionCell({
                 amount={amount}
                 extraSmall={extraSmall}
                 shouldDisablePointerEvents={shouldDisablePointerEvents}
+                chatReport={chatReport}
             />
         );
     }
 
-    const text = translate(actionTranslationsMap[action]);
+    const shouldUseMarkAsDone =
+        shouldShowMarkAsDone({
+            isTrackIntentUser,
+            report: actionCellReport,
+            policy: actionCellPolicy,
+        }) && action === CONST.SEARCH.ACTION_TYPES.SUBMIT;
+    const text = shouldUseMarkAsDone ? translate('common.done') : translate(actionTranslationsMap[action]);
 
     const shouldBeDisabledOffline = action !== CONST.SEARCH.ACTION_TYPES.UNDELETE && isOffline;
     const buttonInnerStyles = isSelected && action === CONST.SEARCH.ACTION_TYPES.UNDELETE ? styles.buttonDefaultSelected : {};
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
index 9eeb51f6645d..8223449df6b5 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
@@ -1,3 +1,4 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React, {useCallback, useMemo} from 'react';
 import {View} from 'react-native';
 // We need direct access to useOnyx to fetch live policy data at render time
@@ -29,7 +30,7 @@ import {handleActionButtonPress} from '@libs/actions/Search';
 import {syncMissingAttendeesViolation} from '@libs/AttendeeUtils';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {isAttendeeTrackingEnabled} from '@libs/PolicyUtils';
-import {getNonHeldAndFullAmount, isInvoiceReport, isOpenExpenseReport, isProcessingReport, isReportPendingDelete} from '@libs/ReportUtils';
+import {getNonHeldAndFullAmount, isInvoiceReport, isOpenExpenseReport, isProcessingReport, isReportPendingDelete, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import {isOnHold, isViolationDismissed, shouldShowViolation, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
@@ -84,22 +85,33 @@ function ExpenseReportListItem<TItem extends ListItem>({
     const [isActionLoading] = useOnyx(`${ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE}${reportItem.reportID}`, {selector: isActionLoadingSelector});
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['DotIndicator']);
     const currentUserDetails = useCurrentUserPersonalDetails();
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     // Fetch live policy categories from Onyx to sync violations at render time
     const [parentPolicy] = originalUseOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(reportItem.policyID)}`);
     const [parentReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportItem.reportID)}`);
-    const [parentChatReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportItem.parentReportID)}`);
     const [policyCategories] = originalUseOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${getNonEmptyStringOnyxID(reportItem.policyID)}`);
 
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy: parentPolicy,
+        report: parentReport,
+        isTrackIntentUser,
+    });
+
     const searchData = currentSearchResults?.data;
 
     const snapshotReport = useMemo(() => {
         return (searchData?.[`${ONYXKEYS.COLLECTION.REPORT}${reportItem.reportID}`] ?? {}) as Report;
     }, [searchData, reportItem.reportID]);
 
+    const [parentChatReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(snapshotReport?.chatReportID ?? reportItem.parentReportID)}`);
+
     const snapshotChatReport = useMemo(() => {
-        return searchData?.[`${ONYXKEYS.COLLECTION.REPORT}${reportItem.parentReportID}`];
-    }, [searchData, reportItem.parentReportID]);
+        const chatReportID = snapshotReport?.chatReportID ?? reportItem.parentReportID;
+        return chatReportID ? searchData?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`] : undefined;
+    }, [searchData, snapshotReport?.chatReportID, reportItem.parentReportID]);
+
+    const chatReport = parentChatReport ?? snapshotChatReport;
 
     const snapshotPolicy = useMemo(() => {
         return (searchData?.[`${ONYXKEYS.COLLECTION.POLICY}${reportItem.policyID}`] ?? {}) as Policy;
@@ -171,7 +183,7 @@ function ExpenseReportListItem<TItem extends ListItem>({
     const liveReportTransactions = useMemo(() => Object.values(reportTransactions), [reportTransactions]);
     const {currentUserAccountID, currentUserLogin, introSelected, betas, isSelfTourViewed, activePolicy, nextStep, chatReportPolicy, amountOwed} = useReportPaymentContext({
         reportID: reportItem.reportID,
-        chatReportPolicyID: parentChatReport?.policyID ?? snapshotChatReport?.policyID,
+        chatReportPolicyID: chatReport?.policyID,
     });
 
     const handleOnButtonPress = useCallback(() => {
@@ -192,7 +204,6 @@ function ExpenseReportListItem<TItem extends ListItem>({
                 // Search rows render from a snapshot; the report may not exist in the main
                 // collection yet. Fall back to the snapshot so the modal can submit.
                 const moneyRequestReport = parentReport ?? snapshotReport;
-                const chatReport = parentChatReport ?? snapshotChatReport;
                 const transactionsForHoldMenu = liveReportTransactions.length > 0 ? liveReportTransactions : holdItem.transactions;
                 const {nonHeldAmount, fullAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount(moneyRequestReport, holdItem.canPay ?? false, transactionsForHoldMenu);
                 const hasNonHeldExpenses = transactionsForHoldMenu.some((t) => !isOnHold(t));
@@ -218,7 +229,7 @@ function ExpenseReportListItem<TItem extends ListItem>({
             betas,
             isSelfTourViewed,
             activePolicy,
-            chatReport: parentChatReport ?? snapshotChatReport,
+            chatReport,
             chatReportPolicy,
             iouReportCurrentNextStepDeprecated: nextStep,
             searchData,
@@ -230,11 +241,10 @@ function ExpenseReportListItem<TItem extends ListItem>({
         onSelectRow,
         searchData,
         snapshotReport,
-        snapshotChatReport,
+        chatReport,
         snapshotPolicy,
         parentPolicy,
         parentReport,
-        parentChatReport,
         lastPaymentMethod,
         userBillingGracePeriodEnds,
         personalPolicyID,
@@ -402,12 +412,14 @@ function ExpenseReportListItem<TItem extends ListItem>({
                         canSelectMultiple={canSelectMultiple}
                         onCheckboxPress={handleSelectionButtonPress}
                         onButtonPress={handleOnButtonPress}
+                        chatReport={chatReport}
                         isSelectAllChecked={isSelected}
                         isIndeterminate={false}
                         isDisabledCheckbox={isDisabledCheckbox}
                         isHovered={hovered}
                         isFocused={isFocused}
                         isPendingDelete={isPendingDelete}
+                        isMarkAsDone={shouldUseMarkAsDoneCopy}
                     />
                     {getDescription}
                 </View>
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx
index ab301d389d58..0c311b640d47 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx
@@ -27,6 +27,7 @@ function ExpenseReportListItemRowWide({
     onCheckboxPress = () => {},
     onButtonPress = () => {},
     isActionLoading,
+    chatReport,
     containerStyle,
     showTooltip,
     canSelectMultiple,
@@ -37,6 +38,7 @@ function ExpenseReportListItemRowWide({
     isHovered = false,
     isFocused = false,
     isPendingDelete = false,
+    isMarkAsDone,
 }: ExpenseReportListItemRowWideProps) {
     const StyleUtils = useStyleUtils();
     const styles = useThemeStyles();
@@ -199,7 +201,9 @@ function ExpenseReportListItemRowWide({
                     reportID={item.reportID}
                     hash={item.hash}
                     amount={item.total}
+                    chatReport={chatReport}
                     shouldDisablePointerEvents={isPendingDelete}
+                    isMarkAsDone={isMarkAsDone}
                 />
             </View>
         ),
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx
index 30e4854a6291..57c5bdb6bd49 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx
@@ -17,6 +17,7 @@ function ExpenseReportListItemRow(props: ExpenseReportListItemRowProps) {
                 isActionLoading={props.isActionLoading}
                 onButtonPress={props.onButtonPress}
                 onCheckboxPress={props.onCheckboxPress}
+                chatReport={props.chatReport}
                 containerStyle={props.containerStyle}
                 isSelectAllChecked={props.isSelectAllChecked}
                 isIndeterminate={props.isIndeterminate}
@@ -25,6 +26,7 @@ function ExpenseReportListItemRow(props: ExpenseReportListItemRowProps) {
                 isFocused={props.isFocused}
                 isPendingDelete={props.isPendingDelete}
                 columns={props.columns}
+                isMarkAsDone={props.isMarkAsDone}
             />
         );
     }
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
index 6a405152939a..716e826d7a38 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
@@ -1,7 +1,8 @@
 import type {StyleProp, ViewStyle} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
 import type {ExpenseReportListItemType} from '@components/Search/SearchList/ListItem/types';
 import type {SearchColumnType} from '@components/Search/types';
-import type {ReportAction} from '@src/types/onyx';
+import type {Report, ReportAction} from '@src/types/onyx';
 
 type ExpenseReportListItemRowNarrowProps = {
     item: ExpenseReportListItemType;
@@ -17,11 +18,13 @@ type ExpenseReportListItemRowWideProps = ExpenseReportListItemRowNarrowProps & {
     showTooltip: boolean;
     isActionLoading?: boolean;
     onButtonPress?: () => void;
+    chatReport?: OnyxEntry<Report>;
     containerStyle?: StyleProp<ViewStyle>;
     isHovered?: boolean;
     isFocused?: boolean;
     isPendingDelete?: boolean;
     columns?: SearchColumnType[];
+    isMarkAsDone: boolean;
 };
 
 type ExpenseReportListItemRowProps = ExpenseReportListItemRowWideProps;
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
new file mode 100644
index 000000000000..63fa8911d25a
--- /dev/null
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -0,0 +1,72 @@
+import React from 'react';
+import {View} from 'react-native';
+import Animated from 'react-native-reanimated';
+import useExpandCollapseAnimation from '@hooks/useExpandCollapseAnimation';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import GroupChildrenContent from './GroupChildrenContent';
+import type {GroupChildrenContentProps} from './types';
+
+type GroupChildrenContainerProps = GroupChildrenContentProps & {
+    isLastItem?: boolean;
+    isSelected?: boolean;
+};
+
+function GroupChildrenContainer({
+    item,
+    isExpanded,
+    groupBy,
+    searchType,
+    columns,
+    canSelectMultiple,
+    onSelectRow,
+    onCheckboxPress,
+    onLongPressRow,
+    nonPersonalAndWorkspaceCards,
+    onUndelete,
+    isLastItem,
+    isSelected,
+    newTransactionID,
+    bankAccountList,
+    cardFeeds,
+    conciergeReportID,
+}: GroupChildrenContainerProps) {
+    const theme = useTheme();
+    const styles = useThemeStyles();
+    const {isRendered, animatedStyle, onLayout} = useExpandCollapseAnimation(isExpanded);
+
+    if (!isExpanded && !isRendered) {
+        return null;
+    }
+
+    return (
+        <View style={[styles.mh5, {backgroundColor: isSelected ? theme.activeComponentBG : theme.highlightBG}, isLastItem && [styles.tableBottomRadius, styles.overflowHidden]]}>
+            <Animated.View style={animatedStyle}>
+                <Animated.View
+                    style={[styles.stickToTop, styles.pb1]}
+                    onLayout={onLayout}
+                >
+                    <GroupChildrenContent
+                        item={item}
+                        isExpanded={isExpanded}
+                        groupBy={groupBy}
+                        searchType={searchType}
+                        columns={columns}
+                        canSelectMultiple={canSelectMultiple}
+                        onSelectRow={onSelectRow}
+                        onCheckboxPress={onCheckboxPress}
+                        onLongPressRow={onLongPressRow}
+                        nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+                        onUndelete={onUndelete}
+                        newTransactionID={newTransactionID}
+                        bankAccountList={bankAccountList}
+                        cardFeeds={cardFeeds}
+                        conciergeReportID={conciergeReportID}
+                    />
+                </Animated.View>
+            </Animated.View>
+        </View>
+    );
+}
+
+export default GroupChildrenContainer;
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
new file mode 100644
index 000000000000..6f876082cd80
--- /dev/null
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
@@ -0,0 +1,227 @@
+import {useIsFocused} from '@react-navigation/native';
+import React, {useEffect, useMemo, useState} from 'react';
+import {useSearchSelectionContext} from '@components/Search/SearchContext';
+import useActionLoadingReportIDs from '@hooks/useActionLoadingReportIDs';
+import {useCurrencyListActions} from '@hooks/useCurrencyList';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
+import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
+import useOnyx from '@hooks/useOnyx';
+import {search} from '@libs/actions/Search';
+import {getSections} from '@libs/SearchUIUtils';
+import {mergeProhibitedViolations, shouldShowViolation} from '@libs/TransactionUtils';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
+import TransactionGroupListExpandedItem from './TransactionGroupListExpanded';
+import type {GroupChildrenContentProps, TransactionListItemType} from './types';
+
+function GroupChildrenContent({
+    item,
+    isExpanded,
+    groupBy,
+    searchType,
+    columns,
+    canSelectMultiple,
+    onSelectRow,
+    onCheckboxPress,
+    onLongPressRow,
+    nonPersonalAndWorkspaceCards,
+    onUndelete,
+    newTransactionID,
+    bankAccountList,
+    cardFeeds,
+    conciergeReportID,
+}: GroupChildrenContentProps) {
+    const {translate, formatPhoneNumber} = useLocalize();
+    const {selectedTransactions} = useSearchSelectionContext();
+    const currentUserDetails = useCurrentUserPersonalDetails();
+    const isScreenFocused = useIsFocused();
+    const {convertToDisplayString} = useCurrencyListActions();
+    const {isOffline} = useNetwork();
+
+    const groupItem = item;
+    const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
+
+    const [transactionsSnapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${groupItem.transactionsQueryJSON?.hash}`);
+    const [transactionsVisibleLimit, setTransactionsVisibleLimit] = useState<number>(CONST.TRANSACTION.RESULTS_PAGE_SIZE);
+    const isActionLoadingSet = useActionLoadingReportIDs();
+    const snapshotData = transactionsSnapshot?.data;
+
+    const selectedTransactionIDsSet = useMemo(() => new Set(Object.keys(selectedTransactions)), [selectedTransactions]);
+
+    const transactions: TransactionListItemType[] = useMemo(() => {
+        if (isExpenseReportType) {
+            return groupItem.transactions;
+        }
+        if (!snapshotData) {
+            return [];
+        }
+        const [sectionData] = getSections({
+            type: CONST.SEARCH.DATA_TYPES.EXPENSE,
+            data: snapshotData,
+            currentAccountID: currentUserDetails.accountID,
+            currentUserEmail: currentUserDetails.email ?? '',
+            translate,
+            formatPhoneNumber,
+            bankAccountList,
+            isActionLoadingSet,
+            cardFeeds,
+            conciergeReportID,
+            convertToDisplayString,
+        }) as [TransactionListItemType[], number, boolean];
+        return sectionData.map((transactionItem) => ({
+            ...transactionItem,
+            isSelected: selectedTransactionIDsSet.has(transactionItem.transactionID),
+        }));
+    }, [
+        isExpenseReportType,
+        groupItem.transactions,
+        snapshotData,
+        currentUserDetails.accountID,
+        currentUserDetails.email,
+        translate,
+        formatPhoneNumber,
+        bankAccountList,
+        isActionLoadingSet,
+        cardFeeds,
+        conciergeReportID,
+        convertToDisplayString,
+        selectedTransactionIDsSet,
+    ]);
+
+    const isEmpty = transactions.length === 0;
+    const shouldDisplayEmptyView = isEmpty && isExpenseReportType;
+
+    const refreshTransactions = () => {
+        if (!groupItem.transactionsQueryJSON) {
+            return;
+        }
+        search({
+            queryJSON: groupItem.transactionsQueryJSON,
+            searchKey: undefined,
+            offset: 0,
+            shouldCalculateTotals: false,
+            isLoading: !!transactionsSnapshot?.search?.isLoading,
+            isOffline,
+        });
+    };
+
+    const searchTransactions = (pageSize = 0) => {
+        if (!groupItem.transactionsQueryJSON) {
+            return;
+        }
+        search({
+            queryJSON: groupItem.transactionsQueryJSON,
+            searchKey: undefined,
+            offset: (transactionsSnapshot?.search?.offset ?? 0) + pageSize,
+            shouldCalculateTotals: false,
+            isLoading: !!transactionsSnapshot?.search?.isLoading,
+            isOffline,
+        });
+    };
+
+    useEffect(() => {
+        if (!newTransactionID || !isExpanded) {
+            return;
+        }
+        refreshTransactions();
+        // Only refresh when a new transaction is created in this group — refreshTransactions is excluded to avoid infinite loops
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [newTransactionID, isExpanded]);
+
+    useEffect(() => {
+        if (!isExpanded || isExpenseReportType) {
+            return;
+        }
+        refreshTransactions();
+        // Only fetch on expand — refreshTransactions and isExpenseReportType are excluded to prevent re-fetching on every render
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [isExpanded]);
+
+    const wasScreenFocusedRef = React.useRef(isScreenFocused);
+    useEffect(() => {
+        const didReturnToScreen = wasScreenFocusedRef.current === false && isScreenFocused === true;
+        wasScreenFocusedRef.current = isScreenFocused;
+        if (!didReturnToScreen || !isExpanded || isExpenseReportType) {
+            return;
+        }
+        refreshTransactions();
+        // Only refresh when returning to this screen while expanded — other deps excluded to avoid redundant fetches
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [isScreenFocused]);
+
+    const filteredViolations: Record<string, TransactionViolation[]> = useMemo(() => {
+        if (!snapshotData) {
+            return {};
+        }
+
+        const groupViolations: Record<string, TransactionViolations | undefined> = {};
+        for (const [key, value] of Object.entries(snapshotData)) {
+            if (key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS)) {
+                groupViolations[key] = value as TransactionViolations;
+            }
+        }
+
+        const result: Record<string, TransactionViolation[]> = {};
+        for (const key of Object.keys(snapshotData)) {
+            if (!key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) {
+                continue;
+            }
+            const snapshotTransaction = snapshotData[key as keyof typeof snapshotData] as Transaction;
+            if (!snapshotTransaction || typeof snapshotTransaction !== 'object' || !('transactionID' in snapshotTransaction) || !('reportID' in snapshotTransaction)) {
+                continue;
+            }
+
+            const report = snapshotData[`${ONYXKEYS.COLLECTION.REPORT}${snapshotTransaction.reportID}`];
+            const policy = snapshotData[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`];
+
+            if (report && policy) {
+                const transactionViolations = groupViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${snapshotTransaction.transactionID}`];
+                if (transactionViolations) {
+                    const merged = mergeProhibitedViolations(
+                        transactionViolations.filter((violation) => shouldShowViolation(report, policy, violation.name, currentUserDetails?.email ?? '', true, snapshotTransaction)),
+                    );
+                    if (merged.length > 0) {
+                        result[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${snapshotTransaction.transactionID}`] = merged;
+                    }
+                }
+            }
+        }
+        return result;
+    }, [snapshotData, currentUserDetails.email]);
+
+    const onExpandedRowLongPress = (transaction: TransactionListItemType) => {
+        onLongPressRow?.(transaction);
+    };
+
+    return (
+        <TransactionGroupListExpandedItem
+            showTooltip
+            canSelectMultiple={canSelectMultiple}
+            onSelectionButtonPress={onCheckboxPress}
+            onSelectRow={onSelectRow}
+            columns={columns}
+            groupBy={groupBy}
+            accountID={currentUserDetails.accountID}
+            isOffline={isOffline}
+            violations={filteredViolations}
+            transactions={transactions}
+            transactionsVisibleLimit={transactionsVisibleLimit}
+            setTransactionsVisibleLimit={setTransactionsVisibleLimit}
+            isEmpty={isEmpty}
+            shouldDisplayEmptyView={shouldDisplayEmptyView}
+            isExpenseReportType={isExpenseReportType}
+            transactionsSnapshot={transactionsSnapshot}
+            transactionsQueryJSON={groupItem.transactionsQueryJSON}
+            searchTransactions={searchTransactions}
+            isInSingleTransactionReport={groupItem.transactions.length === 1}
+            onLongPress={onExpandedRowLongPress}
+            nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+            onUndelete={onUndelete}
+            hideSearchTableHeader
+        />
+    );
+}
+
+export default GroupChildrenContent;
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
new file mode 100644
index 000000000000..42afe29f4666
--- /dev/null
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -0,0 +1,479 @@
+import React, {useMemo, useRef} from 'react';
+import {View} from 'react-native';
+import type {NativeSyntheticEvent} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
+// eslint-disable-next-line no-restricted-imports
+import {useOnyx as originalUseOnyx} from 'react-native-onyx';
+import Animated from 'react-native-reanimated';
+import {getButtonRole} from '@components/Button/utils';
+import Icon from '@components/Icon';
+import OfflineWithFeedback from '@components/OfflineWithFeedback';
+import {PressableWithFeedback} from '@components/Pressable';
+import {useSearchSelectionContext} from '@components/Search/SearchContext';
+import SearchTableHeader from '@components/Search/SearchTableHeader';
+import type {SearchColumnType, SearchCustomColumnIds, SearchGroupBy} from '@components/Search/types';
+import type {ExtendedTargetedEvent} from '@components/SelectionList/ListItem/types';
+import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
+import useExpandCollapseAnimation from '@hooks/useExpandCollapseAnimation';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useOnyx from '@hooks/useOnyx';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useSyncFocus from '@hooks/useSyncFocus';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import type {TransactionPreviewData} from '@libs/actions/Search';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
+import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
+import {getColumnsToShow} from '@libs/SearchUIUtils';
+import {isDeletedTransaction} from '@libs/TransactionUtils';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {ReportAction, ReportActions, Transaction} from '@src/types/onyx';
+import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
+import CardListItemHeader from './CardListItemHeader';
+import CategoryListItemHeader from './CategoryListItemHeader';
+import MemberListItemHeader from './MemberListItemHeader';
+import MerchantListItemHeader from './MerchantListItemHeader';
+import MonthListItemHeader from './MonthListItemHeader';
+import QuarterListItemHeader from './QuarterListItemHeader';
+import ReportListItemHeader from './ReportListItemHeader';
+import TagListItemHeader from './TagListItemHeader';
+import type {GroupHeaderItemType, SearchListActionProps, SearchListItem, TransactionListItemType} from './types';
+import WeekListItemHeader from './WeekListItemHeader';
+import WithdrawalIDListItemHeader from './WithdrawalIDListItemHeader';
+import YearListItemHeader from './YearListItemHeader';
+
+type GroupHeaderProps = SearchListActionProps & {
+    item: GroupHeaderItemType;
+    groupBy?: SearchGroupBy;
+    searchType?: SearchDataTypes;
+    columns?: SearchColumnType[];
+    canSelectMultiple: boolean;
+    isExpanded: boolean;
+    onToggle: () => void;
+    onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
+    onCheckboxPress: (item: GroupHeaderItemType, itemTransactions?: TransactionListItemType[]) => void;
+    onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    onFocus?: (event: NativeSyntheticEvent<ExtendedTargetedEvent>) => void;
+    shouldSyncFocus?: boolean;
+    isFocused?: boolean;
+    isFirstItem: boolean;
+    isLastItem: boolean;
+    originalKey: string;
+    visibleColumns?: SearchCustomColumnIds[];
+};
+
+function GroupHeader({
+    item,
+    groupBy,
+    searchType,
+    columns,
+    canSelectMultiple,
+    isExpanded,
+    onToggle,
+    onSelectRow,
+    onCheckboxPress,
+    onLongPressRow,
+    onFocus,
+    shouldSyncFocus,
+    isFocused,
+    isFirstItem,
+    isLastItem,
+    originalKey,
+    lastPaymentMethod,
+    personalPolicyID,
+    userBillingGracePeriodEnds,
+    ownerBillingGracePeriodEnd,
+    visibleColumns,
+}: GroupHeaderProps) {
+    const theme = useTheme();
+    const styles = useThemeStyles();
+    const StyleUtils = useStyleUtils();
+    const {isLargeScreenWidth} = useResponsiveLayout();
+    const {selectedTransactions} = useSearchSelectionContext();
+    const expensifyIcons = useMemoizedLazyExpensifyIcons(['UpArrow', 'DownArrow']);
+    const currentUserDetails = useCurrentUserPersonalDetails();
+
+    const groupItem = item;
+    const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
+
+    const oneTransactionItem = groupItem.isOneTransactionReport ? groupItem.transactions.at(0) : undefined;
+    const oneTransactionReportID = getNonEmptyStringOnyxID(oneTransactionItem?.reportID);
+    const oneTransactionID = getNonEmptyStringOnyxID(oneTransactionItem?.transactionID);
+    const oneTransactionChildReportID = oneTransactionItem?.reportAction?.childReportID;
+    const [parentReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionReportID}`);
+    const [oneTransactionThreadReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionChildReportID}`);
+    const [oneTransaction] = originalUseOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${oneTransactionID}`);
+    const parentReportActionSelector = (reportActions: OnyxEntry<ReportActions>): OnyxEntry<ReportAction> => reportActions?.[`${oneTransactionItem?.reportAction?.reportActionID}`];
+    const [parentReportAction] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oneTransactionReportID}`, {selector: parentReportActionSelector}, [oneTransactionItem]);
+    const transactionPreviewData: TransactionPreviewData = useMemo(
+        () => ({
+            hasParentReport: !!parentReport,
+            hasTransaction: !!oneTransaction,
+            hasParentReportAction: !!parentReportAction,
+            hasTransactionThreadReport: !!oneTransactionThreadReport,
+        }),
+        [parentReport, oneTransaction, parentReportAction, oneTransactionThreadReport],
+    );
+
+    const [transactionsSnapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${groupItem.transactionsQueryJSON?.hash}`);
+    const snapshotData = transactionsSnapshot?.data;
+    const snapshotSearchType = transactionsSnapshot?.search.type;
+
+    const subHeaderColumns = useMemo(() => {
+        if (isExpenseReportType) {
+            return columns ?? [];
+        }
+        if (!snapshotData) {
+            return [];
+        }
+        return getColumnsToShow({
+            currentAccountID: currentUserDetails.accountID,
+            data: snapshotData,
+            visibleColumns,
+            type: snapshotSearchType,
+        });
+    }, [isExpenseReportType, columns, snapshotData, snapshotSearchType, currentUserDetails.accountID, visibleColumns]);
+
+    const {isSubHeaderAmountColumnWide, isSubHeaderTaxAmountColumnWide, shouldSubHeaderShowYear, isSubHeaderActionColumnWide} = useMemo(() => {
+        let amountWide = false;
+        let taxWide = false;
+        let showYear = false;
+        let actionWide = false;
+        for (const transaction of groupItem.transactions) {
+            if (transaction.isAmountColumnWide) {
+                amountWide = true;
+            }
+            if (transaction.isTaxAmountColumnWide) {
+                taxWide = true;
+            }
+            if (transaction.shouldShowYear) {
+                showYear = true;
+            }
+            if (transaction.isActionColumnWide || isDeletedTransaction(transaction)) {
+                actionWide = true;
+            }
+            if (amountWide && taxWide && showYear && actionWide) {
+                break;
+            }
+        }
+        return {isSubHeaderAmountColumnWide: amountWide, isSubHeaderTaxAmountColumnWide: taxWide, shouldSubHeaderShowYear: showYear, isSubHeaderActionColumnWide: actionWide};
+    }, [groupItem.transactions]);
+
+    const {isRendered: isSubHeaderRendered, animatedStyle: subHeaderAnimatedStyle, onLayout: onSubHeaderLayout} = useExpandCollapseAnimation(isExpanded);
+
+    const hasSnapshotTransactions = !isExpenseReportType && !!snapshotData && Object.keys(snapshotData).some((key) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION));
+    const isEmpty = groupItem.transactions.length === 0 && !hasSnapshotTransactions;
+    const isDisabled = item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
+    const isDisabledOrEmpty = isEmpty || isDisabled;
+
+    const effectiveTransactions = useMemo((): TransactionListItemType[] => {
+        if (isExpenseReportType || groupItem.transactions.length > 0) {
+            return groupItem.transactions;
+        }
+        if (!snapshotData) {
+            return [];
+        }
+        const items: TransactionListItemType[] = [];
+        for (const key of Object.keys(snapshotData)) {
+            if (!key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) {
+                continue;
+            }
+            const transaction = snapshotData[key as keyof typeof snapshotData] as Transaction;
+            if (!transaction?.transactionID) {
+                continue;
+            }
+            const report = snapshotData[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`];
+            items.push({
+                ...transaction,
+                keyForList: transaction.transactionID,
+                report,
+            } as TransactionListItemType);
+        }
+        return items;
+    }, [isExpenseReportType, groupItem.transactions, snapshotData]);
+
+    const {isSelectAllChecked, isIndeterminate} = useMemo(() => {
+        const selectedTransactionIDsSet = new Set(Object.keys(selectedTransactions));
+        const filteredTransactions = effectiveTransactions.filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
+        const selectedCount = filteredTransactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
+        const isEmptyReportSelected = isEmpty && originalKey && selectedTransactions[originalKey]?.isSelected;
+        const allChecked = !!isEmptyReportSelected || (selectedCount === filteredTransactions.length && filteredTransactions.length > 0);
+        const indeterminate = selectedCount > 0 && selectedCount !== filteredTransactions.length;
+        return {isSelectAllChecked: allChecked, isIndeterminate: indeterminate};
+    }, [selectedTransactions, effectiveTransactions, isEmpty, originalKey]);
+
+    const isItemSelected = isSelectAllChecked || item?.isSelected;
+
+    const animatedHighlightStyle = useAnimatedHighlightStyle({
+        shouldHighlight: item?.shouldAnimateInHighlight ?? false,
+        highlightColor: theme.messageHighlightBG,
+        backgroundColor: isItemSelected ? theme.activeComponentBG : theme.highlightBG,
+        shouldApplyOtherStyles: false,
+    });
+
+    const handleSelectionButtonPress = () => {
+        onCheckboxPress(item, isExpenseReportType ? undefined : effectiveTransactions);
+    };
+
+    const pendingAction =
+        item.pendingAction ??
+        (groupItem.transactions.length > 0 && groupItem.transactions.every((transaction) => transaction.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE)
+            ? CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE
+            : undefined);
+
+    const handleSelectRow = (rowItem: SearchListItem, event?: ModifiedMouseEvent) => {
+        onSelectRow(rowItem, transactionPreviewData, event);
+    };
+
+    const renderHeader = (hovered: boolean) => {
+        if (isExpenseReportType && 'groupedBy' in groupItem && groupItem.groupedBy === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT) {
+            return (
+                <ReportListItemHeader
+                    report={groupItem}
+                    onSelectRow={handleSelectRow}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabled}
+                    isFocused={isFocused}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    isHovered={hovered}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                    lastPaymentMethod={lastPaymentMethod}
+                    personalPolicyID={personalPolicyID}
+                    userBillingGracePeriodEnds={userBillingGracePeriodEnds}
+                    ownerBillingGracePeriodEnd={ownerBillingGracePeriodEnd}
+                />
+            );
+        }
+
+        if (!('groupedBy' in groupItem)) {
+            return null;
+        }
+
+        const commonProps = {
+            onCheckboxPress: handleSelectionButtonPress,
+            isDisabled: isDisabledOrEmpty,
+            columns,
+            canSelectMultiple,
+            isSelectAllChecked,
+            isIndeterminate,
+            onDownArrowClick: onToggle,
+            isExpanded,
+        } as const;
+
+        switch (groupItem.groupedBy) {
+            case CONST.SEARCH.GROUP_BY.FROM:
+                return (
+                    <MemberListItemHeader
+                        member={groupItem}
+                        {...commonProps}
+                        isLargeScreenWidth={isLargeScreenWidth}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.CARD:
+                return (
+                    <CardListItemHeader
+                        card={groupItem}
+                        {...commonProps}
+                        isFocused={isFocused}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID:
+                return (
+                    <WithdrawalIDListItemHeader
+                        withdrawalID={groupItem}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.CATEGORY:
+                return (
+                    <CategoryListItemHeader
+                        category={groupItem}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.MERCHANT:
+                return (
+                    <MerchantListItemHeader
+                        merchant={groupItem}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.TAG:
+                return (
+                    <TagListItemHeader
+                        tag={groupItem}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.MONTH:
+                return (
+                    <MonthListItemHeader
+                        month={groupItem}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.WEEK:
+                return (
+                    <WeekListItemHeader
+                        week={groupItem}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.YEAR:
+                return (
+                    <YearListItemHeader
+                        year={groupItem}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.QUARTER:
+                return (
+                    <QuarterListItemHeader
+                        quarter={groupItem}
+                        {...commonProps}
+                    />
+                );
+            default:
+                return null;
+        }
+    };
+
+    const isLastItemCollapsed = isLastItem && !isExpanded && !isSubHeaderRendered;
+    const pressableRef = useRef<View>(null);
+
+    useSyncFocus(pressableRef, !!isFocused, shouldSyncFocus);
+
+    const pressableStyle = [
+        styles.transactionGroupListItemStyle,
+        isLargeScreenWidth && {
+            ...styles.tableRowHeight,
+            borderRadius: 0,
+            ...(isLastItemCollapsed ? styles.tableBottomRadius : {}),
+        },
+        isItemSelected && styles.activeComponentBG,
+    ];
+
+    const shouldDisplayEmptyView = isEmpty && isExpenseReportType;
+
+    const handlePress = (event?: ModifiedMouseEvent) => {
+        if (isExpenseReportType) {
+            onSelectRow(item, transactionPreviewData, event);
+        }
+        if (!isExpenseReportType) {
+            onToggle();
+        }
+    };
+
+    const handleLongPress = () => {
+        onLongPressRow?.(item, isExpenseReportType ? undefined : effectiveTransactions);
+    };
+
+    return (
+        <OfflineWithFeedback pendingAction={pendingAction}>
+            <PressableWithFeedback
+                ref={pressableRef}
+                onPress={handlePress}
+                onLongPress={handleLongPress}
+                disabled={isDisabled && !isItemSelected}
+                sentryLabel={CONST.SENTRY_LABEL.SEARCH.TRANSACTION_GROUP_LIST_ITEM}
+                accessibilityLabel={item.text ?? ''}
+                role={getButtonRole(true)}
+                isNested
+                hoverStyle={[!isExpanded && !item.isDisabled && styles.hoveredComponentBG, isItemSelected && styles.activeComponentBG]}
+                dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true, [CONST.INNER_BOX_SHADOW_ELEMENT]: false}}
+                onMouseDown={(e) => e.preventDefault()}
+                id={item.keyForList ?? ''}
+                onFocus={onFocus}
+                style={[
+                    pressableStyle,
+                    isFocused && StyleUtils.getItemBackgroundColorStyle(!!isItemSelected, !!isFocused, !!item.isDisabled, theme.activeComponentBG, theme.hoverComponentBG),
+                ]}
+                wrapperStyle={[
+                    styles.mh5,
+                    animatedHighlightStyle,
+                    styles.userSelectNone,
+                    isLargeScreenWidth
+                        ? [StyleUtils.getSearchTableGroupRowBorderStyle(isFirstItem, isLastItemCollapsed, isItemSelected), isLastItemCollapsed && styles.overflowHidden]
+                        : [
+                              isFirstItem && [styles.tableTopRadius, styles.overflowHidden],
+                              isLastItemCollapsed && [styles.tableBottomRadius, styles.overflowHidden],
+                              !isLastItemCollapsed && !isExpanded && StyleUtils.getSelectedBorderBottomStyle(isItemSelected),
+                          ],
+                ]}
+            >
+                {({hovered}) => (
+                    <View style={styles.flex1}>
+                        <View style={[styles.flexRow, styles.alignItemsCenter, isLargeScreenWidth && styles.tableRowHeight]}>
+                            <View style={styles.flex1}>{renderHeader(hovered)}</View>
+                            {isLargeScreenWidth && (
+                                <PressableWithFeedback
+                                    onPress={() => {
+                                        if (isEmpty && !shouldDisplayEmptyView) {
+                                            handlePress();
+                                            return;
+                                        }
+                                        onToggle();
+                                    }}
+                                    style={[styles.p3Half, styles.justifyContentCenter, styles.alignItemsCenter, styles.pv2]}
+                                    accessibilityRole={CONST.ROLE.BUTTON}
+                                    accessibilityLabel={isExpanded ? CONST.ACCESSIBILITY_LABELS.COLLAPSE : CONST.ACCESSIBILITY_LABELS.EXPAND}
+                                    sentryLabel={CONST.SENTRY_LABEL.SEARCH.GROUP_EXPAND_TOGGLE}
+                                >
+                                    {({hovered: arrowHovered}) => (
+                                        <Icon
+                                            src={isExpanded ? expensifyIcons.UpArrow : expensifyIcons.DownArrow}
+                                            fill={theme.icon}
+                                            additionalStyles={!arrowHovered && styles.opacitySemiTransparent}
+                                        />
+                                    )}
+                                </PressableWithFeedback>
+                            )}
+                        </View>
+                        {isLargeScreenWidth && subHeaderColumns.length > 0 && (
+                            <Animated.View style={subHeaderAnimatedStyle}>
+                                {(isExpanded || isSubHeaderRendered) && (
+                                    <View
+                                        style={styles.stickToTop}
+                                        onLayout={onSubHeaderLayout}
+                                    >
+                                        <View style={[styles.ph3, styles.pb1]}>
+                                            <View style={[styles.borderBottom, styles.borderNone]} />
+                                        </View>
+                                        <View style={[styles.searchListHeaderContainerStyle, styles.groupSearchListTableContainerStyle, styles.bgTransparent, styles.pl8, styles.borderNone]}>
+                                            <SearchTableHeader
+                                                canSelectMultiple
+                                                type={CONST.SEARCH.DATA_TYPES.EXPENSE}
+                                                onSortPress={() => {}}
+                                                sortOrder={undefined}
+                                                sortBy={undefined}
+                                                shouldShowYear={shouldSubHeaderShowYear}
+                                                isAmountColumnWide={isSubHeaderAmountColumnWide}
+                                                isTaxAmountColumnWide={isSubHeaderTaxAmountColumnWide}
+                                                shouldShowSorting={false}
+                                                columns={subHeaderColumns}
+                                                groupBy={groupBy}
+                                                isExpenseReportView
+                                                isActionColumnWide={isSubHeaderActionColumnWide}
+                                            />
+                                        </View>
+                                        <View style={[styles.ph3, styles.groupSubHeaderBorderOverlap]}>
+                                            <View style={StyleUtils.getSelectedBorderBottomStyle(isItemSelected)} />
+                                        </View>
+                                    </View>
+                                )}
+                            </Animated.View>
+                        )}
+                    </View>
+                )}
+            </PressableWithFeedback>
+        </OfflineWithFeedback>
+    );
+}
+
+export default GroupHeader;
diff --git a/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx b/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx
index 8e97f79ed7b2..5596e7c933bc 100644
--- a/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx
@@ -1,6 +1,7 @@
 import React, {useMemo} from 'react';
 import type {ColorValue} from 'react-native';
 import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
 import Checkbox from '@components/Checkbox';
 import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import Icon from '@components/Icon';
@@ -96,6 +97,9 @@ type FirstRowReportHeaderProps<TItem extends ListItem> = {
 
     /** Whether the down arrow is expanded */
     isExpanded?: boolean;
+
+    /** Parent chat report resolved from live Onyx with search snapshot fallback */
+    chatReport?: OnyxEntry<Report>;
 };
 
 function HeaderFirstRow<TItem extends ListItem>({
@@ -109,6 +113,7 @@ function HeaderFirstRow<TItem extends ListItem>({
     isIndeterminate,
     onDownArrowClick,
     isExpanded,
+    chatReport,
 }: FirstRowReportHeaderProps<TItem>) {
     const icons = useMemoizedLazyExpensifyIcons(['DownArrow', 'UpArrow']);
     const styles = useThemeStyles();
@@ -190,6 +195,7 @@ function HeaderFirstRow<TItem extends ListItem>({
                         hash={reportItem.hash}
                         amount={reportItem.total}
                         extraSmall={!isLargeScreenWidth}
+                        chatReport={chatReport}
                     />
                 </View>
             )}
@@ -228,11 +234,16 @@ function ReportListItemHeader<TItem extends ListItem>({
     const snapshotPolicy = useMemo(() => {
         return (snapshot?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${reportItem.policyID}`] ?? {}) as Policy;
     }, [snapshot, reportItem.policyID]);
+    const snapshotChatReport = useMemo(() => {
+        const chatReportID = snapshotReport?.chatReportID ?? reportItem.parentReportID;
+        return chatReportID ? snapshot?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`] : undefined;
+    }, [snapshot, snapshotReport?.chatReportID, reportItem.parentReportID]);
     const [parentPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(snapshotReport?.policyID ?? reportItem.policyID)}`);
-    const [parentChatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(snapshotReport?.chatReportID)}`);
+    const [parentChatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(snapshotReport?.chatReportID ?? reportItem.parentReportID)}`);
+    const chatReport = parentChatReport ?? snapshotChatReport;
     const {currentUserAccountID, currentUserLogin, introSelected, betas, isSelfTourViewed, activePolicy, nextStep, chatReportPolicy, amountOwed} = useReportPaymentContext({
         reportID: reportItem.reportID,
-        chatReportPolicyID: parentChatReport?.policyID,
+        chatReportPolicyID: chatReport?.policyID,
     });
     const {isDelegateAccessRestricted} = useDelegateNoAccessState();
     const {showDelegateNoAccessModal} = useDelegateNoAccessActions();
@@ -265,7 +276,7 @@ function ReportListItemHeader<TItem extends ListItem>({
             betas,
             isSelfTourViewed,
             activePolicy,
-            chatReport: parentChatReport,
+            chatReport,
             chatReportPolicy,
             iouReportCurrentNextStepDeprecated: nextStep,
             searchData: snapshot?.data,
@@ -306,6 +317,7 @@ function ReportListItemHeader<TItem extends ListItem>({
                 isIndeterminate={isIndeterminate}
                 onDownArrowClick={onDownArrowClick}
                 isExpanded={isExpanded}
+                chatReport={chatReport}
             />
         </View>
     );
diff --git a/src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx b/src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx
index d9e4d018dcf3..fc8050baf190 100644
--- a/src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx
+++ b/src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx
@@ -64,6 +64,7 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
     onLongPress,
     nonPersonalAndWorkspaceCards,
     onUndelete,
+    hideSearchTableHeader,
 }: TransactionGroupListExpandedProps<TItem>) {
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -289,7 +290,7 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
 
     const content = (
         <View style={[styles.flexColumn, styles.flex1]}>
-            {isLargeScreenWidth && !(isEmpty && shouldDisplayLoadingIndicator) && (
+            {isLargeScreenWidth && !hideSearchTableHeader && !(isEmpty && shouldDisplayLoadingIndicator) && (
                 <>
                     <View style={[styles.searchListHeaderContainerStyle, styles.groupSearchListTableContainerStyle, styles.bgTransparent, styles.pl8, styles.borderNone]}>
                         <SearchTableHeader
diff --git a/src/components/Search/SearchList/ListItem/TransactionGroupListItem.tsx b/src/components/Search/SearchList/ListItem/TransactionGroupListItem.tsx
index 21b8e1f39a42..dff4e1eac338 100644
--- a/src/components/Search/SearchList/ListItem/TransactionGroupListItem.tsx
+++ b/src/components/Search/SearchList/ListItem/TransactionGroupListItem.tsx
@@ -177,7 +177,9 @@ function TransactionGroupListItem<TItem extends ListItem>({
     const isSelectAllChecked = isEmptyReportSelected || (selectedItemsLength === transactionsWithoutPendingDelete.length && transactionsWithoutPendingDelete.length > 0);
     const isIndeterminate = selectedItemsLength > 0 && selectedItemsLength !== transactionsWithoutPendingDelete.length;
 
+    // Currently only the transaction report groups have transactions where the empty view makes sense
     const shouldDisplayEmptyView = isEmpty && isExpenseReportType;
+    const isDisabledOrEmpty = isEmpty || isDisabled;
 
     const refreshTransactions = () => {
         if (!groupItem.transactionsQueryJSON) {
@@ -290,7 +292,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
     };
 
     const onPress = (event?: ModifiedMouseEvent) => {
-        if (isExpenseReportType) {
+        if (isExpenseReportType || transactions.length === 0) {
             onSelectRow(item, transactionPreviewData, event);
         }
         if (!isExpenseReportType) {
@@ -325,7 +327,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <MemberListItemHeader
                     member={groupItem as TransactionMemberGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -339,7 +341,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <CardListItemHeader
                     card={groupItem as TransactionCardGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     isFocused={isFocused}
                     canSelectMultiple={canSelectMultiple}
@@ -353,7 +355,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <WithdrawalIDListItemHeader
                     withdrawalID={groupItem as TransactionWithdrawalIDGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -366,7 +368,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <CategoryListItemHeader
                     category={groupItem as TransactionCategoryGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -379,7 +381,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <MerchantListItemHeader
                     merchant={groupItem as TransactionMerchantGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -392,7 +394,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <TagListItemHeader
                     tag={groupItem as TransactionTagGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -405,7 +407,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <MonthListItemHeader
                     month={groupItem as TransactionMonthGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -418,7 +420,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <WeekListItemHeader
                     week={groupItem as TransactionWeekGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -431,7 +433,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <YearListItemHeader
                     year={groupItem as TransactionYearGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -444,7 +446,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <QuarterListItemHeader
                     quarter={groupItem as TransactionQuarterGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
diff --git a/src/components/Search/SearchList/ListItem/types.ts b/src/components/Search/SearchList/ListItem/types.ts
index 488468eeae5f..b1c4c0f4ccd9 100644
--- a/src/components/Search/SearchList/ListItem/types.ts
+++ b/src/components/Search/SearchList/ListItem/types.ts
@@ -3,9 +3,13 @@ import type {ValueOf} from 'type-fest';
 import type {SearchColumnType, SearchGroupBy, SearchQueryJSON} from '@components/Search/types';
 import type {ListItemProps} from '@components/SelectionList/ListItem/types';
 import type {ListItem} from '@components/SelectionList/types';
+import type {TransactionPreviewData} from '@libs/actions/Search';
+import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
 import type CONST from '@src/CONST';
 import type {
+    BankAccountList,
     BillingGraceEndPeriod,
+    CardFeeds,
     CardList,
     LastPaymentMethod,
     PersonalDetails,
@@ -478,6 +482,58 @@ type TransactionGroupListExpandedProps<TItem extends ListItem> = Pick<
     isInSingleTransactionReport: boolean;
     searchTransactions: (pageSize?: number) => void;
     onLongPress: (transaction: TransactionListItemType) => void;
+    hideSearchTableHeader?: boolean;
+};
+
+const GROUP_ITEM_TYPES = {
+    GROUP_HEADER: 'group_header',
+    CHILDREN_CONTAINER: 'children_container',
+} as const;
+
+type GroupHeaderListItemType = {listItemType: typeof GROUP_ITEM_TYPES.GROUP_HEADER};
+
+type GroupHeaderItemType =
+    | (TransactionReportGroupListItemType & GroupHeaderListItemType)
+    | (TransactionMemberGroupListItemType & GroupHeaderListItemType)
+    | (TransactionCardGroupListItemType & GroupHeaderListItemType)
+    | (TransactionWithdrawalIDGroupListItemType & GroupHeaderListItemType)
+    | (TransactionCategoryGroupListItemType & GroupHeaderListItemType)
+    | (TransactionMerchantGroupListItemType & GroupHeaderListItemType)
+    | (TransactionTagGroupListItemType & GroupHeaderListItemType)
+    | (TransactionMonthGroupListItemType & GroupHeaderListItemType)
+    | (TransactionWeekGroupListItemType & GroupHeaderListItemType)
+    | (TransactionYearGroupListItemType & GroupHeaderListItemType)
+    | (TransactionQuarterGroupListItemType & GroupHeaderListItemType)
+    | (TransactionGroupListItemType & GroupHeaderListItemType);
+
+type GroupChildrenContainerItemType = TransactionGroupListItemType & {
+    listItemType: typeof GROUP_ITEM_TYPES.CHILDREN_CONTAINER;
+};
+
+function isGroupHeaderItem(item: SearchListItem): item is GroupHeaderItemType {
+    return 'listItemType' in item && item.listItemType === GROUP_ITEM_TYPES.GROUP_HEADER;
+}
+
+function isGroupChildrenContainerItem(item: SearchListItem): item is GroupChildrenContainerItemType {
+    return 'listItemType' in item && item.listItemType === GROUP_ITEM_TYPES.CHILDREN_CONTAINER;
+}
+
+type GroupChildrenContentProps = {
+    item: GroupChildrenContainerItemType;
+    isExpanded: boolean;
+    groupBy?: SearchGroupBy;
+    searchType?: SearchDataTypes;
+    columns?: SearchColumnType[];
+    canSelectMultiple: boolean;
+    onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
+    onCheckboxPress: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    nonPersonalAndWorkspaceCards?: CardList;
+    onUndelete?: (transaction: Transaction) => void;
+    newTransactionID?: string;
+    bankAccountList?: OnyxEntry<BankAccountList>;
+    cardFeeds?: OnyxCollection<CardFeeds>;
+    conciergeReportID?: string;
 };
 
 type UnreportedExpenseListItemType = Transaction & {
@@ -512,4 +568,9 @@ export type {
     TransactionListItemProps,
     ReportActionListItemType,
     UnreportedExpenseListItemType,
+    GroupHeaderItemType,
+    GroupChildrenContainerItemType,
+    GroupChildrenContentProps,
 };
+
+export {GROUP_ITEM_TYPES, isGroupHeaderItem, isGroupChildrenContainerItem};
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 836af7e5bdcd..d3dd9cdbb75f 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -28,15 +28,18 @@ import {turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
 import DateUtils from '@libs/DateUtils';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
 import navigationRef from '@libs/Navigation/navigationRef';
-import {getTableMinWidth} from '@libs/SearchUIUtils';
+import {getTableMinWidth, splitGroupsIntoPairs} from '@libs/SearchUIUtils';
 import variables from '@styles/variables';
 import type {TransactionPreviewData} from '@userActions/Search';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
 import type {CardList, Transaction} from '@src/types/onyx';
 import BaseSearchList from './BaseSearchList';
 import type ChatListItem from './ListItem/ChatListItem';
 import type ExpenseReportListItem from './ListItem/ExpenseReportListItem';
+import GroupChildrenContainer from './ListItem/GroupChildrenContainer';
+import GroupHeader from './ListItem/GroupHeader';
 import type TaskListItem from './ListItem/TaskListItem';
 import type TransactionGroupListItem from './ListItem/TransactionGroupListItem';
 import type TransactionListItem from './ListItem/TransactionListItem';
@@ -53,6 +56,7 @@ import type {
     TransactionWeekGroupListItemType,
     TransactionYearGroupListItemType,
 } from './ListItem/types';
+import {isGroupChildrenContainerItem, isGroupHeaderItem} from './ListItem/types';
 import SearchSelectAllMenu from './SearchSelectAllMenu';
 
 const easing = Easing.bezier(0.76, 0.0, 0.24, 1.0);
@@ -232,11 +236,11 @@ function SearchList({
         return data;
     }, [data, groupBy, type]);
     const emptyReports = useMemo(() => {
-        if (isTransactionGroupListItemArray(data)) {
-            return data.filter((item) => item.transactions.length === 0 && item.keyForList);
+        if (type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT && isTransactionGroupListItemArray(data)) {
+            return data.filter((item) => item.transactions.length === 0);
         }
         return [];
-    }, [data]);
+    }, [data, type]);
 
     const selectedItemsLength = useMemo(() => {
         const selectedTransactionsCount = flattenedItems.reduce((acc, item) => {
@@ -244,7 +248,7 @@ function SearchList({
             return acc + (isTransactionSelected ? 1 : 0);
         }, 0);
 
-        if (isTransactionGroupListItemArray(data)) {
+        if (type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT && isTransactionGroupListItemArray(data)) {
             const selectedEmptyReports = emptyReports.reduce((acc, item) => {
                 const isEmptyReportSelected = !!(item.keyForList && selectedTransactions[item.keyForList]?.isSelected);
                 return acc + (isEmptyReportSelected ? 1 : 0);
@@ -254,10 +258,10 @@ function SearchList({
         }
 
         return selectedTransactionsCount;
-    }, [flattenedItems, data, emptyReports, selectedTransactions]);
+    }, [flattenedItems, type, data, emptyReports, selectedTransactions]);
 
     const totalItems = useMemo(() => {
-        if (isTransactionGroupListItemArray(data)) {
+        if (type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT && isTransactionGroupListItemArray(data)) {
             const selectableEmptyReports = emptyReports.filter((item) => item.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
             const selectableTransactions = flattenedItems.filter((item) => {
                 if ('pendingAction' in item) {
@@ -275,7 +279,7 @@ function SearchList({
             return true;
         });
         return selectableTransactions.length;
-    }, [data, flattenedItems, emptyReports]);
+    }, [data, type, flattenedItems, emptyReports]);
 
     const {translate} = useLocalize();
     const {isOffline} = useNetwork();
@@ -294,10 +298,60 @@ function SearchList({
     const hasItemsBeingRemoved = prevDataLength && prevDataLength > data.length;
     const {isEditingCell, wasRecentlyEditingCell} = useEditingCellState();
 
+    const isGroupByActive = !!groupBy || type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
+    const [expandedGroups, setExpandedGroups] = useState<Set<string>>(() => new Set());
+
+    const onToggleGroup = useCallback((key: string) => {
+        setExpandedGroups((prev) => {
+            const next = new Set(prev);
+            if (next.has(key)) {
+                next.delete(key);
+            } else {
+                next.add(key);
+            }
+            return next;
+        });
+    }, []);
+
+    const shouldSplitGroups = isGroupByActive && isLargeScreenWidth;
+
+    const {splitData: listData, stickyHeaderIndices} = useMemo(() => {
+        if (!shouldSplitGroups) {
+            return {splitData: data, stickyHeaderIndices: undefined};
+        }
+        const {splitData, stickyHeaderIndices: allIndices} = splitGroupsIntoPairs(data);
+        const activeIndices = allIndices.filter((idx) => {
+            const item = splitData.at(idx);
+            const originalKey = item?.keyForList?.replace('header_', '') ?? '';
+            return expandedGroups.has(originalKey);
+        });
+        return {splitData, stickyHeaderIndices: activeIndices.length > 0 ? activeIndices : undefined};
+    }, [data, shouldSplitGroups, expandedGroups]);
+
+    const getItemType = useCallback(
+        (item: SearchListItem) => {
+            if (!shouldSplitGroups) {
+                return undefined;
+            }
+            if (isGroupHeaderItem(item)) {
+                return item.listItemType;
+            }
+            if (isGroupChildrenContainerItem(item)) {
+                return item.listItemType;
+            }
+            return 'default';
+        },
+        [shouldSplitGroups],
+    );
+
     const [lastPaymentMethod] = useOnyx(ONYXKEYS.NVP_LAST_PAYMENT_METHOD);
     const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID);
     const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END);
     const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END);
+    const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
+    const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
+    const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
+    const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
     const undeleteTransactions = useUndeleteTransactions();
 
     const handleUndelete = (transaction: Transaction) => undeleteTransactions([transaction]);
@@ -395,16 +449,21 @@ function SearchList({
                 return;
             }
 
-            // Don't scroll while a cell is being edited
-            // as it can cause unwanted scrolling when the edit is dismissed
-            // See: https://github.com/Expensify/App/pull/83127#issuecomment-4064533155
             if (isEditingCell || wasRecentlyEditingCell) {
                 return;
             }
 
-            listRef.current.scrollToIndex({index, animated, viewOffset: -variables.contentHeaderHeight});
+            let targetIndex = index;
+            if (shouldSplitGroups && item.keyForList) {
+                const splitIndex = listData.findIndex((li) => li.keyForList === `header_${item.keyForList}` || li.keyForList === item.keyForList);
+                if (splitIndex !== -1) {
+                    targetIndex = splitIndex;
+                }
+            }
+
+            listRef.current.scrollToIndex({index: targetIndex, animated, viewOffset: -variables.contentHeaderHeight});
         },
-        [data, isEditingCell, wasRecentlyEditingCell],
+        [data, isEditingCell, wasRecentlyEditingCell, shouldSplitGroups, listData],
     );
 
     useFocusEffect(
@@ -423,13 +482,81 @@ function SearchList({
     useImperativeHandle(ref, () => ({scrollToIndex}), [scrollToIndex]);
 
     const isItemVisible = useCallback((item: SearchListItem) => item.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || isOffline, [isOffline]);
-    const firstVisibleIndex = useMemo(() => data.findIndex(isItemVisible), [data, isItemVisible]);
-    const lastVisibleIndex = useMemo(() => data.findLastIndex(isItemVisible), [data, isItemVisible]);
+    const firstVisibleIndex = useMemo(() => listData.findIndex(isItemVisible), [listData, isItemVisible]);
+    const lastVisibleIndex = useMemo(() => listData.findLastIndex(isItemVisible), [listData, isItemVisible]);
 
     const renderItem = useCallback(
         (item: SearchListItem, index: number, isItemFocused: boolean, onFocus?: (event: NativeSyntheticEvent<ExtendedTargetedEvent>) => void) => {
+            // Handle group header items (sticky)
+            if (isGroupHeaderItem(item)) {
+                const headerItem = item;
+                const originalKey = (item.keyForList ?? '').replace('header_', '');
+                return (
+                    <GroupHeader
+                        item={headerItem}
+                        groupBy={groupBy}
+                        searchType={type}
+                        columns={columns}
+                        canSelectMultiple={canSelectMultiple}
+                        isExpanded={expandedGroups.has(originalKey)}
+                        onToggle={() => onToggleGroup(originalKey)}
+                        onSelectRow={(rowItem, previewData, event) => onSelectRow({...rowItem, keyForList: originalKey}, previewData, event)}
+                        onCheckboxPress={(val, itemTransactions) => onCheckboxPress({...val, keyForList: originalKey} as SearchListItem, itemTransactions)}
+                        onLongPressRow={(rowItem, itemTransactions) => {
+                            const fixedItem = {...rowItem, keyForList: originalKey} as SearchListItem;
+                            if (isMobileSelectionModeEnabled) {
+                                handleLongPressRowInMobileSelectionMode(fixedItem, itemTransactions);
+                            } else {
+                                handleLongPressRow(fixedItem, itemTransactions);
+                            }
+                        }}
+                        onFocus={onFocus}
+                        isFocused={isItemFocused}
+                        isFirstItem={index === firstVisibleIndex}
+                        isLastItem={index + 1 >= lastVisibleIndex && !ListFooterComponent}
+                        originalKey={originalKey}
+                        lastPaymentMethod={lastPaymentMethod}
+                        personalPolicyID={personalPolicyID}
+                        userBillingGracePeriodEnds={userBillingGracePeriodEnds}
+                        ownerBillingGracePeriodEnd={ownerBillingGracePeriodEnd}
+                        visibleColumns={visibleColumns}
+                    />
+                );
+            }
+
+            // Handle children container items (animated expand/collapse)
+            if (isGroupChildrenContainerItem(item)) {
+                const containerItem = item;
+                const originalKey = (item.keyForList ?? '').replace('children_', '');
+                const containerNewTransactionID = item.keyForList ? newTransactionIDByItemKey.get(originalKey) : undefined;
+                const isContainerSelected =
+                    !!containerItem.isSelected || (containerItem.transactions.length > 0 && containerItem.transactions.every((t) => selectedTransactions[t.transactionID]?.isSelected));
+                return (
+                    <GroupChildrenContainer
+                        item={containerItem}
+                        isExpanded={expandedGroups.has(originalKey)}
+                        isSelected={isContainerSelected}
+                        groupBy={groupBy}
+                        searchType={type}
+                        columns={columns}
+                        canSelectMultiple={canSelectMultiple}
+                        onSelectRow={onSelectRow}
+                        onCheckboxPress={onCheckboxPress}
+                        onLongPressRow={isMobileSelectionModeEnabled ? handleLongPressRowInMobileSelectionMode : handleLongPressRow}
+                        nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+                        onUndelete={handleUndelete}
+                        isLastItem={index === lastVisibleIndex && !ListFooterComponent}
+                        newTransactionID={containerNewTransactionID}
+                        bankAccountList={bankAccountList}
+                        cardFeeds={cardFeeds}
+                        conciergeReportID={conciergeReportID}
+                    />
+                );
+            }
+
+            // Default rendering for non-group items
             const isDisabled = item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
-            const shouldApplyAnimation = shouldAnimate && index < data.length - 1;
+            const shouldApplyAnimation = shouldAnimate && index < listData.length - 1;
 
             const newTransactionID = item.keyForList ? newTransactionIDByItemKey.get(item.keyForList) : undefined;
 
@@ -473,7 +600,7 @@ function SearchList({
             groupBy,
             newTransactionIDByItemKey,
             shouldAnimate,
-            data.length,
+            listData.length,
             styles.overflowHidden,
             hasItemsBeingRemoved,
             ListItem,
@@ -494,6 +621,13 @@ function SearchList({
             handleUndelete,
             firstVisibleIndex,
             lastVisibleIndex,
+            expandedGroups,
+            onToggleGroup,
+            bankAccountList,
+            cardFeeds,
+            conciergeReportID,
+            visibleColumns,
+            selectedTransactions,
         ],
     );
 
@@ -508,6 +642,7 @@ function SearchList({
                     style={[
                         styles.searchListHeaderContainerStyle,
                         isLargeScreenWidth ? [styles.listTableHeaderCompact, styles.searchListHeaderTableStyle, styles.mh5] : styles.listTableHeader,
+                        isLargeScreenWidth && shouldSplitGroups && styles.searchListHeaderTableStickyOverlap,
                     ]}
                 >
                     {canSelectMultiple && (
@@ -522,10 +657,11 @@ function SearchList({
                     )}
 
                     {SearchTableHeader}
+                    {isLargeScreenWidth && shouldSplitGroups && <View style={styles.searchListHeaderBorderCover} />}
                 </View>
             )}
             <BaseSearchList
-                data={data}
+                data={listData}
                 renderItem={renderItem}
                 onSelectRow={onSelectRow}
                 keyExtractor={keyExtractor}
@@ -534,7 +670,7 @@ function SearchList({
                 ref={listRef}
                 columns={columns}
                 scrollToIndex={scrollToIndex}
-                flattenedItemsLength={data.length}
+                flattenedItemsLength={listData.length}
                 onEndReached={onEndReached}
                 onEndReachedThreshold={onEndReachedThreshold}
                 ListFooterComponent={ListFooterComponent}
@@ -545,6 +681,8 @@ function SearchList({
                 selectedTransactions={selectedTransactions}
                 isAttendeesEnabledForMovingPolicy={isAttendeesEnabledForMovingPolicy}
                 nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+                stickyHeaderIndices={stickyHeaderIndices}
+                getItemType={getItemType}
             />
             <Modal
                 isVisible={isModalVisible}
diff --git a/src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx b/src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx
index eeafcf7f3065..13ccdacd59db 100644
--- a/src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx
+++ b/src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx
@@ -142,15 +142,13 @@ function SearchActionsBarCreateButton() {
                             const freshReportID = generateReportID();
                             const freshTransactionID = generateReportID();
                             Navigation.navigate(
-                                createDynamicRoute(
-                                    DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                        action: CONST.IOU.ACTION.CREATE,
-                                        iouType: CONST.IOU.TYPE.CREATE,
-                                        transactionID: freshTransactionID,
-                                        reportID: freshReportID,
-                                        upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                                    }),
-                                ),
+                                ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                    action: CONST.IOU.ACTION.CREATE,
+                                    iouType: CONST.IOU.TYPE.CREATE,
+                                    transactionID: freshTransactionID,
+                                    reportID: freshReportID,
+                                    upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                                }),
                             );
                             return;
                         }
diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx
index db8a64bc421e..f702a7e20a8e 100644
--- a/src/components/Search/SearchRouter/SearchRouter.tsx
+++ b/src/components/Search/SearchRouter/SearchRouter.tsx
@@ -375,7 +375,6 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
     useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ESCAPE, () => {
         onRouterClose();
     });
-    const updateAndScrollToFocusedIndex = useCallback(() => listRef.current?.updateAndScrollToFocusedIndex(searchQueryItems?.length ?? 1, true), [searchQueryItems?.length]);
 
     const modalWidth = shouldUseNarrowLayout ? styles.w100 : {width: variables.searchRouterPopoverWidth};
 
@@ -424,7 +423,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
                 searchQueryItems={searchQueryItems}
                 getAdditionalSections={getAdditionalSections}
                 onListItemPress={onListItemPress}
-                onHighlightFirstItem={updateAndScrollToFocusedIndex}
+                shouldHighlightFirstItem
                 ref={listRef}
                 textInputRef={textInputRef}
                 autocompleteSubstitutions={autocompleteSubstitutions}
diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx
index 2068734773bc..b974e2ffb743 100644
--- a/src/components/Search/index.tsx
+++ b/src/components/Search/index.tsx
@@ -350,6 +350,7 @@ function Search({
     const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
     const [customCardNames] = useOnyx(ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES);
     const [nonPersonalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST);
+    const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
     const reportAttributesDerivedValue = useReportAttributes();
 
@@ -603,7 +604,8 @@ function Search({
             queryJSON,
             isActionLoadingSet,
             cardFeeds,
-            cardList: nonPersonalAndWorkspaceCards,
+            cardList: personalAndWorkspaceCards,
+            nonPersonalAndWorkspaceCardList: nonPersonalAndWorkspaceCards,
             isOffline,
             allTransactionViolations: violations,
             customCardNames,
@@ -638,6 +640,7 @@ function Search({
         email,
         isActionLoadingSet,
         cardFeeds,
+        personalAndWorkspaceCards,
         nonPersonalAndWorkspaceCards,
         policies,
         bankAccountList,
diff --git a/src/components/SelectionList/ListItem/MultiSelectListItem.tsx b/src/components/SelectionList/ListItem/MultiSelectListItem.tsx
index b6d358c58a9b..d8f93bfe6d90 100644
--- a/src/components/SelectionList/ListItem/MultiSelectListItem.tsx
+++ b/src/components/SelectionList/ListItem/MultiSelectListItem.tsx
@@ -28,6 +28,7 @@ function MultiSelectListItem<TItem extends ListItem>({
     wrapperStyle,
     titleStyles,
     shouldHighlightSelectedItem,
+    titleNumberOfLines,
 }: MultiSelectListItemProps<TItem>) {
     const styles = useThemeStyles();
     const icon = item.icons?.at(0);
@@ -59,6 +60,7 @@ function MultiSelectListItem<TItem extends ListItem>({
             wrapperStyle={computedWrapperStyle}
             titleStyles={titleStyles}
             shouldHighlightSelectedItem={shouldHighlightSelectedItem}
+            titleNumberOfLines={titleNumberOfLines}
         />
     );
 }
diff --git a/src/components/SelectionList/ListItem/SingleSelectListItem.tsx b/src/components/SelectionList/ListItem/SingleSelectListItem.tsx
index f47ab05457e3..36fbbe6a2fb3 100644
--- a/src/components/SelectionList/ListItem/SingleSelectListItem.tsx
+++ b/src/components/SelectionList/ListItem/SingleSelectListItem.tsx
@@ -27,6 +27,7 @@ function SingleSelectListItem<TItem extends ListItem>({
     isFocusVisible,
     rightHandSideComponent,
     selectionButtonPosition,
+    titleNumberOfLines,
 }: SingleSelectListItemProps<TItem>) {
     const styles = useThemeStyles();
 
@@ -51,6 +52,7 @@ function SingleSelectListItem<TItem extends ListItem>({
             shouldHighlightSelectedItem={shouldHighlightSelectedItem}
             isFocusVisible={isFocusVisible}
             selectionButtonPosition={selectionButtonPosition}
+            titleNumberOfLines={titleNumberOfLines}
         />
     );
 }
diff --git a/src/components/Skeletons/TabNavigatorSkeleton.tsx b/src/components/Skeletons/TabNavigatorSkeleton.tsx
index a4aa38e96790..efffbbcf250e 100644
--- a/src/components/Skeletons/TabNavigatorSkeleton.tsx
+++ b/src/components/Skeletons/TabNavigatorSkeleton.tsx
@@ -18,32 +18,34 @@ function TabNavigatorSkeleton({reasonAttributes}: TabNavigatorSkeletonProps) {
 
     return (
         <View style={[styles.flexRow, styles.w100, styles.justifyContentBetween, styles.h10]}>
-            <SkeletonViewContentLoader
-                animate
-                height={40}
-                backgroundColor={theme.skeletonLHNIn}
-                foregroundColor={theme.skeletonLHNOut}
-                style={[styles.flex1, styles.ml4, styles.button, styles.highlightBG]}
-            >
-                <SkeletonRect
-                    transform={[{translateX: '20%'}, {translateY: 13}]}
+            <View style={[styles.flex1, styles.ml4, styles.button, styles.highlightBG, styles.alignItemsCenter, styles.justifyContentCenter]}>
+                <SkeletonViewContentLoader
+                    animate
                     width="60%"
-                    height={14}
-                />
-            </SkeletonViewContentLoader>
-            <SkeletonViewContentLoader
-                animate
-                height={40}
-                backgroundColor={theme.skeletonLHNIn}
-                foregroundColor={theme.skeletonLHNOut}
-                style={[styles.flex1, styles.mr4, styles.button, styles.appBG]}
-            >
-                <SkeletonRect
-                    transform={[{translateX: '20%'}, {translateY: 13}]}
+                    height="35%"
+                    backgroundColor={theme.skeletonLHNIn}
+                    foregroundColor={theme.skeletonLHNOut}
+                >
+                    <SkeletonRect
+                        width="100%"
+                        height="100%"
+                    />
+                </SkeletonViewContentLoader>
+            </View>
+            <View style={[styles.flex1, styles.mr4, styles.button, styles.appBG, styles.alignItemsCenter, styles.justifyContentCenter]}>
+                <SkeletonViewContentLoader
+                    animate
                     width="60%"
-                    height={14}
-                />
-            </SkeletonViewContentLoader>
+                    height="35%"
+                    backgroundColor={theme.skeletonLHNIn}
+                    foregroundColor={theme.skeletonLHNOut}
+                >
+                    <SkeletonRect
+                        width="100%"
+                        height="100%"
+                    />
+                </SkeletonViewContentLoader>
+            </View>
         </View>
     );
 }
diff --git a/src/components/SpendRules/SpendRulesSection.tsx b/src/components/SpendRules/SpendRulesSection.tsx
index 9e151d269dae..16947ae3762b 100644
--- a/src/components/SpendRules/SpendRulesSection.tsx
+++ b/src/components/SpendRules/SpendRulesSection.tsx
@@ -11,7 +11,6 @@ import Section from '@components/Section';
 import Text from '@components/Text';
 import useConfirmModal from '@hooks/useConfirmModal';
 import useDefaultFundID from '@hooks/useDefaultFundID';
-import useEnvironment from '@hooks/useEnvironment';
 import useExpensifyCardRules from '@hooks/useExpensifyCardRulesList';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -45,7 +44,6 @@ function SpendRulesSection({policyID, canWriteRules, showReadOnlyModal}: SpendRu
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['Lock', 'Plus']);
     const {showConfirmModal} = useConfirmModal();
     const illustrations = useMemoizedLazyIllustrations(['ExpensifyCardProtectionIllustration']);
-    const {isProduction} = useEnvironment();
     const {isOffline} = useNetwork();
     const defaultFundID = useDefaultFundID(policyID);
     const [expensifyCardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${defaultFundID}`);
@@ -220,24 +218,22 @@ function SpendRulesSection({policyID, canWriteRules, showReadOnlyModal}: SpendRu
                     </OfflineWithFeedback>
                 ))
             )}
-            {!isProduction && (
-                <MenuItem
-                    title={translate('workspace.rules.spendRules.addSpendRule')}
-                    titleStyle={styles.textStrong}
-                    icon={expensifyIcons.Plus}
-                    iconHeight={20}
-                    iconWidth={20}
-                    style={[styles.sectionMenuItemTopDescription, styles.mt6, styles.mbn3, !canWriteRules && styles.buttonOpacityDisabled]}
-                    onPress={() => {
-                        if (!canWriteRules) {
-                            showReadOnlyModal();
-                            return;
-                        }
-                        Navigation.navigate(ROUTES.RULES_SPEND_NEW.getRoute(policyID));
-                    }}
-                    sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.RULES.ADD_SPEND_RULE}
-                />
-            )}
+            <MenuItem
+                title={translate('workspace.rules.spendRules.addSpendRule')}
+                titleStyle={styles.textStrong}
+                icon={expensifyIcons.Plus}
+                iconHeight={20}
+                iconWidth={20}
+                style={[styles.sectionMenuItemTopDescription, styles.mt6, styles.mbn3, !canWriteRules && styles.buttonOpacityDisabled]}
+                sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.RULES.ADD_SPEND_RULE}
+                onPress={() => {
+                    if (!canWriteRules) {
+                        showReadOnlyModal();
+                        return;
+                    }
+                    Navigation.navigate(ROUTES.RULES_SPEND_NEW.getRoute(policyID));
+                }}
+            />
         </Section>
     );
 }
diff --git a/src/components/SpendRules/configuration/SpendRuleMaxAmountBase.tsx b/src/components/SpendRules/configuration/SpendRuleMaxAmountBase.tsx
index 5f1fe84d2679..7c2459c6678e 100644
--- a/src/components/SpendRules/configuration/SpendRuleMaxAmountBase.tsx
+++ b/src/components/SpendRules/configuration/SpendRuleMaxAmountBase.tsx
@@ -8,6 +8,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
 import Text from '@components/Text';
 import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
@@ -27,6 +28,7 @@ function SpendRuleMaxAmountBase({policyID, maxAmount, currencyCode, onMaxAmountC
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const {inputCallbackRef} = useAutoFocusInput();
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
 
     const goBack = () => {
         Navigation.goBack();
@@ -40,8 +42,9 @@ function SpendRuleMaxAmountBase({policyID, maxAmount, currencyCode, onMaxAmountC
     return (
         <AccessOrNotFoundWrapper
             policyID={policyID}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
+            shouldBeBlocked={!canWriteCardSpendRules}
         >
             <ScreenWrapper
                 shouldEnableMaxHeight
diff --git a/src/components/SpendRules/configuration/SpendRuleMerchantEditBase.tsx b/src/components/SpendRules/configuration/SpendRuleMerchantEditBase.tsx
index d033abe52510..5134cf8864ca 100644
--- a/src/components/SpendRules/configuration/SpendRuleMerchantEditBase.tsx
+++ b/src/components/SpendRules/configuration/SpendRuleMerchantEditBase.tsx
@@ -12,6 +12,7 @@ import type {ListItem} from '@components/SelectionList/ListItem/types';
 import Text from '@components/Text';
 import TextInput from '@components/TextInput';
 import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
@@ -37,6 +38,7 @@ function SpendRuleMerchantEditBase({policyID, merchantIndex, merchantMatchTypes,
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const {inputCallbackRef} = useAutoFocusInput();
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
 
     const isNew = merchantIndex === ROUTES.NEW;
     const index = isNew ? -1 : Number(merchantIndex);
@@ -98,7 +100,8 @@ function SpendRuleMerchantEditBase({policyID, merchantIndex, merchantMatchTypes,
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!canWriteCardSpendRules}
         >
             <ScreenWrapper
                 testID="SpendRuleMerchantEditPage"
diff --git a/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx b/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx
index 3db6f730f0b3..36614e27edb5 100644
--- a/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx
+++ b/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx
@@ -7,6 +7,7 @@ import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -29,6 +30,7 @@ function SpendRuleMerchantsBase({policyID, action, merchantMatchTypes, merchantN
     const {translate} = useLocalize();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['Plus']);
     const illustrations = useMemoizedLazyIllustrations(['FoodTruck']);
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
 
     const emptyStateTitle =
         action === CONST.SPEND_RULES.ACTION.BLOCK ? translate('workspace.rules.spendRules.noBlockedMerchants') : translate('workspace.rules.spendRules.noAllowedMerchants');
@@ -52,7 +54,8 @@ function SpendRuleMerchantsBase({policyID, action, merchantMatchTypes, merchantN
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!canWriteCardSpendRules}
         >
             <ScreenWrapper
                 testID="SpendRuleMerchantsPage"
diff --git a/src/components/TabSelector/TabSelectorBase.tsx b/src/components/TabSelector/TabSelectorBase.tsx
index 93916bfc1503..7209dc573e51 100644
--- a/src/components/TabSelector/TabSelectorBase.tsx
+++ b/src/components/TabSelector/TabSelectorBase.tsx
@@ -26,6 +26,7 @@ function TabSelectorBase({
     position,
     shouldShowLabelWhenInactive = true,
     equalWidth = false,
+    contentContainerStyles,
 }: TabSelectorBaseProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -61,7 +62,11 @@ function TabSelectorBase({
             }}
             ref={containerRef}
             style={styles.scrollableTabSelector}
-            contentContainerStyle={styles.tabSelectorContentContainer}
+            // On iOS a horizontal ScrollView lays out its content along an unbounded main axis, so flex-1 tabs
+            // (equalWidth) divide their intrinsic content width instead of the viewport. Giving the content
+            // container a definite width lets the flex children split it evenly. Scoped to equalWidth so normal
+            // overflowing/scrollable tab rows are not constrained.
+            contentContainerStyle={[styles.tabSelectorContentContainer, equalWidth && styles.w100, contentContainerStyles]}
             horizontal
             showsHorizontalScrollIndicator={false}
             keyboardShouldPersistTaps="handled"
@@ -119,6 +124,8 @@ function TabSelectorBase({
                         shouldShowLabelWhenInactive={shouldShowLabelWhenInactive}
                         equalWidth={equalWidth}
                         badgeText={tab.badgeText}
+                        isBadgeCondensed={tab.isBadgeCondensed}
+                        badgeStyles={tab.badgeStyles}
                         pendingAction={tab.pendingAction}
                         isDisabled={tab.isDisabled}
                     />
diff --git a/src/components/TabSelector/TabSelectorItem.tsx b/src/components/TabSelector/TabSelectorItem.tsx
index 421f643601b1..0b1e4a88a563 100644
--- a/src/components/TabSelector/TabSelectorItem.tsx
+++ b/src/components/TabSelector/TabSelectorItem.tsx
@@ -31,6 +31,8 @@ function TabSelectorItem({
     sentryLabel,
     equalWidth = false,
     badgeText,
+    isBadgeCondensed = false,
+    badgeStyles,
     isDisabled = false,
     pendingAction,
 }: TabSelectorItemProps) {
@@ -90,6 +92,8 @@ function TabSelectorItem({
                 <Badge
                     text={badgeText}
                     success
+                    isCondensed={isBadgeCondensed}
+                    badgeStyles={badgeStyles}
                 />
             )}
         </AnimatedPressableWithFeedback>
diff --git a/src/components/TabSelector/types.ts b/src/components/TabSelector/types.ts
index b32c41e37d15..9a80f4ac3aea 100644
--- a/src/components/TabSelector/types.ts
+++ b/src/components/TabSelector/types.ts
@@ -1,6 +1,6 @@
 import type {MaterialTopTabBarProps} from '@react-navigation/material-top-tabs';
 // eslint-disable-next-line no-restricted-imports
-import type {Animated} from 'react-native';
+import type {Animated, StyleProp, ViewStyle} from 'react-native';
 import type {ThemeColors} from '@styles/theme/types';
 import type {PendingAction} from '@src/types/onyx/OnyxCommon';
 import type IconAsset from '@src/types/utils/IconAsset';
@@ -39,6 +39,12 @@ type TabSelectorBaseItem = WithSentryLabel & {
     /** Text to display on the badge on the tab. */
     badgeText?: string;
 
+    /** Whether the tab's badge should use the condensed (smaller) style. */
+    isBadgeCondensed?: boolean;
+
+    /** Additional styles for the tab's badge. */
+    badgeStyles?: StyleProp<ViewStyle>;
+
     /** Whether this tab is disabled */
     isDisabled?: boolean;
 
@@ -70,6 +76,9 @@ type TabSelectorBaseProps = {
 
     /** Whether tabs should have equal width. */
     equalWidth?: boolean;
+
+    /** Additional styles for the tabs' scroll content container. */
+    contentContainerStyles?: StyleProp<ViewStyle>;
 };
 
 type TabSelectorItemProps = WithSentryLabel & {
@@ -112,6 +121,12 @@ type TabSelectorItemProps = WithSentryLabel & {
     /** Text to display on the badge on the tab. */
     badgeText?: string;
 
+    /** Whether the tab's badge should use the condensed (smaller) style. */
+    isBadgeCondensed?: boolean;
+
+    /** Additional styles for the tab's badge. */
+    badgeStyles?: StyleProp<ViewStyle>;
+
     /** Whether this tab is disabled */
     isDisabled?: boolean;
 
diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx
index 89d86d71f8a8..c95436c9b7d7 100644
--- a/src/components/Table/Table.tsx
+++ b/src/components/Table/Table.tsx
@@ -149,6 +149,7 @@ function Table<DataType extends TableData, ColumnKey extends string = string, Fi
     isItemInFilter,
     isItemInSearch,
     initialSortColumn,
+    narrowLayoutSortColumn,
     children,
     selectionEnabled,
     onRowSelectionChange,
@@ -163,6 +164,7 @@ function Table<DataType extends TableData, ColumnKey extends string = string, Fi
     }
 
     const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
+    const shouldUseNarrowTableLayout = shouldUseNarrowLayout || isMediumScreenWidth;
 
     const {middleware: filterMiddleware, currentFilters, methods: filterMethods} = useFiltering<DataType, FilterKey>({filters, isItemInFilter});
     const filteredData = filterMiddleware(data);
@@ -170,7 +172,16 @@ function Table<DataType extends TableData, ColumnKey extends string = string, Fi
     const {middleware: searchMiddleware, activeSearchString, methods: searchMethods} = useSearching<DataType>({isItemInSearch});
     const searchedData = searchMiddleware(filteredData);
 
-    const {middleware: sortMiddleware, activeSorting, methods: sortMethods} = useSorting<DataType, ColumnKey>({compareItems, initialSortColumn});
+    const {
+        middleware: sortMiddleware,
+        activeSorting,
+        methods: sortMethods,
+    } = useSorting<DataType, ColumnKey>({
+        compareItems,
+        initialSortColumn,
+        narrowLayoutSortColumn,
+        shouldUseNarrowTableLayout,
+    });
     const sortedData = sortMiddleware(searchedData);
 
     const {middleware: selectionMiddleware, methods: selectionMethods, mobileSelectionModalRowKey} = useSelection<DataType>({data: sortedData, selectedKeys, onRowSelectionChange});
@@ -206,7 +217,6 @@ function Table<DataType extends TableData, ColumnKey extends string = string, Fi
     });
 
     const originalDataLength = data?.length ?? 0;
-    const shouldUseNarrowTableLayout = shouldUseNarrowLayout || isMediumScreenWidth;
 
     // Check if filters are applied (not default values)
     const hasActiveFilters = filters
diff --git a/src/components/Table/middlewares/selection.ts b/src/components/Table/middlewares/selection.ts
index 3bfefd6efff1..b757664079fd 100644
--- a/src/components/Table/middlewares/selection.ts
+++ b/src/components/Table/middlewares/selection.ts
@@ -70,6 +70,14 @@ export default function useSelection<DataType extends TableData>({data, selected
         turnOffMobileSelectionMode();
     }, [selectableKeys.length, isSelectionModeEnabled]);
 
+    const prevSelectionModeEnabledRef = useRef(isSelectionModeEnabled);
+    useEffect(() => {
+        if (prevSelectionModeEnabledRef.current && !isSelectionModeEnabled) {
+            onRowSelectionChange?.([]);
+        }
+        prevSelectionModeEnabledRef.current = isSelectionModeEnabled;
+    }, [isSelectionModeEnabled, onRowSelectionChange]);
+
     /**
      * Clear all of the currently selected keys
      */
diff --git a/src/components/Table/middlewares/sorting.ts b/src/components/Table/middlewares/sorting.ts
index 1b775fffa91e..a31344ed6fcc 100644
--- a/src/components/Table/middlewares/sorting.ts
+++ b/src/components/Table/middlewares/sorting.ts
@@ -1,4 +1,4 @@
-import {useState} from 'react';
+import {useMemo, useState} from 'react';
 import type {SetStateAction} from 'react';
 import type {Middleware, MiddlewareHookResult} from './types';
 
@@ -60,6 +60,8 @@ type SortingMethods<ColumnKey extends string = string> = {
 type UseSortingProps<T, ColumnKey extends string = string> = {
     compareItems?: CompareItemsCallback<T, ColumnKey>;
     initialSortColumn?: ColumnKey;
+    narrowLayoutSortColumn?: ColumnKey;
+    shouldUseNarrowTableLayout?: boolean;
 };
 
 /**
@@ -82,14 +84,24 @@ type UseSortingResult<T, ColumnKey extends string = string> = MiddlewareHookResu
  * @param initialSortColumn - The initial column to sort by on mount.
  * @returns The result of the sorting middleware.
  */
-function useSorting<T, ColumnKey extends string = string>({compareItems, initialSortColumn}: UseSortingProps<T, ColumnKey>): UseSortingResult<T, ColumnKey> {
-    const [activeSorting, updateSorting] = useState<ActiveSorting<ColumnKey>>({
+function useSorting<T, ColumnKey extends string = string>({
+    compareItems,
+    initialSortColumn,
+    narrowLayoutSortColumn,
+    shouldUseNarrowTableLayout,
+}: UseSortingProps<T, ColumnKey>): UseSortingResult<T, ColumnKey> {
+    const [userSorting, setUserSorting] = useState<ActiveSorting<ColumnKey>>({
         columnKey: initialSortColumn,
         order: 'asc',
     });
 
+    const activeSorting = useMemo(
+        () => (shouldUseNarrowTableLayout && narrowLayoutSortColumn ? ({columnKey: narrowLayoutSortColumn, order: 'asc'} satisfies ActiveSorting<ColumnKey>) : userSorting),
+        [shouldUseNarrowTableLayout, narrowLayoutSortColumn, userSorting],
+    );
+
     const toggleColumnSorting: SortingMethods<ColumnKey>['toggleColumnSorting'] = (columnKey) => {
-        updateSorting((previousSorting) => {
+        setUserSorting((previousSorting) => {
             const columnKeyToUse = columnKey ?? previousSorting.columnKey;
             const orderToUse = previousSorting.order === 'asc' ? 'desc' : 'asc';
 
@@ -107,7 +119,7 @@ function useSorting<T, ColumnKey extends string = string>({compareItems, initial
     const middleware: Middleware<T> = (data) => sort({data, activeSorting, compareItems});
 
     const methods: SortingMethods<ColumnKey> = {
-        updateSorting,
+        updateSorting: setUserSorting,
         toggleColumnSorting,
         getActiveSorting,
     };
diff --git a/src/components/Table/types.ts b/src/components/Table/types.ts
index 834fad6a2ed9..bb1168abf553 100644
--- a/src/components/Table/types.ts
+++ b/src/components/Table/types.ts
@@ -138,6 +138,9 @@ type TableProps<DataType extends TableData, ColumnKey extends string = string, F
         /** Optional initial column to sort by on mount. */
         initialSortColumn?: ColumnKey;
 
+        /** Optional column to force-sort by when the table switches to narrow layout. The wide-layout sorting is restored when leaving narrow layout. */
+        narrowLayoutSortColumn?: ColumnKey;
+
         /** Optional initial search string to apply on mount. */
         initialSearchString?: string;
 
diff --git a/src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx b/src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx
index 05ce37a59527..f4ac34160422 100644
--- a/src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx
+++ b/src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx
@@ -13,7 +13,7 @@ import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {formatMaskedCardName, getCardFeedWithDomainID} from '@libs/CardUtils';
+import {formatMaskedCardName} from '@libs/CardUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import variables from '@styles/variables';
@@ -45,6 +45,9 @@ type WorkspaceCompanyCardTableRowProps = {
     /** Policy ID */
     policyID: string;
 
+    /** Selected card feed */
+    feedName?: CompanyCardFeedWithDomainID;
+
     /** Card feed icon element */
     CardFeedIcon?: React.ReactNode;
 
@@ -71,6 +74,7 @@ type WorkspaceCompanyCardTableRowProps = {
 function WorkspaceCompanyCardTableRow({
     item,
     policyID,
+    feedName,
     CardFeedIcon,
     shouldUseNarrowTableLayout,
     rowIndex,
@@ -108,7 +112,7 @@ function WorkspaceCompanyCardTableRow({
         ? {width: variables.cardAvatarWidth, height: variables.cardAvatarHeight}
         : {width: variables.cardAvatarWidthSmall, height: variables.cardAvatarHeightSmall};
 
-    const canOpenCardDetails = !!assignedCard?.accountID && !!assignedCard?.fundID && assignedCard?.cardID !== undefined;
+    const canOpenCardDetails = !!assignedCard?.accountID && assignedCard?.cardID !== undefined && !!feedName;
     const canAssignCard = !isAssigned && canWriteCompanyCards && !isAssigningCardDisabled;
     const canPressRow = canOpenCardDetails || canAssignCard;
 
@@ -122,14 +126,12 @@ function WorkspaceCompanyCardTableRow({
             return;
         }
 
-        const {cardID, fundID} = assignedCard;
-        if (!canOpenCardDetails || cardID === undefined || !fundID) {
+        const {cardID} = assignedCard;
+        if (!canOpenCardDetails || cardID === undefined || !feedName) {
             return;
         }
 
-        const feedName = getCardFeedWithDomainID(assignedCard?.bank as CompanyCardFeed, fundID);
-
-        return Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_DETAILS.getRoute(policyID, feedName as CompanyCardFeedWithDomainID, cardID.toString()));
+        return Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_DETAILS.getRoute(policyID, feedName, cardID.toString()));
     };
 
     return (
diff --git a/src/components/Tables/WorkspaceCompanyCardsTable/index.tsx b/src/components/Tables/WorkspaceCompanyCardsTable/index.tsx
index f7cb8d672a3c..1679b0f7154d 100644
--- a/src/components/Tables/WorkspaceCompanyCardsTable/index.tsx
+++ b/src/components/Tables/WorkspaceCompanyCardsTable/index.tsx
@@ -294,6 +294,7 @@ function WorkspaceCompanyCardsTable({
             item={item}
             rowIndex={index}
             policyID={policyID ?? String(CONST.DEFAULT_NUMBER_ID)}
+            feedName={feedName}
             CardFeedIcon={cardFeedIcon}
             onAssignCard={onAssignCard}
             isAssigningCardDisabled={isAssigningCardDisabled}
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
new file mode 100644
index 000000000000..5e4eb71e49fd
--- /dev/null
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -0,0 +1,195 @@
+import {format, parseISO} from 'date-fns';
+import React from 'react';
+import {View} from 'react-native';
+import Icon from '@components/Icon';
+import StatusBadge from '@components/StatusBadge';
+import Switch from '@components/Switch';
+import Table from '@components/Table';
+import type {TableData} from '@components/Table';
+import {useTableContext} from '@components/Table/TableContext';
+import TextWithTooltip from '@components/TextWithTooltip';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import DistanceRequestUtils from '@libs/DistanceRequestUtils';
+import {getRateStatus} from '@libs/PolicyDistanceRatesUtils';
+import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
+import variables from '@styles/variables';
+import CONST from '@src/CONST';
+import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
+import type {Rate} from '@src/types/onyx/Policy';
+
+type DistanceRateTableItemData = TableData & {
+    rateID: string;
+    rate: Rate;
+    formattedRate: string;
+    enabled: boolean;
+    isLocked: boolean;
+    pendingAction?: OnyxCommon.PendingAction;
+    errors?: OnyxCommon.Errors;
+    action: () => void;
+    dismissError: () => void;
+    onToggleEnabled: (value: boolean) => void;
+};
+
+type WorkspaceDistanceRatesTableRowProps = {
+    item: DistanceRateTableItemData;
+    rowIndex: number;
+    shouldUseNarrowTableLayout: boolean;
+    shouldShowDateColumns: boolean;
+    statusLabels: Record<string, string>;
+};
+
+function formatDate(dateString: string | null | undefined): string {
+    if (!dateString) {
+        return '';
+    }
+    return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT);
+}
+
+function getRateStatusColors(status: string, theme: ReturnType<typeof useTheme>, isSelected?: boolean) {
+    switch (status) {
+        case CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE:
+            return theme.reportStatusBadge.paid;
+        case CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE:
+            return theme.reportStatusBadge.draft;
+        case CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED:
+            return theme.reportStatusBadge.outstanding;
+        case CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE:
+        default:
+            return {backgroundColor: isSelected ? theme.buttonHoveredBG : theme.badgeDefaultBG, textColor: theme.text};
+    }
+}
+
+function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLayout, shouldShowDateColumns, statusLabels}: WorkspaceDistanceRatesTableRowProps) {
+    const theme = useTheme();
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const Expensicons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
+    const {processedData} = useTableContext<DistanceRateTableItemData>();
+
+    const {rate, formattedRate, pendingAction, errors} = item;
+    const isDeleting = pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
+    const isSelected = processedData.at(rowIndex)?.selected ?? false;
+
+    const status = getRateStatus(rate);
+    const statusColors = getRateStatusColors(status, theme, isSelected);
+    const dateLabelText = DistanceRequestUtils.getRateDateLabel({...rate, unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES}, translate);
+
+    const accessibilityLabel = [rate.name, statusLabels[status], formattedRate, dateLabelText].filter(Boolean).join(', ');
+
+    const reasonAttributes: SkeletonSpanReasonAttributes = {
+        context: 'WorkspaceDistanceRatesTableItem',
+        isDeleting,
+    };
+
+    return (
+        <Table.Row
+            interactive
+            rowIndex={rowIndex}
+            disabled={item.disabled}
+            accessibilityLabel={accessibilityLabel}
+            skeletonReasonAttributes={reasonAttributes}
+            sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.DISTANCE_RATES.ROW}
+            offlineWithFeedback={{errors, pendingAction, dismissError: item.dismissError, shouldHideOnDelete: false}}
+            onPress={item.action}
+        >
+            {({hovered}) => (
+                <>
+                    {shouldUseNarrowTableLayout && (
+                        <View style={[styles.flex1, styles.justifyContentCenter]}>
+                            <TextWithTooltip
+                                text={rate.name ?? ''}
+                                style={[styles.optionDisplayName, styles.pre]}
+                            />
+                            <View style={[styles.flexRow, styles.alignItemsCenter, styles.mt1, styles.gap2]}>
+                                <StatusBadge
+                                    text={statusLabels[status] ?? ''}
+                                    backgroundColor={statusColors.backgroundColor}
+                                    textColor={statusColors.textColor}
+                                />
+                                <TextWithTooltip
+                                    text={[formattedRate, dateLabelText].filter(Boolean).join(` ${CONST.DOT_SEPARATOR} `)}
+                                    numberOfLines={1}
+                                    style={[styles.textLabelSupporting, styles.lh16, styles.pre, styles.flexShrink1]}
+                                />
+                            </View>
+                        </View>
+                    )}
+
+                    {!shouldUseNarrowTableLayout && (
+                        <View style={[styles.justifyContentCenter]}>
+                            <StatusBadge
+                                text={statusLabels[status] ?? ''}
+                                backgroundColor={statusColors.backgroundColor}
+                                textColor={statusColors.textColor}
+                            />
+                        </View>
+                    )}
+
+                    {!shouldUseNarrowTableLayout && (
+                        <View style={[styles.flex1]}>
+                            <TextWithTooltip
+                                numberOfLines={1}
+                                text={rate.name ?? ''}
+                                style={[styles.lh16, styles.optionDisplayName, styles.pre]}
+                            />
+                        </View>
+                    )}
+
+                    {!shouldUseNarrowTableLayout && (
+                        <View style={[styles.flex1]}>
+                            <TextWithTooltip
+                                numberOfLines={1}
+                                text={formattedRate}
+                                style={[styles.lh16, styles.optionDisplayName, styles.pre]}
+                            />
+                        </View>
+                    )}
+
+                    {!shouldUseNarrowTableLayout && shouldShowDateColumns && (
+                        <View style={[styles.flex1]}>
+                            <TextWithTooltip
+                                numberOfLines={1}
+                                text={formatDate(rate.startDate)}
+                                style={[styles.lh16, styles.optionDisplayName, styles.pre]}
+                            />
+                        </View>
+                    )}
+
+                    {!shouldUseNarrowTableLayout && shouldShowDateColumns && (
+                        <View style={[styles.flex1]}>
+                            <TextWithTooltip
+                                numberOfLines={1}
+                                text={formatDate(rate.endDate)}
+                                style={[styles.lh16, styles.optionDisplayName, styles.pre]}
+                            />
+                        </View>
+                    )}
+
+                    <View style={[styles.justifyContentCenter, styles.alignItemsEnd]}>
+                        <Switch
+                            isOn={item.enabled}
+                            showLockIcon={item.isLocked}
+                            disabled={item.disabled}
+                            accessibilityLabel={rate.name ?? ''}
+                            onToggle={item.onToggleEnabled}
+                        />
+                    </View>
+
+                    <Icon
+                        src={Expensicons.ArrowRight}
+                        fill={theme.icon}
+                        additionalStyles={[styles.justifyContentCenter, styles.alignItemsCenter, (!hovered || item.disabled) && styles.opacitySemiTransparent]}
+                        width={variables.iconSizeNormal}
+                        height={variables.iconSizeNormal}
+                    />
+                </>
+            )}
+        </Table.Row>
+    );
+}
+
+export default WorkspaceDistanceRatesTableRow;
+export type {DistanceRateTableItemData};
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
new file mode 100644
index 000000000000..9f978e980a97
--- /dev/null
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -0,0 +1,150 @@
+import type {ListRenderItemInfo} from '@shopify/flash-list';
+import React, {useMemo} from 'react';
+import Table from '@components/Table';
+import type {CompareItemsCallback, IsItemInSearchCallback, TableColumn} from '@components/Table';
+import useLocalize from '@hooks/useLocalize';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {getRateStatus} from '@libs/PolicyDistanceRatesUtils';
+import tokenizedSearch from '@libs/tokenizedSearch';
+import variables from '@styles/variables';
+import CONST from '@src/CONST';
+import WorkspaceDistanceRatesTableRow from './WorkspaceDistanceRatesTableRow';
+import type {DistanceRateTableItemData} from './WorkspaceDistanceRatesTableRow';
+
+type DistanceRatesTableColumnKey = 'status' | 'name' | 'rate' | 'startDate' | 'endDate' | 'enabled' | 'actions';
+
+type WorkspaceDistanceRatesTableProps = {
+    ratesData: DistanceRateTableItemData[];
+    selectionEnabled: boolean;
+    selectedKeys: string[];
+    onRowSelectionChange: (selectedRowKeys: string[]) => void;
+};
+
+const STATUS_ORDER: Record<string, number> = {
+    [CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE]: 0,
+    [CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE]: 1,
+    [CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED]: 2,
+    [CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE]: 3,
+};
+
+function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys, onRowSelectionChange}: WorkspaceDistanceRatesTableProps) {
+    const styles = useThemeStyles();
+    const {translate, localeCompare} = useLocalize();
+    const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
+    const shouldUseNarrowTableLayout = shouldUseNarrowLayout || isMediumScreenWidth;
+
+    const hasAnyDateBound = ratesData.some((item) => !!item.rate.startDate || !!item.rate.endDate);
+
+    const columns: Array<TableColumn<DistanceRatesTableColumnKey>> = [
+        {
+            key: 'status',
+            label: translate('workspace.distanceRates.status'),
+            sortable: true,
+            width: variables.tableStatusColumnWidth,
+            styling: {containerStyles: [styles.justifyContentCenter]},
+        },
+        {key: 'name', label: translate('common.name'), sortable: true},
+        {key: 'rate', label: translate('workspace.distanceRates.rate'), sortable: true},
+        ...(hasAnyDateBound
+            ? ([
+                  {key: 'startDate', label: translate('workspace.distanceRates.startDate'), sortable: true},
+                  {key: 'endDate', label: translate('workspace.distanceRates.endDate'), sortable: true},
+              ] as const)
+            : []),
+        {key: 'enabled', label: translate('common.enabled'), sortable: true, width: variables.tableSwitchColumnWidth, styling: {containerStyles: [styles.justifyContentEnd]}},
+        {key: 'actions', label: '', sortable: false, width: variables.tableCaretColumnWidth},
+    ];
+
+    const compareItems: CompareItemsCallback<DistanceRateTableItemData, DistanceRatesTableColumnKey> = (a, b, activeSorting) => {
+        const orderMultiplier = activeSorting.order === 'asc' ? 1 : -1;
+
+        if (activeSorting.columnKey === 'status') {
+            const aStatus = getRateStatus(a.rate);
+            const bStatus = getRateStatus(b.rate);
+            const diff = (STATUS_ORDER[aStatus] ?? 0) - (STATUS_ORDER[bStatus] ?? 0);
+            if (diff !== 0) {
+                return diff * orderMultiplier;
+            }
+            return localeCompare(a.rate.name ?? '', b.rate.name ?? '') * orderMultiplier;
+        }
+
+        if (activeSorting.columnKey === 'name') {
+            return localeCompare(a.rate.name ?? '', b.rate.name ?? '') * orderMultiplier;
+        }
+
+        if (activeSorting.columnKey === 'rate') {
+            return ((a.rate.rate ?? 0) - (b.rate.rate ?? 0)) * orderMultiplier;
+        }
+
+        if (activeSorting.columnKey === 'startDate') {
+            return localeCompare(a.rate.startDate ?? '', b.rate.startDate ?? '') * orderMultiplier;
+        }
+
+        if (activeSorting.columnKey === 'endDate') {
+            return localeCompare(a.rate.endDate ?? '', b.rate.endDate ?? '') * orderMultiplier;
+        }
+
+        if (activeSorting.columnKey === 'enabled') {
+            return ((a.enabled ? 1 : 0) - (b.enabled ? 1 : 0)) * orderMultiplier;
+        }
+
+        return 0;
+    };
+
+    const isItemInSearch: IsItemInSearchCallback<DistanceRateTableItemData> = (item, searchString) => {
+        const matchingItems = tokenizedSearch([item], searchString, (i) => [i.rate.name ?? '', i.formattedRate]);
+        return matchingItems.length > 0;
+    };
+
+    const statusLabels = useMemo(
+        () => ({
+            [CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE]: translate('workspace.distanceRates.statusActive'),
+            [CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE]: translate('workspace.distanceRates.statusFuture'),
+            [CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED]: translate('workspace.distanceRates.statusExpired'),
+            [CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE]: translate('workspace.distanceRates.statusInactive'),
+        }),
+        [translate],
+    );
+
+    const renderItem = ({item, index}: ListRenderItemInfo<DistanceRateTableItemData>) => (
+        <WorkspaceDistanceRatesTableRow
+            key={item.rateID}
+            item={item}
+            rowIndex={index}
+            shouldUseNarrowTableLayout={shouldUseNarrowTableLayout}
+            shouldShowDateColumns={hasAnyDateBound}
+            statusLabels={statusLabels}
+        />
+    );
+
+    const isEmpty = ratesData.length === 0;
+    const shouldShowSearchBar = ratesData.length >= CONST.STANDARD_LIST_ITEM_LIMIT;
+
+    return (
+        <Table
+            data={ratesData}
+            columns={columns}
+            selectionEnabled={selectionEnabled}
+            selectedKeys={selectedKeys}
+            onRowSelectionChange={onRowSelectionChange}
+            renderItem={renderItem}
+            keyExtractor={(item) => item.keyForList}
+            compareItems={compareItems}
+            isItemInSearch={isItemInSearch}
+            initialSortColumn="name"
+            narrowLayoutSortColumn="name"
+            title={translate('workspace.common.distanceRates')}
+        >
+            {!isEmpty && (
+                <>
+                    {shouldShowSearchBar && <Table.SearchBar label={translate('workspace.distanceRates.findRate')} />}
+                    <Table.Header />
+                    <Table.Body />
+                </>
+            )}
+        </Table>
+    );
+}
+
+export default WorkspaceDistanceRatesTable;
diff --git a/src/components/Tables/WorkspaceRoomsTable/WorkspaceRoomsTableRow.tsx b/src/components/Tables/WorkspaceRoomsTable/WorkspaceRoomsTableRow.tsx
index aac049417db3..b7afb850a51b 100644
--- a/src/components/Tables/WorkspaceRoomsTable/WorkspaceRoomsTableRow.tsx
+++ b/src/components/Tables/WorkspaceRoomsTable/WorkspaceRoomsTableRow.tsx
@@ -1,6 +1,5 @@
 import React from 'react';
 import {View} from 'react-native';
-import Avatar from '@components/Avatar';
 import Icon from '@components/Icon';
 import ReportActionAvatars from '@components/ReportActionAvatars';
 import type {TableData} from '@components/Table';
@@ -11,7 +10,6 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
-import type {AvatarSource} from '@libs/UserUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 
@@ -22,15 +20,6 @@ type WorkspaceRoomRowData = TableData & {
     /** The room display name */
     name: string;
 
-    /** Owner accountID for resolving the avatar */
-    ownerAccountID?: number;
-
-    /** Owner avatar source */
-    ownerAvatar?: AvatarSource;
-
-    /** Pre-formatted owner display name */
-    ownerDisplayName: string;
-
     /** Number of members in the room */
     memberCount: number;
 
@@ -59,7 +48,6 @@ function WorkspaceRoomsTableRow({item, rowIndex, shouldUseNarrowTableLayout, sho
     const icons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
 
     const memberCountSubtitle = translate('domain.groups.memberCount', {count: item.memberCount});
-    const narrowSubtitle = item.ownerDisplayName ? `${translate('common.createdBy')}: ${item.ownerDisplayName} • ${memberCountSubtitle}` : memberCountSubtitle;
 
     return (
         <Table.Row
@@ -91,7 +79,7 @@ function WorkspaceRoomsTableRow({item, rowIndex, shouldUseNarrowTableLayout, sho
                                     numberOfLines={1}
                                     style={styles.textLabelSupporting}
                                 >
-                                    {narrowSubtitle}
+                                    {memberCountSubtitle}
                                 </Text>
                             </View>
                             <Icon
@@ -121,26 +109,6 @@ function WorkspaceRoomsTableRow({item, rowIndex, shouldUseNarrowTableLayout, sho
                                 />
                             </View>
 
-                            <View style={[styles.flex1, styles.flexRow, styles.gap2, styles.alignItemsCenter]}>
-                                {!!item.ownerDisplayName && (
-                                    <>
-                                        {!!item.ownerAccountID && (
-                                            <Avatar
-                                                source={item.ownerAvatar}
-                                                avatarID={item.ownerAccountID}
-                                                type={CONST.ICON_TYPE_AVATAR}
-                                                size={CONST.AVATAR_SIZE.MID_SUBSCRIPT}
-                                            />
-                                        )}
-                                        <TextWithTooltip
-                                            shouldShowTooltip
-                                            text={item.ownerDisplayName}
-                                            style={styles.flexShrink1}
-                                        />
-                                    </>
-                                )}
-                            </View>
-
                             <View style={styles.flex1}>
                                 <Text numberOfLines={1}>{item.memberCount}</Text>
                             </View>
diff --git a/src/components/Tables/WorkspaceRoomsTable/index.tsx b/src/components/Tables/WorkspaceRoomsTable/index.tsx
index b8466bc88907..2030d43de85e 100644
--- a/src/components/Tables/WorkspaceRoomsTable/index.tsx
+++ b/src/components/Tables/WorkspaceRoomsTable/index.tsx
@@ -10,7 +10,7 @@ import variables from '@styles/variables';
 import WorkspaceRoomsTableRow from './WorkspaceRoomsTableRow';
 import type {WorkspaceRoomRowData} from './WorkspaceRoomsTableRow';
 
-type WorkspaceRoomsTableColumnKey = 'name' | 'createdBy' | 'members' | 'actions';
+type WorkspaceRoomsTableColumnKey = 'name' | 'members' | 'actions';
 
 type WorkspaceRoomsTableProps = {
     /** Pre-built row data for each room */
@@ -46,7 +46,6 @@ function WorkspaceRoomsTable({rooms, highlightedReportID}: WorkspaceRoomsTablePr
 
     const columns: Array<TableColumn<WorkspaceRoomsTableColumnKey>> = [
         {key: 'name', label: translate('common.name'), sortable: true},
-        {key: 'createdBy', label: translate('common.createdBy'), sortable: true},
         {key: 'members', label: translate('common.members'), width: variables.workspaceRoomsMembersColumnWidth, sortable: true},
         {key: 'actions', label: '', width: variables.workspaceRoomsActionsColumnWidth, styling: {containerStyles: [styles.justifyContentEnd, styles.pr3]}, sortable: false},
     ];
@@ -54,10 +53,6 @@ function WorkspaceRoomsTable({rooms, highlightedReportID}: WorkspaceRoomsTablePr
     const compareItems: CompareItemsCallback<WorkspaceRoomRowData, WorkspaceRoomsTableColumnKey> = (a, b, activeSorting) => {
         const orderMultiplier = activeSorting.order === 'asc' ? 1 : -1;
 
-        if (activeSorting.columnKey === 'createdBy') {
-            return orderMultiplier * localeCompare(a.ownerDisplayName, b.ownerDisplayName);
-        }
-
         if (activeSorting.columnKey === 'members') {
             return orderMultiplier * (a.memberCount - b.memberCount);
         }
diff --git a/src/components/TagPicker/index.tsx b/src/components/TagPicker/index.tsx
index 8e139d3c8a01..434ae4466905 100644
--- a/src/components/TagPicker/index.tsx
+++ b/src/components/TagPicker/index.tsx
@@ -161,20 +161,20 @@ function TagPicker({
         ref: inputCallbackRef as (ref: BaseTextInputRef | null) => void,
     };
 
-    const listItemTitleStyles = [styles.breakAll, styles.w100];
-
     return (
         <SelectionListWithSections
             sections={sections}
             ListItem={SingleSelectListItem}
             style={{
                 sectionTitleStyles: styles.mt5,
-                listItemTitleStyles,
+                listItemTitleStyles: styles.w100,
             }}
             textInputOptions={textInputOptions}
             shouldShowTextInput={availableTagsCount >= CONST.STANDARD_LIST_ITEM_LIMIT}
             initiallyFocusedItemKey={selectedOptionKey}
             onSelectRow={onSubmit}
+            isRowMultilineSupported
+            titleNumberOfLines={CONST.TRANSACTION_TAG_AND_CATEGORY_PICKER_MAX_TITLE_LINES}
         />
     );
 }
diff --git a/src/components/TransactionItemRow/DataCells/TotalCell.tsx b/src/components/TransactionItemRow/DataCells/TotalCell.tsx
index 18ec1cd2060c..4f910c6faa3b 100644
--- a/src/components/TransactionItemRow/DataCells/TotalCell.tsx
+++ b/src/components/TransactionItemRow/DataCells/TotalCell.tsx
@@ -11,7 +11,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {convertToBackendAmount, convertToFrontendAmountAsString, getCurrencyDecimals, sanitizeCurrencyCode} from '@libs/CurrencyUtils';
 import {formatToParts} from '@libs/NumberFormatUtils';
 import {parseFloatAnyLocale, roundToTwoDecimalPlaces} from '@libs/NumberUtils';
-import {isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {isGroupPolicy} from '@libs/PolicyUtils';
 import {isExpenseReport, isInvoiceReport, shouldEnableNegative} from '@libs/ReportUtils';
 import {getAmount as getTransactionAmount, getCurrency as getTransactionCurrency, isDeletedTransaction, isExpenseUnreported, isScanning} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
@@ -47,7 +47,7 @@ function TotalCell({shouldShowTooltip, transactionItem, canEdit, onSave, report,
     const effectiveReport = report ?? transactionItem.report;
     const effectivePolicy = policy ?? transactionItem.policy;
     const isDeleted = isDeletedTransaction(transactionItem);
-    const isFromExpenseReport = (!isEmptyObject(effectiveReport) && isExpenseReport(effectiveReport)) || isPaidGroupPolicy(effectivePolicy);
+    const isFromExpenseReport = (!isEmptyObject(effectiveReport) && isExpenseReport(effectiveReport)) || isGroupPolicy(effectivePolicy);
     const amount = getTransactionAmount(transactionItem, isFromExpenseReport, transactionItem.reportID === CONST.REPORT.UNREPORTED_REPORT_ID, isDeleted);
     let amountToDisplay = convertToDisplayString(amount, currency);
     if (isScanning(transactionItem)) {
diff --git a/src/components/TransactionItemRow/TransactionItemRowWide.tsx b/src/components/TransactionItemRow/TransactionItemRowWide.tsx
index 9c09063f9214..3507989a14b1 100644
--- a/src/components/TransactionItemRow/TransactionItemRowWide.tsx
+++ b/src/components/TransactionItemRow/TransactionItemRowWide.tsx
@@ -113,6 +113,7 @@ function TransactionItemRowWide({
     totalPerAttendee,
     transactionThreadReportID,
     createdAt,
+    isMarkAsDone,
 }: TransactionItemRowWideProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -304,6 +305,7 @@ function TransactionItemRowWide({
                                 hash={transactionItem?.hash}
                                 amount={report?.total}
                                 shouldDisablePointerEvents={isDisabled}
+                                isMarkAsDone={isMarkAsDone}
                             />
                         )}
                     </View>
diff --git a/src/components/TransactionItemRow/index.tsx b/src/components/TransactionItemRow/index.tsx
index ae0024e52a13..cebbc85f037d 100644
--- a/src/components/TransactionItemRow/index.tsx
+++ b/src/components/TransactionItemRow/index.tsx
@@ -1,12 +1,14 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import type {StyleProp, ViewStyle} from 'react-native';
 import useAttendees from '@hooks/useAttendees';
 import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getCompanyCardDescription} from '@libs/CardUtils';
 import {getDecodedCategoryName, isCategoryMissing} from '@libs/CategoryUtils';
 import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
-import {isExpenseReport, isSettled} from '@libs/ReportUtils';
+import {isExpenseReport, isSettled, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import StringUtils from '@libs/StringUtils';
 import {
     getAmount,
@@ -22,6 +24,7 @@ import {
 } from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
+import ONYXKEYS from '@src/ONYXKEYS';
 import TransactionItemRowNarrow from './TransactionItemRowNarrow';
 import TransactionItemRowWide from './TransactionItemRowWide';
 import type {TransactionItemRowProps, TransactionWithOptionalSearchFields} from './types';
@@ -97,6 +100,12 @@ function TransactionItemRow({
     canEditAmount,
     canEditTag,
 }: TransactionItemRowProps) {
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report,
+        isTrackIntentUser,
+    });
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const createdAt = getTransactionCreated(transactionItem);
@@ -253,6 +262,7 @@ function TransactionItemRow({
             totalPerAttendee={!attendeesCount || totalAmount === undefined ? undefined : totalAmount / attendeesCount}
             createdAt={createdAt}
             transactionThreadReportID={transactionThreadReportID}
+            isMarkAsDone={shouldUseMarkAsDoneCopy}
         />
     );
 }
diff --git a/src/components/TransactionItemRow/types.ts b/src/components/TransactionItemRow/types.ts
index 747228ef6845..82e5001c6d79 100644
--- a/src/components/TransactionItemRow/types.ts
+++ b/src/components/TransactionItemRow/types.ts
@@ -140,6 +140,7 @@ type TransactionItemRowWideComputedData = Omit<TransactionItemRowNarrowComputedD
     transactionAttendees: Attendee[];
     shouldShowAttendees: boolean;
     totalPerAttendee: number | undefined;
+    isMarkAsDone: boolean;
 };
 
 export type {TransactionWithOptionalSearchFields, TransactionItemRowProps, TransactionItemRowNarrowComputedData, TransactionItemRowWideComputedData};
diff --git a/src/components/WorkspaceMemberRoleList.tsx b/src/components/WorkspaceMemberRoleList.tsx
index 801a8698faba..1e361fa19b79 100644
--- a/src/components/WorkspaceMemberRoleList.tsx
+++ b/src/components/WorkspaceMemberRoleList.tsx
@@ -40,18 +40,25 @@ function WorkspaceMemberRoleList({role, policy, navigateBackTo = undefined, isLo
     const workspaceRoles: ListItemType[] = [
         {
             value: CONST.POLICY.ROLE.ADMIN,
-            text: translate('common.admin'),
+            text: translate('workspace.common.roleName', CONST.POLICY.ROLE.ADMIN),
             alternateText: translate('workspace.common.adminAlternateText'),
             isSelected: role === CONST.POLICY.ROLE.ADMIN,
             keyForList: CONST.POLICY.ROLE.ADMIN,
         },
         {
             value: CONST.POLICY.ROLE.AUDITOR,
-            text: translate('common.auditor'),
+            text: translate('workspace.common.roleName', CONST.POLICY.ROLE.AUDITOR),
             alternateText: translate('workspace.common.auditorAlternateText'),
             isSelected: role === CONST.POLICY.ROLE.AUDITOR,
             keyForList: CONST.POLICY.ROLE.AUDITOR,
         },
+        {
+            value: CONST.POLICY.ROLE.CARD_ADMIN,
+            text: translate('workspace.common.roleName', CONST.POLICY.ROLE.CARD_ADMIN),
+            alternateText: translate('workspace.common.cardAdminAlternateText'),
+            isSelected: role === CONST.POLICY.ROLE.CARD_ADMIN,
+            keyForList: CONST.POLICY.ROLE.CARD_ADMIN,
+        },
         {
             value: CONST.POLICY.ROLE.USER,
             text: translate('common.member'),
@@ -64,12 +71,15 @@ function WorkspaceMemberRoleList({role, policy, navigateBackTo = undefined, isLo
     const isPolicyControl = isControlPolicy(policy);
     // Only strict admins can assign the ADMIN role. Editors (e.g. Submit workspace owners) can
     // invite/manage members but must not be able to escalate anyone to admin.
-    const canAssignAdminRole = isPolicyAdmin(policy, currentUserEmail);
+    const canAssignElevatedRoles = isPolicyAdmin(policy, currentUserEmail);
     const availableRoleItems: ListItemType[] = workspaceRoles.filter((item) => {
-        if (item.value === CONST.POLICY.ROLE.AUDITOR && !isPolicyControl) {
+        if (item.value === CONST.POLICY.ROLE.AUDITOR && (!isPolicyControl || !canAssignElevatedRoles)) {
+            return false;
+        }
+        if (item.value === CONST.POLICY.ROLE.CARD_ADMIN && (!isPolicyControl || !canAssignElevatedRoles)) {
             return false;
         }
-        if (item.value === CONST.POLICY.ROLE.ADMIN && !canAssignAdminRole) {
+        if (item.value === CONST.POLICY.ROLE.ADMIN && !canAssignElevatedRoles) {
             return false;
         }
         return true;
diff --git a/src/components/utils/getActionBadgeText.ts b/src/components/utils/getActionBadgeText.ts
new file mode 100644
index 000000000000..79d5105c6dfc
--- /dev/null
+++ b/src/components/utils/getActionBadgeText.ts
@@ -0,0 +1,11 @@
+import type {OptionData} from '@libs/ReportUtils';
+import type {TranslationPaths} from '@src/languages/types';
+
+function getActionBadgeText(actionBadge: OptionData['actionBadge'], translate: (key: TranslationPaths) => string, isMarkAsDone?: boolean): string {
+    if (!actionBadge) {
+        return '';
+    }
+    return isMarkAsDone ? translate('common.markAsDone') : translate(`common.actionBadge.${actionBadge}`);
+}
+
+export default getActionBadgeText;
diff --git a/src/hooks/useAddAgentToApprovalWorkflow.ts b/src/hooks/useAddAgentToApprovalWorkflow.ts
deleted file mode 100644
index e34bc1cac936..000000000000
--- a/src/hooks/useAddAgentToApprovalWorkflow.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-import type {OnyxEntry} from 'react-native-onyx';
-import Navigation from '@libs/Navigation/Navigation';
-import {getMemberAccountIDsForWorkspace} from '@libs/PolicyUtils';
-import type {AvatarSource} from '@libs/UserAvatarUtils';
-import {addMembersToWorkspace} from '@userActions/Policy/Member';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES from '@src/ROUTES';
-import type {Policy} from '@src/types/onyx';
-import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
-import useAllPolicyExpenseChatReportActions from './useAllPolicyExpenseChatReportActions';
-import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
-import useLocalize from './useLocalize';
-import useOnyx from './useOnyx';
-
-type OwnedAgent = {accountID: number; email: string; displayName: string; avatar?: AvatarSource};
-
-/**
- * Returns a handler that seeds an approval workflow with the current user's first available
- * owned agent and navigates to the approver edit screen. When every owned agent is already
- * an approver on the workflow, the handler routes the admin to the create-agent screen so
- * we don't duplicate an existing agent.
- */
-function useAddAgentToApprovalWorkflow(policy: OnyxEntry<Policy>, policyID: string) {
-    const {formatPhoneNumber} = useLocalize();
-    const currentUserPersonalDetails = useCurrentUserPersonalDetails();
-    const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
-    const [agentPrompts] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT);
-    const filteredReportActions = useAllPolicyExpenseChatReportActions();
-
-    const ownedAgents: OwnedAgent[] = (() => {
-        if (!agentPrompts || !personalDetails) {
-            return [];
-        }
-        return Object.keys(agentPrompts)
-            .map<OwnedAgent | null>((key) => {
-                const accountID = Number(key.slice(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT.length));
-                const details = personalDetails[accountID];
-                if (!details?.login) {
-                    return null;
-                }
-                return {
-                    accountID,
-                    email: details.login,
-                    displayName: details.displayName ?? details.login,
-                    avatar: details.avatar,
-                };
-            })
-            .filter((agent): agent is OwnedAgent => !!agent);
-    })();
-
-    return (workflow: ApprovalWorkflow) => {
-        const workflowApproverEmail = workflow.approvers.at(0)?.email ?? '';
-
-        // Prefer the first owned agent that isn't already an approver on this workflow.
-        // If every owned agent is already in the workflow there's nothing to seed, so we
-        // route the admin to create a new agent instead of duplicating an existing one.
-        const agentToSeed = ownedAgents.find((candidate) => !workflow.approvers.some((approver) => approver.email === candidate.email));
-        if (!agentToSeed) {
-            Navigation.navigate(
-                ROUTES.WORKSPACE_WORKFLOWS_ADD_AGENT.getRoute({
-                    policyID,
-                    workflowApproverEmail,
-                }),
-            );
-            return;
-        }
-
-        // Ensure the agent is a workspace member before they show up as an approver. The
-        // server makes this idempotent so it's safe to call even if the agent was added via
-        // the API's `policyID` parameter when CREATE_AGENT was first called.
-        const isAlreadyMember = !!policy?.employeeList?.[agentToSeed.email];
-        if (!isAlreadyMember && policy) {
-            const policyMemberAccountIDs = Object.values(getMemberAccountIDsForWorkspace(policy.employeeList, false, false));
-            addMembersToWorkspace(
-                {[agentToSeed.email]: agentToSeed.accountID},
-                '',
-                policy,
-                policyMemberAccountIDs,
-                CONST.POLICY.ROLE.USER,
-                formatPhoneNumber,
-                {
-                    accountID: currentUserPersonalDetails.accountID,
-                    displayName: currentUserPersonalDetails.displayName,
-                    email: currentUserPersonalDetails.login,
-                    avatar: currentUserPersonalDetails.avatar,
-                },
-                filteredReportActions,
-            );
-        }
-
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, workflowApproverEmail, agentToSeed.email));
-    };
-}
-
-export default useAddAgentToApprovalWorkflow;
diff --git a/src/hooks/useCanWriteCardSpendRules.ts b/src/hooks/useCanWriteCardSpendRules.ts
new file mode 100644
index 000000000000..242d171b6ecf
--- /dev/null
+++ b/src/hooks/useCanWriteCardSpendRules.ts
@@ -0,0 +1,13 @@
+import {canMemberWrite} from '@libs/PolicyUtils';
+import CONST from '@src/CONST';
+import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
+import usePolicy from './usePolicy';
+
+function useCanWriteCardSpendRules(policyID: string | undefined): boolean {
+    const policy = usePolicy(policyID);
+    const {login = ''} = useCurrentUserPersonalDetails();
+
+    return canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.RULES) || canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD);
+}
+
+export default useCanWriteCardSpendRules;
diff --git a/src/hooks/useCreateReport.tsx b/src/hooks/useCreateReport.tsx
index 91e545b6aa5a..0b0225de3bec 100644
--- a/src/hooks/useCreateReport.tsx
+++ b/src/hooks/useCreateReport.tsx
@@ -3,7 +3,7 @@ import type {OnyxEntry} from 'react-native-onyx';
 import interceptAnonymousUser from '@libs/interceptAnonymousUser';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
-import {getDefaultChatEnabledPolicy, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {getDefaultChatEnabledPolicy, isGroupPolicy} from '@libs/PolicyUtils';
 import {generateReportID} from '@libs/ReportUtils';
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
 import CONST from '@src/CONST';
@@ -87,15 +87,13 @@ export default function useCreateReport({
                 const freshReportID = generateReportID();
                 const freshTransactionID = generateReportID();
                 Navigation.navigate(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                            action: CONST.IOU.ACTION.CREATE,
-                            iouType: CONST.IOU.TYPE.CREATE,
-                            transactionID: freshTransactionID,
-                            reportID: freshReportID,
-                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                        }),
-                    ),
+                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                        action: CONST.IOU.ACTION.CREATE,
+                        iouType: CONST.IOU.TYPE.CREATE,
+                        transactionID: freshTransactionID,
+                        reportID: freshReportID,
+                        upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                    }),
                 );
                 return;
             }
@@ -106,7 +104,7 @@ export default function useCreateReport({
             // at least 2 non-personal workspaces to choose between. Also fall back to the selector if
             // the default is billing-restricted and alternatives exist, so the user isn't dead-ended
             // on the restricted-action page.
-            const isDefaultPersonal = !activePolicy || activePolicy.type === CONST.POLICY.TYPE.PERSONAL || !isPaidGroupPolicy(activePolicy);
+            const isDefaultPersonal = !activePolicy || activePolicy.type === CONST.POLICY.TYPE.PERSONAL || !isGroupPolicy(activePolicy);
             const hasMultipleNonPersonalWorkspaces = groupPoliciesWithChatEnabled.length > 1;
             const isDefaultBillingRestricted =
                 !!workspaceIDForReportCreation && shouldRestrictUserBillableActions(defaultChatEnabledPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, accountID);
diff --git a/src/hooks/useDefaultExpensePolicy.tsx b/src/hooks/useDefaultExpensePolicy.tsx
index 32630fafff88..850004e037d9 100644
--- a/src/hooks/useDefaultExpensePolicy.tsx
+++ b/src/hooks/useDefaultExpensePolicy.tsx
@@ -1,5 +1,5 @@
 import type {OnyxCollection} from 'react-native-onyx';
-import {isPaidGroupPolicy, isPolicyAccessible} from '@libs/PolicyUtils';
+import {isGroupPolicy, isPolicyAccessible} from '@libs/PolicyUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Policy} from '@src/types/onyx';
 import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
@@ -17,7 +17,7 @@ function getSingleGroupPolicyID(policies: OnyxCollection<Policy>, login: string)
 
     let singlePolicyID: string | undefined;
     for (const policy of Object.values(policies)) {
-        if (!policy || !isPaidGroupPolicy(policy) || !isPolicyAccessible(policy, login)) {
+        if (!policy || !isGroupPolicy(policy) || !isPolicyAccessible(policy, login)) {
             continue;
         }
         if (!singlePolicyID) {
@@ -45,11 +45,11 @@ export default function useDefaultExpensePolicy() {
     // Per-key lookup for the single group policy (only fires when that specific policy changes)
     const [singleGroupPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${singleGroupPolicyID}`);
 
-    if (isRestrictedToPreferredPolicy && isPaidGroupPolicy(preferredPolicy) && isPolicyAccessible(preferredPolicy, login)) {
+    if (isRestrictedToPreferredPolicy && isGroupPolicy(preferredPolicy) && isPolicyAccessible(preferredPolicy, login)) {
         return preferredPolicy;
     }
 
-    if (isPaidGroupPolicy(activePolicy) && isPolicyAccessible(activePolicy, login)) {
+    if (isGroupPolicy(activePolicy) && isPolicyAccessible(activePolicy, login)) {
         return activePolicy;
     }
 
diff --git a/src/hooks/useDeferredAgentWorkflowReconciliation.ts b/src/hooks/useDeferredAgentWorkflowReconciliation.ts
deleted file mode 100644
index dc1fc17da549..000000000000
--- a/src/hooks/useDeferredAgentWorkflowReconciliation.ts
+++ /dev/null
@@ -1,176 +0,0 @@
-import {useEffect, useRef} from 'react';
-import type {OnyxEntry} from 'react-native-onyx';
-import {buildDeferredAgentWorkflowSaveKey, clearDeferredAgentWorkflowSave, updateApprovalWorkflow} from '@libs/actions/Workflow';
-import {resolveOptimisticAgent} from '@libs/WorkflowUtils';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {Policy} from '@src/types/onyx';
-import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
-import {isEmptyObject} from '@src/types/utils/EmptyObject';
-import useOnyx from './useOnyx';
-
-type ApprovalWorkflowWithRouting = ApprovalWorkflow & {routingFirstApproverEmail: string};
-
-/**
- * Overlays deferred-save approval workflows on top of the server's view and reconciles them
- * once the pending agent's real identity lands.
- *
- * - Overlay: when the admin saves an Edit Approvers page while CREATE_AGENT is still in
- *   flight, we stash the workflow in `DEFERRED_AGENT_WORKFLOW_SAVES`. This hook merges that
- *   stashed approver chain into the workflows list so the new agent shows up faded in the
- *   workflow card. Each workflow also gets a `routingFirstApproverEmail` so the edit route /
- *   list key keep using the original (pre-overlay) email even when the overlaid `approvers[0]`
- *   is a pending agent with an empty `email` placeholder. A failed `CREATE_AGENT` surfaces
- *   `policy.errorFields[ADD_AGENT]` on the pending approver row so the admin sees an RBR
- *   right where the optimistic agent is shown.
- * - Reconcile: once the pending agent has a real email (the personal detail at
- *   `pendingAgentAccountID` gains a login OR `OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING` echoes a
- *   real accountID OR a prompt-match resolves to a known member), we swap that email into
- *   the workflow, fire the real `updateApprovalWorkflow`, and clear the entry.
- */
-function useDeferredAgentWorkflowReconciliation(rawApprovalWorkflows: ApprovalWorkflow[], policy: OnyxEntry<Policy>, policyID: string): ApprovalWorkflowWithRouting[] {
-    const [deferredAgentWorkflowSaves] = useOnyx(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES);
-    const [agentPrompts] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT);
-    const [optimisticAgentAccountIDMapping] = useOnyx(ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING);
-    const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
-
-    const addAgentErrors = policy?.errorFields?.[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT];
-
-    const approvalWorkflows: ApprovalWorkflowWithRouting[] = (() => {
-        if (!deferredAgentWorkflowSaves || isEmptyObject(deferredAgentWorkflowSaves)) {
-            return rawApprovalWorkflows.map((workflow) => ({...workflow, routingFirstApproverEmail: workflow.approvers.at(0)?.email ?? ''}));
-        }
-        return rawApprovalWorkflows.map((workflow) => {
-            const firstApproverEmail = workflow.approvers.at(0)?.email ?? '';
-            if (!firstApproverEmail) {
-                return {...workflow, routingFirstApproverEmail: firstApproverEmail};
-            }
-            const deferredEntry = deferredAgentWorkflowSaves[buildDeferredAgentWorkflowSaveKey(policyID, firstApproverEmail)];
-            if (!deferredEntry) {
-                return {...workflow, routingFirstApproverEmail: firstApproverEmail};
-            }
-            const overlaidApprovers = deferredEntry.approvalWorkflow.approvers
-                .filter((approver): approver is NonNullable<typeof approver> => !!approver)
-                .map((approver) =>
-                    addAgentErrors && approver.accountID === deferredEntry.pendingAgentAccountID && approver.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD
-                        ? {...approver, errors: addAgentErrors}
-                        : approver,
-                );
-            return {
-                ...workflow,
-                approvers: overlaidApprovers,
-                routingFirstApproverEmail: firstApproverEmail,
-            };
-        });
-    })();
-
-    // Tracks deferred-save keys we've already reconciled in this mount. `updateApprovalWorkflow`'s
-    // optimistic write to `policy.employeeList` re-renders the page before the matching
-    // `clearDeferredAgentWorkflowSave` Onyx merge settles; without this guard the effect would
-    // fire `updateApprovalWorkflow` (and the underlying `UPDATE_WORKSPACE_APPROVAL` API call)
-    // a second time for the same entry on that intermediate render.
-    const reconciledDeferredKeysRef = useRef<Set<string>>(new Set());
-
-    useEffect(() => {
-        // Drop any tracked keys whose Onyx entries are gone (clear has settled or the entry was
-        // removed elsewhere) so the same key can be reconciled again if it ever reappears.
-        if (reconciledDeferredKeysRef.current.size > 0) {
-            for (const key of [...reconciledDeferredKeysRef.current]) {
-                if (!deferredAgentWorkflowSaves?.[key]) {
-                    reconciledDeferredKeysRef.current.delete(key);
-                }
-            }
-        }
-        if (!deferredAgentWorkflowSaves || isEmptyObject(deferredAgentWorkflowSaves) || !policy || !personalDetails) {
-            return;
-        }
-        for (const deferredEntry of Object.values(deferredAgentWorkflowSaves)) {
-            if (!deferredEntry || deferredEntry.policyID !== policyID) {
-                continue;
-            }
-            const deferredKey = buildDeferredAgentWorkflowSaveKey(deferredEntry.policyID, deferredEntry.firstApproverEmail);
-            if (reconciledDeferredKeysRef.current.has(deferredKey)) {
-                continue;
-            }
-            const pendingApprover = deferredEntry.approvalWorkflow.approvers.find(
-                (approver) => approver?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD && approver.accountID === deferredEntry.pendingAgentAccountID,
-            );
-            if (!pendingApprover) {
-                // Nothing left to wait on — the save can fire as-is (or was already fired).
-                reconciledDeferredKeysRef.current.add(deferredKey);
-                clearDeferredAgentWorkflowSave(deferredEntry.policyID, deferredEntry.firstApproverEmail);
-                continue;
-            }
-            const knownEmails = new Set(
-                deferredEntry.approvalWorkflow.approvers
-                    .filter((approver): approver is NonNullable<typeof approver> => !!approver?.email && approver.accountID !== deferredEntry.pendingAgentAccountID)
-                    .map((approver) => approver.email),
-            );
-            const resolved = resolveOptimisticAgent({
-                optimisticAccountID: deferredEntry.pendingAgentAccountID,
-                pendingAgentPrompt: deferredEntry.pendingAgentPrompt,
-                personalDetails,
-                employeeList: policy.employeeList,
-                agentPrompts,
-                optimisticAccountIDMapping: optimisticAgentAccountIDMapping,
-                knownApproverEmails: knownEmails,
-            });
-            if (!resolved) {
-                continue;
-            }
-            const {accountID: resolvedAccountID, email: resolvedEmail} = resolved;
-            // Upgrade the deferred workflow with the real email, then fire the save action.
-            // `updateApprovalWorkflow` expects `ApprovalWorkflow` (approvers required, no
-            // editor-only fields), so filter out the holes in the Onyx representation and
-            // hand off only the fields it cares about.
-            const upgradedApprovers = deferredEntry.approvalWorkflow.approvers
-                .filter((approver): approver is NonNullable<typeof approver> => !!approver)
-                .map((approver) =>
-                    approver === pendingApprover
-                        ? {
-                              ...approver,
-                              email: resolvedEmail,
-                              accountID: resolvedAccountID,
-                              pendingAction: undefined,
-                          }
-                        : approver,
-                );
-            // When the saved workflow is the default one, the new agent becomes the new default
-            // approver. The deferred snapshot's `members` list was captured before CREATE_AGENT
-            // resolved, so the agent isn't in it — and `convertApprovalWorkflowToPolicyEmployees`
-            // only rewrites `submitsTo` for emails present in `members`. Without the agent in
-            // that list their `submitsTo` (set to the previous default approver by
-            // `shareWithEmployees` in CreateAgent.cpp) is never overwritten, leaving them as
-            // their own orphan submission group in the workflows list. Injecting them here
-            // mirrors the online editor's behaviour (where the agent is already in employeeList
-            // when the editor renders and falls naturally into the "Everyone" members list) so
-            // the agent ends up submitting to themselves like every other default approver.
-            const upgradedMembers =
-                deferredEntry.approvalWorkflow.isDefault && !deferredEntry.approvalWorkflow.members.some((member) => member.email === resolvedEmail)
-                    ? [
-                          ...deferredEntry.approvalWorkflow.members,
-                          {
-                              email: resolvedEmail,
-                              displayName: pendingApprover.displayName,
-                              avatar: pendingApprover.avatar,
-                          },
-                      ]
-                    : deferredEntry.approvalWorkflow.members;
-            const upgradedWorkflow = {
-                members: upgradedMembers,
-                approvers: upgradedApprovers,
-                isDefault: deferredEntry.approvalWorkflow.isDefault,
-            };
-            const initialApprovers = deferredEntry.initialApprovalWorkflow.approvers.filter((approver): approver is NonNullable<typeof approver> => !!approver);
-            const membersToRemove = deferredEntry.initialApprovalWorkflow.members.filter((initialMember) => !upgradedWorkflow.members.some((member) => member.email === initialMember.email));
-            const approversToRemove = initialApprovers.filter((initialApprover) => !upgradedWorkflow.approvers.some((approver) => approver.email === initialApprover.email));
-            reconciledDeferredKeysRef.current.add(deferredKey);
-            updateApprovalWorkflow(upgradedWorkflow, membersToRemove, approversToRemove, policy);
-            clearDeferredAgentWorkflowSave(deferredEntry.policyID, deferredEntry.firstApproverEmail);
-        }
-    }, [deferredAgentWorkflowSaves, policy, personalDetails, policyID, agentPrompts, optimisticAgentAccountIDMapping]);
-
-    return approvalWorkflows;
-}
-
-export default useDeferredAgentWorkflowReconciliation;
diff --git a/src/hooks/useExpandCollapseAnimation.ts b/src/hooks/useExpandCollapseAnimation.ts
new file mode 100644
index 000000000000..7fca790c5444
--- /dev/null
+++ b/src/hooks/useExpandCollapseAnimation.ts
@@ -0,0 +1,49 @@
+import {useState} from 'react';
+import type {LayoutChangeEvent} from 'react-native';
+import {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
+import {scheduleOnRN} from 'react-native-worklets';
+import {easing} from '@components/Modal/ReanimatedModal/utils';
+
+const EXPAND_COLLAPSE_DURATION = 300;
+
+function useExpandCollapseAnimation(isExpanded: boolean) {
+    const contentHeight = useSharedValue(0);
+    const hasExpanded = useSharedValue(isExpanded);
+    const [isRendered, setIsRendered] = useState(isExpanded);
+
+    hasExpanded.set(isExpanded);
+    // Matches the pattern in AnimatedCollapsible — mount content synchronously on expand,
+    // unmount asynchronously after collapse animation via scheduleOnRN callback.
+    if (isExpanded && !isRendered) {
+        setIsRendered(true);
+    }
+
+    const animatedHeight = useDerivedValue(() => {
+        if (!contentHeight.get()) {
+            return 0;
+        }
+        const target = hasExpanded.get() ? contentHeight.get() : 0;
+        return withTiming(target, {duration: EXPAND_COLLAPSE_DURATION, easing}, (finished) => {
+            if (!finished || target) {
+                return;
+            }
+            scheduleOnRN(setIsRendered, false);
+        });
+    }, []);
+
+    const animatedStyle = useAnimatedStyle(() => ({
+        height: animatedHeight.get(),
+        overflow: 'hidden',
+    }));
+
+    const onLayout = (e: LayoutChangeEvent) => {
+        const height = e.nativeEvent.layout.height;
+        if (height) {
+            contentHeight.set(height);
+        }
+    };
+
+    return {isRendered, animatedStyle, onLayout};
+}
+
+export default useExpandCollapseAnimation;
diff --git a/src/hooks/useExpenseActions.ts b/src/hooks/useExpenseActions.ts
index d91876bcb581..b7fcb7b92195 100644
--- a/src/hooks/useExpenseActions.ts
+++ b/src/hooks/useExpenseActions.ts
@@ -510,24 +510,33 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                         );
                         const deleteNavigateBackUrl = goBackRoute ?? backTo ?? Navigation.getActiveRoute();
                         setDeleteTransactionNavigateBackUrl(deleteNavigateBackUrl);
+                        // The wide RHP close animation was changed, and because of that the expense was deleted right after
+                        // the animation finished, which caused flickering in the expenses list. We want the user to see
+                        // the expense in the list for a little bit longer, so we wait for the animation to finish and then
+                        // add an additional delay before removing it.
+                        // See https://github.com/Expensify/App/issues/92036
+                        const afterTransition = () => {
+                            setTimeout(() => {
+                                const deleteResult = deleteTransactions(
+                                    [transaction.transactionID],
+                                    duplicateTransactions,
+                                    duplicateTransactionViolations,
+                                    isReportInSearch ? currentSearchHash : undefined,
+                                    false,
+                                );
+
+                                if (deleteResult.action === 'redirected') {
+                                    return;
+                                }
+
+                                removeTransaction(transaction.transactionID);
+                            }, CONST.EXPENSE_REPORT_DELETE_DELAY_MS);
+                        };
                         if (goBackRoute) {
-                            navigateOnDeleteExpense(goBackRoute);
+                            navigateOnDeleteExpense(goBackRoute, afterTransition);
+                        } else {
+                            afterTransition();
                         }
-                        InteractionManager.runAfterInteractions(() => {
-                            const deleteResult = deleteTransactions(
-                                [transaction.transactionID],
-                                duplicateTransactions,
-                                duplicateTransactionViolations,
-                                isReportInSearch ? currentSearchHash : undefined,
-                                false,
-                            );
-
-                            if (deleteResult.action === 'redirected') {
-                                return;
-                            }
-
-                            removeTransaction(transaction.transactionID);
-                        });
                     }
                     return;
                 }
@@ -546,19 +555,27 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                 const deleteNavigateBackUrl = backToRoute ?? Navigation.getActiveRoute();
                 setDeleteTransactionNavigateBackUrl(deleteNavigateBackUrl);
 
+                // The wide RHP close animation was changed, and because of that the report was deleted right after
+                // the animation finished, which caused flickering in the reports list. We want the user to see
+                // the report in the list for a little bit longer, so we wait for the animation to finish and then
+                // add an additional delay before removing it.
+                // See https://github.com/Expensify/App/issues/92036
                 Navigation.setNavigationActionToMicrotaskQueue(() => {
-                    Navigation.goBack(backToRoute);
-                    InteractionManager.runAfterInteractions(() => {
-                        deleteAppReport({
-                            report: moneyRequestReport,
-                            selfDMReport,
-                            currentUserEmailParam: email ?? '',
-                            currentUserAccountIDParam: accountID,
-                            reportTransactions,
-                            allTransactionViolations,
-                            bankAccountList,
-                            hash: currentSearchHash,
-                        });
+                    Navigation.goBack(backToRoute, {
+                        afterTransition: () => {
+                            setTimeout(() => {
+                                deleteAppReport({
+                                    report: moneyRequestReport,
+                                    selfDMReport,
+                                    currentUserEmailParam: email ?? '',
+                                    currentUserAccountIDParam: accountID,
+                                    reportTransactions,
+                                    allTransactionViolations,
+                                    bankAccountList,
+                                    hash: currentSearchHash,
+                                });
+                            }, CONST.EXPENSE_REPORT_DELETE_DELAY_MS);
+                        },
                     });
                 });
             },
diff --git a/src/hooks/useHRSyncResultsModal.ts b/src/hooks/useHRSyncResultsModal.ts
index 8a45dff48a74..e7ef15042448 100644
--- a/src/hooks/useHRSyncResultsModal.ts
+++ b/src/hooks/useHRSyncResultsModal.ts
@@ -1,10 +1,13 @@
-import {useEffect} from 'react';
+import {isModalActiveSelector} from '@selectors/Modal';
+import {useEffect, useEffectEvent, useRef} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
-import type {TupleToUnion} from 'type-fest';
 import HRSyncResultsModal from '@components/HRSyncResultsModal';
 import {useModal} from '@components/Modal/Global/ModalContext';
+import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type {PolicyConnectionSyncProgress} from '@src/types/onyx/Policy';
+import useOnyx from './useOnyx';
 import usePrevious from './usePrevious';
 
 /**
@@ -14,37 +17,55 @@ import usePrevious from './usePrevious';
 function useHRSyncResultsModal(policyID: string, connectionSyncProgress: OnyxEntry<PolicyConnectionSyncProgress>, isFocused: boolean) {
     const modal = useModal();
     const previousSyncProgress = usePrevious(connectionSyncProgress);
+    const pendingSyncResultRef = useRef<Pick<PolicyConnectionSyncProgress, 'connectionName' | 'result'> | null>(null);
+    const [isAnyModalActive] = useOnyx(ONYXKEYS.MODAL, {selector: isModalActiveSelector});
 
     const connectionName = connectionSyncProgress?.connectionName;
+    const showSyncResultsModal = useEffectEvent((syncResult: PolicyConnectionSyncProgress['result'], syncConnectionName: PolicyConnectionSyncProgress['connectionName']) => {
+        if (!syncResult || !syncConnectionName) {
+            return;
+        }
+
+        modal.showModal({
+            component: HRSyncResultsModal,
+            props: {result: syncResult, policyID},
+            id: `${syncConnectionName}-sync-results-${policyID}`,
+        });
+    });
 
     useEffect(() => {
         const syncResult = connectionSyncProgress?.result;
-        const isHRSyncDoneWithResult =
-            CONST.POLICY.CONNECTIONS.HR_CONNECTION_NAMES.includes(connectionName as TupleToUnion<typeof CONST.POLICY.CONNECTIONS.HR_CONNECTION_NAMES>) &&
-            connectionSyncProgress?.stageInProgress === CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.JOB_DONE &&
-            !!syncResult;
+        const isHRConnectionName = CONST.POLICY.CONNECTIONS.HR_CONNECTION_NAMES.some((hrConnectionName) => hrConnectionName === connectionName);
+        const isHRSyncDoneWithResult = isHRConnectionName && connectionSyncProgress?.stageInProgress === CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.JOB_DONE && !!syncResult;
         const didTransitionToJobDone = previousSyncProgress?.connectionName === connectionName && previousSyncProgress?.stageInProgress !== CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.JOB_DONE;
         const didHRSyncComplete = isFocused && isHRSyncDoneWithResult && didTransitionToJobDone;
 
-        if (!didHRSyncComplete || !syncResult || !connectionName) {
+        if (didHRSyncComplete && syncResult && connectionName) {
+            pendingSyncResultRef.current = {connectionName, result: syncResult};
+        }
+
+        const pendingSyncResult = pendingSyncResultRef.current;
+        if (!pendingSyncResult || isAnyModalActive) {
             return;
         }
 
-        modal.showModal({
-            component: HRSyncResultsModal,
-            props: {result: syncResult, policyID},
-            id: `${connectionName}-sync-results-${policyID}`,
+        const handle = TransitionTracker.runAfterTransitions({
+            callback: () => {
+                showSyncResultsModal(pendingSyncResult.result, pendingSyncResult.connectionName);
+                pendingSyncResultRef.current = null;
+            },
+            waitForUpcomingTransition: true,
         });
+        return () => handle.cancel();
     }, [
         connectionName,
         connectionSyncProgress?.result,
         connectionSyncProgress?.stageInProgress,
         connectionSyncProgress?.timestamp,
+        isAnyModalActive,
         isFocused,
-        policyID,
         previousSyncProgress?.connectionName,
         previousSyncProgress?.stageInProgress,
-        modal,
     ]);
 }
 
diff --git a/src/hooks/useInboxTabSpanLifecycle.ts b/src/hooks/useInboxTabSpanLifecycle.ts
new file mode 100644
index 000000000000..9c638f16bbe2
--- /dev/null
+++ b/src/hooks/useInboxTabSpanLifecycle.ts
@@ -0,0 +1,60 @@
+import {useFocusEffect} from '@react-navigation/native';
+import {useCallback, useEffect, useRef} from 'react';
+import {cancelSpan, endSpan, getSpan} from '@libs/telemetry/activeSpans';
+import CONST from '@src/CONST';
+
+/**
+ * Manages the ManualNavigateToInboxTab span lifecycle for the inbox sidebar.
+ *
+ * Three signals are handled:
+ * - onLayout fires on first mount: ends the span (normal path).
+ * - useFocusEffect fires on re-focus when react-freeze has cached the layout: ends the span (warm path).
+ *   The blur cleanup cancels any orphaned span when the user navigates away before layout completes.
+ * - useEffect unmount cleanup cancels the span only if layout never completed AND the active span
+ *   is the same one that was present when this instance mounted (avoids canceling a span started
+ *   by a subsequent tab click).
+ *
+ * Returns `onLayout` to be attached to the sidebar container View.
+ */
+function useInboxTabSpanLifecycle(): () => void {
+    const hasHadFirstLayout = useRef(false);
+    const spanOnMount = useRef(getSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB));
+
+    const onLayout = useCallback(() => {
+        hasHadFirstLayout.current = true;
+        endSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+        spanOnMount.current = undefined;
+    }, []);
+
+    // Focus: ends span on re-visits (react-freeze cached layout, onLayout won't fire again).
+    // Blur cleanup: cancels orphaned span when user navigates away before onLayout fires.
+    useFocusEffect(
+        useCallback(() => {
+            if (hasHadFirstLayout.current) {
+                endSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+            }
+            return () => cancelSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+        }, []),
+    );
+
+    // Unmount: cancel only if layout never completed AND the active span is
+    // the same one that existed when this instance mounted (avoids canceling
+    // a newer span started by a subsequent tab click).
+    useEffect(
+        () => () => {
+            if (hasHadFirstLayout.current) {
+                return;
+            }
+            const activeSpan = getSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+            if (activeSpan !== spanOnMount.current) {
+                return;
+            }
+            cancelSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+        },
+        [],
+    );
+
+    return onLayout;
+}
+
+export default useInboxTabSpanLifecycle;
diff --git a/src/hooks/useIsAllowedToIssueCompanyCard.ts b/src/hooks/useIsAllowedToIssueCompanyCard.ts
index 87db7fae7b69..e9f35646cd93 100644
--- a/src/hooks/useIsAllowedToIssueCompanyCard.ts
+++ b/src/hooks/useIsAllowedToIssueCompanyCard.ts
@@ -1,5 +1,6 @@
 import {getCompanyFeeds, getSelectedFeed} from '@libs/CardUtils';
-import {isPolicyAdmin as isPolicyAdminPolicyUtils} from '@libs/PolicyUtils';
+import {canMemberWrite} from '@libs/PolicyUtils';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import {isAdminSelector} from '@src/selectors/Domain';
 import useCardFeeds from './useCardFeeds';
@@ -8,10 +9,10 @@ import useOnyx from './useOnyx';
 import usePolicy from './usePolicy';
 
 function useIsAllowedToIssueCompanyCard({policyID}: {policyID?: string}) {
-    const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
+    const {accountID: currentUserAccountID, login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
     const [lastSelectedFeed] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`);
     const policy = usePolicy(policyID);
-    const isPolicyAdmin = isPolicyAdminPolicyUtils(policy);
+    const canWriteCompanyCards = canMemberWrite(policy, currentUserLogin, CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS);
 
     const [cardFeeds] = useCardFeeds(policyID);
     const companyCards = getCompanyFeeds(cardFeeds);
@@ -21,7 +22,7 @@ function useIsAllowedToIssueCompanyCard({policyID}: {policyID?: string}) {
     const [domain] = useOnyx(`${ONYXKEYS.COLLECTION.DOMAIN}${selectedFeedData?.domainID}`);
 
     if (selectedFeedData?.domainID === policy?.policyAccountID || (policyID && selectedFeedData?.linkedPolicyIDs?.some((id) => id.toUpperCase() === policyID.toUpperCase()))) {
-        return isPolicyAdmin;
+        return canWriteCompanyCards;
     }
 
     return isAdminSelector(currentUserAccountID)(domain);
diff --git a/src/hooks/useLifecycleActions.tsx b/src/hooks/useLifecycleActions.tsx
index a25c43c159ee..af868c5c5ff9 100644
--- a/src/hooks/useLifecycleActions.tsx
+++ b/src/hooks/useLifecycleActions.tsx
@@ -1,4 +1,5 @@
 import {delegateEmailSelector} from '@selectors/Account';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import type {ActionHandledType} from '@components/Modal/Global/HoldMenuModalWrapper';
@@ -18,6 +19,7 @@ import {
     isExported as isExportedUtils,
     isReportOwner,
     shouldBlockSubmitDueToStrictPolicyRules,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import {cancelPayment, markReportPaymentReceived} from '@userActions/IOU/PayMoneyRequest';
@@ -71,6 +73,7 @@ function useLifecycleActions({reportID, startApprovedAnimation, startAnimation,
     const [amountOwed] = useOnyx(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED);
     const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END);
     const [delegateEmail] = useOnyx(ONYXKEYS.ACCOUNT, {selector: delegateEmailSelector});
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     const {reportActions: unfilteredReportActions} = usePaginatedReportActions(moneyRequestReport?.reportID);
     const reportActions = getFilteredReportActionsForReportView(unfilteredReportActions);
@@ -228,7 +231,7 @@ function useLifecycleActions({reportID, startApprovedAnimation, startAnimation,
     const actions: Record<string, SecondaryActionEntry> = {
         [CONST.REPORT.SECONDARY_ACTIONS.SUBMIT]: {
             value: CONST.REPORT.SECONDARY_ACTIONS.SUBMIT,
-            text: translate('common.submit'),
+            text: shouldShowMarkAsDone({policy, report: moneyRequestReport, isTrackIntentUser}) ? translate('common.markAsDone') : translate('common.submit'),
             icon: expensifyIcons.Send,
             sentryLabel: CONST.SENTRY_LABEL.MORE_MENU.SUBMIT,
             onSelected: () => {
diff --git a/src/hooks/useMergeHRInitialSyncingModal.ts b/src/hooks/useMergeHRInitialSyncingModal.ts
index db0bbaabcb6d..d710022f8889 100644
--- a/src/hooks/useMergeHRInitialSyncingModal.ts
+++ b/src/hooks/useMergeHRInitialSyncingModal.ts
@@ -1,6 +1,5 @@
 import {useEffect, useEffectEvent, useState} from 'react';
 import {setMergeHRInitialSyncModalShown} from '@libs/actions/connections/MergeHR';
-// eslint-disable-next-line no-restricted-imports -- the hook does not use React Navigation hooks internally (isFocused is passed in as a parameter), so there is no navigation instance available to use navigation.addListener for transition detection.
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import Visibility from '@libs/Visibility';
 import CONST from '@src/CONST';
diff --git a/src/hooks/useNavigateToTransactionThread.ts b/src/hooks/useNavigateToTransactionThread.ts
new file mode 100644
index 000000000000..914a27ffdc4d
--- /dev/null
+++ b/src/hooks/useNavigateToTransactionThread.ts
@@ -0,0 +1,87 @@
+import type {OnyxEntry} from 'react-native-onyx';
+import {useWideRHPActions} from '@components/WideRHPContextProvider';
+import {createTransactionThreadReport, setOptimisticTransactionThread} from '@libs/actions/Report';
+import {setActiveTransactionIDs} from '@libs/actions/TransactionThreadNavigation';
+import Navigation from '@libs/Navigation/Navigation';
+import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import type {Report, ReportAction, Transaction} from '@src/types/onyx';
+import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
+import useOnyx from './useOnyx';
+
+type NavigateToTransactionThreadParams = {
+    /** The transaction whose thread should be opened */
+    transactionID: string;
+
+    /** Report actions of the parent (IOU/expense) report, used to resolve the IOU action and its thread */
+    reportActions: ReportAction[];
+
+    /** The parent (IOU/expense) report that owns the transaction */
+    report: OnyxEntry<Report>;
+
+    /** The transaction being opened, used to build the thread optimistically when it doesn't exist yet */
+    transaction: OnyxEntry<Transaction>;
+
+    /** Ordered list of sibling transaction IDs used to drive the prev/next carousel in the thread RHP */
+    siblingTransactionIDs: string[];
+
+    /** Route to return to when navigating back; defaults to the current active route */
+    backTo?: string;
+};
+
+/**
+ * Shared navigation algorithm for opening a transaction thread (single-expense RHP view with the
+ * prev/next carousel). It resolves the IOU action's `childReportID`, creates the thread optimistically
+ * when it doesn't exist yet, seeds the sibling transaction IDs for the carousel, and navigates to the
+ * SEARCH_REPORT route.
+ *
+ * Callers are responsible for gathering their own `reportActions`, `report`, `transaction`, and
+ * `siblingTransactionIDs` because the data sources differ per screen.
+ */
+function useNavigateToTransactionThread() {
+    const {markReportIDAsExpense} = useWideRHPActions();
+    const currentUserDetails = useCurrentUserPersonalDetails();
+    const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
+    const [betas] = useOnyx(ONYXKEYS.BETAS);
+
+    return ({transactionID, reportActions, report, transaction, siblingTransactionIDs, backTo}: NavigateToTransactionThreadParams) => {
+        const iouAction = getIOUActionForTransactionID(reportActions, transactionID);
+        const resolvedBackTo = backTo ?? Navigation.getActiveRoute();
+        let reportIDToNavigate = iouAction?.childReportID;
+
+        const routeParams: {reportID: string | undefined; reportActionID?: string; backTo?: string} = {
+            reportID: reportIDToNavigate,
+            backTo: resolvedBackTo,
+        };
+
+        if (!reportIDToNavigate) {
+            const transactionThreadReport = createTransactionThreadReport({
+                introSelected,
+                currentUserLogin: currentUserDetails.email ?? '',
+                currentUserAccountID: currentUserDetails.accountID,
+                betas,
+                iouReport: report,
+                iouReportAction: iouAction,
+                transaction,
+            });
+            if (transactionThreadReport) {
+                reportIDToNavigate = transactionThreadReport.reportID;
+                routeParams.reportID = reportIDToNavigate;
+            }
+        } else {
+            setOptimisticTransactionThread(reportIDToNavigate, report?.reportID, iouAction?.reportActionID, report?.policyID);
+        }
+
+        // Single transaction report opens in RHP. We seed every sibling transaction ID so the RHP can
+        // display prev/next arrows for navigation between expenses.
+        setActiveTransactionIDs(siblingTransactionIDs).then(() => {
+            if (reportIDToNavigate) {
+                markReportIDAsExpense(reportIDToNavigate);
+            }
+            Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(routeParams));
+        });
+    };
+}
+
+export default useNavigateToTransactionThread;
diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts
index 4845a30cdd7d..82f17e6c3552 100644
--- a/src/hooks/useOnboardingFlow.ts
+++ b/src/hooks/useOnboardingFlow.ts
@@ -4,7 +4,6 @@ import {emailSelector} from '@selectors/Session';
 import {useEffect} from 'react';
 import getCurrentUrl from '@libs/Navigation/currentUrl';
 import Navigation from '@libs/Navigation/Navigation';
-// eslint-disable-next-line no-restricted-imports
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import {isLoggingInAsNewUser} from '@libs/SessionUtils';
 import {startOnboardingFlow} from '@userActions/Welcome/OnboardingFlow';
diff --git a/src/hooks/useParticipantSubmission.ts b/src/hooks/useParticipantSubmission.ts
index 751802e0cb01..4ffc3ebba138 100644
--- a/src/hooks/useParticipantSubmission.ts
+++ b/src/hooks/useParticipantSubmission.ts
@@ -4,9 +4,8 @@ import {setTransactionReport} from '@libs/actions/Transaction';
 import {READ_COMMANDS} from '@libs/API/types';
 import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import HttpUtils from '@libs/HttpUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
-import {isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {isGroupPolicy} from '@libs/PolicyUtils';
 import {findSelfDMReportID, generateReportID, isInvoiceRoomWithID} from '@libs/ReportUtils';
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
 import {isDistanceRequest} from '@libs/TransactionUtils';
@@ -23,7 +22,7 @@ import {createDraftWorkspace, generateDefaultWorkspaceName} from '@userActions/P
 import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import {lastWorkspaceNumberSelector} from '@src/selectors/Policy';
 import type {Policy, Transaction} from '@src/types/onyx';
 import type {Participant} from '@src/types/onyx/IOU';
@@ -97,7 +96,7 @@ function useParticipantSubmission({
 
     const isActivePolicyRequest =
         iouType === CONST.IOU.TYPE.CREATE &&
-        isPaidGroupPolicy(activePolicy) &&
+        isGroupPolicy(activePolicy) &&
         activePolicy?.isPolicyExpenseChatEnabled &&
         !shouldRestrictUserBillableActions(activePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID);
 
@@ -354,10 +353,7 @@ function useParticipantSubmission({
             }
             Navigation.setNavigationActionToMicrotaskQueue(() => {
                 if (isCategorizing) {
-                    const confirmationRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.SUBMIT, initialTransactionID, expenseChatReportID, undefined, true);
-                    Navigation.navigate(
-                        createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, CONST.IOU.TYPE.SUBMIT, initialTransactionID, expenseChatReportID), confirmationRoute),
-                    );
+                    Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, CONST.IOU.TYPE.SUBMIT, initialTransactionID, expenseChatReportID));
                 } else {
                     Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.SUBMIT, initialTransactionID, expenseChatReportID, undefined, true));
                 }
@@ -376,7 +372,7 @@ function useParticipantSubmission({
         );
 
         const route = isCategorizing
-            ? createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, initialTransactionID, selectedReportID.current || reportID), iouConfirmationPageRoute)
+            ? ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, initialTransactionID, selectedReportID.current || reportID, iouConfirmationPageRoute)
             : iouConfirmationPageRoute;
 
         KeyboardUtils.dismissKeyboardAndExecute(() => {
diff --git a/src/hooks/usePolicyForMovingExpenses.ts b/src/hooks/usePolicyForMovingExpenses.ts
index b3f88e88a2ac..74f3e8384158 100644
--- a/src/hooks/usePolicyForMovingExpenses.ts
+++ b/src/hooks/usePolicyForMovingExpenses.ts
@@ -1,7 +1,7 @@
 import {activePolicySelector} from '@selectors/Policy';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import {useSession} from '@components/OnyxListItemProvider';
-import {canSubmitPerDiemExpenseFromWorkspace, isPaidGroupPolicy, isPolicyMemberWithoutPendingDelete, isTimeTrackingEnabled} from '@libs/PolicyUtils';
+import {canSubmitPerDiemExpenseFromWorkspace, isGroupPolicy, isPolicyMemberWithoutPendingDelete, isTimeTrackingEnabled} from '@libs/PolicyUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Policy} from '@src/types/onyx';
@@ -24,7 +24,7 @@ function isPolicyValidForMovingExpenses(policy: OnyxEntry<Policy>, login: string
     return (
         checkForUserPendingDelete(login, policy) &&
         isPolicyMemberByRole(policy) &&
-        isPaidGroupPolicy(policy) &&
+        isGroupPolicy(policy) &&
         policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE &&
         (!isPerDiemRequest || canSubmitPerDiemExpenseFromWorkspace(policy)) &&
         (!isTimeRequest || isTimeTrackingEnabled(policy))
diff --git a/src/hooks/useReceiptScanDrop.tsx b/src/hooks/useReceiptScanDrop.tsx
index 0ea8a8ac55d4..6e519cc74611 100644
--- a/src/hooks/useReceiptScanDrop.tsx
+++ b/src/hooks/useReceiptScanDrop.tsx
@@ -3,7 +3,7 @@ import React, {useMemo} from 'react';
 import {setTransactionReport} from '@libs/actions/Transaction';
 import {navigateToParticipantPage} from '@libs/IOUUtils';
 import Navigation from '@libs/Navigation/Navigation';
-import {hasOnlyPersonalPolicies as hasOnlyPersonalPoliciesUtil, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {hasOnlyPersonalPolicies as hasOnlyPersonalPoliciesUtil, isGroupPolicy} from '@libs/PolicyUtils';
 import {generateReportID, getPolicyExpenseChat, isSelfDM} from '@libs/ReportUtils';
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
 import type {ReceiptFile} from '@pages/iou/request/step/IOURequestStepScan/types';
@@ -80,7 +80,7 @@ function useReceiptScanDrop() {
         }
 
         if (
-            isPaidGroupPolicy(activePolicy) &&
+            isGroupPolicy(activePolicy) &&
             activePolicy?.isPolicyExpenseChatEnabled &&
             !shouldRestrictUserBillableActions(activePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID)
         ) {
diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts
index eb1594d833d2..87b9dd722ee8 100644
--- a/src/hooks/useSearchBulkActions.ts
+++ b/src/hooks/useSearchBulkActions.ts
@@ -1,4 +1,5 @@
 /* eslint-disable react-hooks/refs -- Refs in this hook are used inside callbacks that capture stable references; the lint rule flags false positives for these patterns */
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import {InteractionManager} from 'react-native';
@@ -55,6 +56,7 @@ import {
     isInvoiceReport,
     isIOUReport as isIOUReportUtil,
     isSelfDM,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import {buildSearchQueryJSON, buildSearchQueryString, serializeQueryJSONForBackend} from '@libs/SearchQueryUtils';
 import {getSelectedGroupFilterEntry, navigateToSearchRHP, shouldShowDeleteOption} from '@libs/SearchUIUtils';
@@ -381,6 +383,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
 
     const [dismissedRejectUseExplanation] = useOnyx(ONYXKEYS.NVP_DISMISSED_REJECT_USE_EXPLANATION);
     const [dismissedHoldUseExplanation] = useOnyx(ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     const isExpenseReportType = queryJSON?.type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
     const expensifyIcons = useMemoizedLazyExpensifyIcons([
@@ -1243,6 +1246,56 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
         });
     }, [isExpenseReportType, defaultExpensePolicy, selectedReports, accountID]);
 
+    const allReportsShouldMarkAsDone = useMemo(() => {
+        if (selectedReports.length > 0) {
+            return selectedReports.every((report) => {
+                const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`];
+
+                return shouldShowMarkAsDone({
+                    isTrackIntentUser,
+                    report: fullReport,
+                    policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`],
+                });
+            });
+        }
+
+        return Object.values(selectedTransactions).every((transaction) => {
+            const reportID = transaction.reportID;
+            const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+
+            return shouldShowMarkAsDone({
+                isTrackIntentUser,
+                report: fullReport,
+                policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${transaction.policyID}`],
+            });
+        });
+    }, [selectedReports, currentSearchResults?.data, isTrackIntentUser, policies, selectedTransactions]);
+
+    const noReportsShouldMarkAsDone = useMemo(() => {
+        if (selectedReports.length > 0) {
+            return selectedReports.every((report) => {
+                const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`];
+
+                return !shouldShowMarkAsDone({
+                    isTrackIntentUser,
+                    report: fullReport,
+                    policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`],
+                });
+            });
+        }
+
+        return Object.values(selectedTransactions).every((transaction) => {
+            const reportID = transaction.reportID;
+            const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+
+            return !shouldShowMarkAsDone({
+                isTrackIntentUser,
+                report: fullReport,
+                policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${transaction.policyID}`],
+            });
+        });
+    }, [selectedReports, currentSearchResults?.data, isTrackIntentUser, policies, selectedTransactions]);
+
     const headerButtonsOptions = useMemo(() => {
         if (selectedTransactionsKeys.length === 0 || status == null || !hash) {
             return CONST.EMPTY_ARRAY as unknown as Array<DropdownOption<SearchHeaderOptionValue>>;
@@ -1577,13 +1630,17 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
             !isOffline &&
             areSelectedTransactionsIncludedInReports &&
             (selectedReports.length
-                ? selectedReports.every((report) => report.canSubmit)
-                : selectedTransactionsKeys.every((id) => selectedTransactions[id].action === CONST.SEARCH.ACTION_TYPES.SUBMIT));
+                ? selectedReports.every((report) => report.canSubmit) &&
+                  // Disable for mixed selections: all must be the same submit type
+                  (isTrackIntentUser ? allReportsShouldMarkAsDone || noReportsShouldMarkAsDone : true)
+                : selectedTransactionsKeys.every((id) => selectedTransactions[id].action === CONST.SEARCH.ACTION_TYPES.SUBMIT) &&
+                  // Disable for mixed selections: all must be the same submit type
+                  (isTrackIntentUser ? allReportsShouldMarkAsDone || noReportsShouldMarkAsDone : true));
 
         if (shouldShowSubmitOption) {
             options.push({
                 icon: expensifyIcons.Send,
-                text: translate('common.submit'),
+                text: allReportsShouldMarkAsDone ? translate('common.markAsDone') : translate('common.submit'),
                 value: CONST.SEARCH.BULK_ACTION_TYPES.SUBMIT,
                 shouldCloseModalOnSelect: true,
                 onSelected: () => {
@@ -1944,6 +2001,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
         userBillingGracePeriodEnds,
         ownerBillingGracePeriodEnd,
         currentSearchKey,
+        isTrackIntentUser,
         getCurrencyDecimals,
         amountOwed,
         allTransactions,
diff --git a/src/hooks/useSearchSections.ts b/src/hooks/useSearchSections.ts
index 89e6c3e3a8d2..c2c7881f8c92 100644
--- a/src/hooks/useSearchSections.ts
+++ b/src/hooks/useSearchSections.ts
@@ -26,6 +26,7 @@ function useSearchSections(): UseSearchSectionsResult {
     const {convertToDisplayString} = useCurrencyListActions();
 
     const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
+    const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
     const [nonPersonalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST);
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
 
@@ -55,7 +56,8 @@ function useSearchSections(): UseSearchSectionsResult {
             archivedReportsIDList: archivedReportsIDSet,
             isActionLoadingSet,
             cardFeeds,
-            cardList: nonPersonalAndWorkspaceCards,
+            cardList: personalAndWorkspaceCards,
+            nonPersonalAndWorkspaceCardList: nonPersonalAndWorkspaceCards,
             conciergeReportID,
             convertToDisplayString,
             reportAttributesDerivedValue,
diff --git a/src/hooks/useSearchTypeMenuSections.ts b/src/hooks/useSearchTypeMenuSections.ts
index b30b4d0bd8d8..28920ad130ff 100644
--- a/src/hooks/useSearchTypeMenuSections.ts
+++ b/src/hooks/useSearchTypeMenuSections.ts
@@ -2,11 +2,11 @@ import {defaultExpensifyCardSelector} from '@selectors/Card';
 import {validTransactionDraftIDsSelector} from '@selectors/TransactionDraft';
 import {useCallback, useEffect, useMemo, useState} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
-import isTrackOnboardingChoice from '@libs/OnboardingUtils';
 import {createTypeMenuSections, doesSearchItemMatchSort} from '@libs/SearchUIUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {IntroSelected, Policy, Session} from '@src/types/onyx';
+import {isTrackIntentUserSelector} from '@src/selectors/Onboarding';
+import type {Policy, Session} from '@src/types/onyx';
 import useCardFeedsForDisplay from './useCardFeedsForDisplay';
 import useCreateEmptyReportConfirmation from './useCreateEmptyReportConfirmation';
 import useMappedPolicies from './useMappedPolicies';
@@ -44,8 +44,6 @@ const currentUserLoginAndAccountIDSelector = (session: OnyxEntry<Session>) => ({
     accountID: session?.accountID,
 });
 
-const isTrackIntentUserSelector = (introSelected: OnyxEntry<IntroSelected>) => isTrackOnboardingChoice(introSelected?.choice);
-
 type UseSearchTypeMenuSectionsParams = {
     hash?: number;
     similarSearchHash?: number;
diff --git a/src/hooks/useSelectionModeReportActions.ts b/src/hooks/useSelectionModeReportActions.ts
index bb4dea802e5b..2f0a90af1d63 100644
--- a/src/hooks/useSelectionModeReportActions.ts
+++ b/src/hooks/useSelectionModeReportActions.ts
@@ -1,5 +1,5 @@
 import {delegateEmailSelector, isUserValidatedSelector} from '@selectors/Account';
-import {hasSeenTourSelector} from '@selectors/Onboarding';
+import {hasSeenTourSelector, isTrackIntentUserSelector} from '@selectors/Onboarding';
 import truncate from 'lodash/truncate';
 import {useContext, useEffect, useRef, useState} from 'react';
 // eslint-disable-next-line no-restricted-imports
@@ -38,6 +38,7 @@ import {
     isIOUReport as isIOUReportUtil,
     isReportOwner,
     shouldBlockSubmitDueToStrictPolicyRules,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import {markPendingRTERTransactionsAsCash} from '@userActions/Transaction';
@@ -126,6 +127,8 @@ function useSelectionModeReportActions({
     const [invoiceReceiverPolicy] = useOnyx(
         `${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined}`,
     );
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+
     const existingB2BInvoiceReport = useParticipantsInvoiceReport(activePolicyID, CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS, chatReport?.policyID);
     const activeAdminPolicies = useActiveAdminPolicies();
     const lastWorkspaceNumber = useLastWorkspaceNumber();
@@ -511,7 +514,7 @@ function useSelectionModeReportActions({
         let idx = 0;
         if (hasSubmitAction && !shouldBlockSubmit) {
             actions[idx++] = {
-                text: translate('common.submit'),
+                text: shouldShowMarkAsDone({policy, report, isTrackIntentUser}) ? translate('common.markAsDone') : translate('common.submit'),
                 icon: expensifyIcons.Send,
                 value: CONST.REPORT.PRIMARY_ACTIONS.SUBMIT,
                 onSelected: handleSubmitReport,
diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index 2e4e31f13a0d..c15e52fe29ae 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -1,5 +1,7 @@
 import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
+import type {ValueOf} from 'type-fest';
+import {setInboxTab} from '@libs/actions/User';
 import Log from '@libs/Log';
 import SidebarUtils from '@libs/SidebarUtils';
 import type {BrickRoad} from '@libs/WorkspacesSettingsUtils';
@@ -27,27 +29,40 @@ type SidebarOrderedReportsContextProviderProps = {
 };
 
 type SidebarOrderedReportsStateContextValue = {
-    orderedReports: OnyxTypes.Report[];
+    /** The reports rendered in the LHN for the active Inbox tab (a filtered subset of orderedReportIDs). */
+    filteredReports: OnyxTypes.Report[];
+    /** All ordered LHN report IDs, unfiltered by the active Inbox tab. Used for total counts (e.g. focus-mode switch) and brick road. */
     orderedReportIDs: string[];
     currentReportID: string | undefined;
     chatTabBrickRoad: BrickRoad;
+    activeTab: ValueOf<typeof CONST.INBOX_TAB>;
+    inboxTabCounts: Record<typeof CONST.INBOX_TAB.TODO | typeof CONST.INBOX_TAB.UNREAD, number>;
 };
 
 type SidebarOrderedReportsActionsContextValue = {
     clearLHNCache: () => void;
+    setActiveTab: (tab: ValueOf<typeof CONST.INBOX_TAB>) => void;
+    setStickyReportID: (reportID: string) => void;
 };
 
-type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean}>;
+type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean; isUnreadReport?: boolean}>;
 
 const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsStateContextValue>({
-    orderedReports: [],
+    filteredReports: [],
     orderedReportIDs: [],
     currentReportID: '',
     chatTabBrickRoad: undefined,
+    activeTab: CONST.INBOX_TAB.ALL,
+    inboxTabCounts: {
+        [CONST.INBOX_TAB.TODO]: 0,
+        [CONST.INBOX_TAB.UNREAD]: 0,
+    },
 });
 
 const SidebarOrderedReportsActionsContext = createContext<SidebarOrderedReportsActionsContextValue>({
     clearLHNCache: () => {},
+    setActiveTab: () => {},
+    setStickyReportID: () => {},
 });
 
 const policyMapper = (policy: OnyxEntry<OnyxTypes.Policy>): PartialPolicyForSidebar =>
@@ -72,6 +87,8 @@ function SidebarOrderedReportsContextProvider({
 }: SidebarOrderedReportsContextProviderProps) {
     const {localeCompare} = useLocalize();
     const [priorityMode = CONST.PRIORITY_MODE.DEFAULT] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
+    const [inboxTab = CONST.INBOX_TAB.ALL] = useOnyx(ONYXKEYS.NVP_INBOX_TAB);
+    const activeTab = inboxTab ?? CONST.INBOX_TAB.ALL;
     const [chatReports, {sourceValue: reportUpdates}] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
     const [, {sourceValue: policiesUpdates}] = useMappedPolicies(policyMapper);
     const [transactions, {sourceValue: transactionsUpdates}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION);
@@ -278,7 +295,32 @@ function SidebarOrderedReportsContextProvider({
 
     const orderedReportIDs = useMemo(() => getOrderedReportIDs(), [getOrderedReportIDs]);
 
-    // Get the actual reports based on the ordered IDs
+    // When a report is opened from the To-do/Unread tab (see setStickyReportID), we remember it so it
+    // stays visible after viewing it removes it from the tab (e.g. it gets read). It's only set on a
+    // non-All tab, so opening a chat from the All tab never makes it appear under Unread/To-do.
+    const [stickyReport, setStickyReport] = useState<{reportID: string; tab: ValueOf<typeof CONST.INBOX_TAB>} | undefined>(undefined);
+
+    // The reports for the active tab, plus the sticky report opened from it (kept visible even after it's read).
+    const stickyReportID = stickyReport?.reportID;
+    const stickyReportTab = stickyReport?.tab;
+    const filteredReportIDs = useMemo(() => {
+        const baseFilteredReportIDs = SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab);
+        if (activeTab === CONST.INBOX_TAB.ALL || !stickyReportID || stickyReportTab !== activeTab || baseFilteredReportIDs.includes(stickyReportID)) {
+            return baseFilteredReportIDs;
+        }
+        if (!orderedReportIDs.includes(stickyReportID)) {
+            // While opening the report, reading it can briefly drop it from the LHN set entirely (before
+            // navigation marks it as the focused report). Keep it at the top so the list doesn't flash empty.
+            return [stickyReportID, ...baseFilteredReportIDs];
+        }
+        const baseSet = new Set(baseFilteredReportIDs);
+        return orderedReportIDs.filter((reportID) => baseSet.has(reportID) || reportID === stickyReportID);
+    }, [orderedReportIDs, reportsToDisplayInLHN, activeTab, stickyReportTab, stickyReportID]);
+
+    // The count shown in each tab's badge, derived from the full "All" set (not the currently filtered view).
+    const inboxTabCounts = useMemo(() => SidebarUtils.getInboxTabCounts(orderedReportIDs, reportsToDisplayInLHN), [orderedReportIDs, reportsToDisplayInLHN]);
+
+    // Get the actual reports based on the filtered IDs
     const getOrderedReports = useCallback(
         (reportIDs: string[]): OnyxTypes.Report[] => {
             if (!chatReports) {
@@ -289,7 +331,7 @@ function SidebarOrderedReportsContextProvider({
         [chatReports],
     );
 
-    const orderedReports = useMemo(() => getOrderedReports(orderedReportIDs), [getOrderedReports, orderedReportIDs]);
+    const filteredReports = useMemo(() => getOrderedReports(filteredReportIDs), [getOrderedReports, filteredReportIDs]);
 
     const clearLHNCache = useCallback(() => {
         Log.info('[useSidebarOrderedReports] Clearing sidebar cache manually via debug modal');
@@ -297,6 +339,25 @@ function SidebarOrderedReportsContextProvider({
         setClearCacheDummyCounter((current) => current + 1);
     }, []);
 
+    const setActiveTab = useCallback((tab: ValueOf<typeof CONST.INBOX_TAB>) => {
+        setInboxTab(tab);
+
+        // The sticky report is scoped to the tab it was opened from, so reset it when switching tabs.
+        setStickyReport(undefined);
+    }, []);
+
+    // Called when a report is opened from the LHN. On the To-do/Unread tabs we remember it so it stays
+    // visible after viewing it removes it from the tab. On the All tab we keep nothing sticky.
+    const setStickyReportID = useCallback(
+        (reportID: string) => {
+            if (activeTab === CONST.INBOX_TAB.ALL) {
+                return;
+            }
+            setStickyReport({reportID, tab: activeTab});
+        },
+        [activeTab],
+    );
+
     const stateValue: SidebarOrderedReportsStateContextValue = useMemo(() => {
         // We need to make sure the current report is in the list of reports, but we do not want
         // to have to re-generate the list every time the currentReportID changes. To do that
@@ -308,31 +369,52 @@ function SidebarOrderedReportsContextProvider({
         // requirement for web. Consider a case, where we have report with expenses and we click on
         // any expense, a new LHN item is added in the list and is visible on web. But on mobile, we
         // just navigate to the screen with expense details, so there seems no point to execute this logic on mobile.
+        // Only the "All" tab force-regenerates to surface the current report. On the To-do/Unread tabs the
+        // sticky-aware filteredReportIDs already keeps the opened report visible, and re-filtering here
+        // (without the sticky report) would briefly empty the list while opening it.
         if (
-            (!shouldUseNarrowLayout || orderedReportIDs.length === 0) &&
+            activeTab === CONST.INBOX_TAB.ALL &&
+            (!shouldUseNarrowLayout || filteredReportIDs.length === 0) &&
             derivedCurrentReportID &&
             derivedCurrentReportID !== '-1' &&
-            orderedReportIDs.indexOf(derivedCurrentReportID) === -1
+            filteredReportIDs.indexOf(derivedCurrentReportID) === -1
         ) {
             const updatedReportIDs = getOrderedReportIDs();
-            const updatedReports = getOrderedReports(updatedReportIDs);
+            const updatedFilteredIDs = SidebarUtils.filterReportsForInboxTab(updatedReportIDs, reportsToDisplayInLHN, activeTab);
+            const updatedReports = getOrderedReports(updatedFilteredIDs);
             return {
-                orderedReports: updatedReports,
+                filteredReports: updatedReports,
                 orderedReportIDs: updatedReportIDs,
                 currentReportID: derivedCurrentReportID,
                 chatTabBrickRoad: getChatTabBrickRoad(updatedReportIDs, reportAttributes),
+                activeTab,
+                inboxTabCounts,
             };
         }
 
         return {
-            orderedReports,
+            filteredReports,
             orderedReportIDs,
             currentReportID: derivedCurrentReportID,
             chatTabBrickRoad: getChatTabBrickRoad(orderedReportIDs, reportAttributes),
+            activeTab,
+            inboxTabCounts,
         };
-    }, [getOrderedReportIDs, orderedReportIDs, derivedCurrentReportID, shouldUseNarrowLayout, getOrderedReports, orderedReports, reportAttributes]);
+    }, [
+        getOrderedReportIDs,
+        orderedReportIDs,
+        filteredReportIDs,
+        derivedCurrentReportID,
+        shouldUseNarrowLayout,
+        getOrderedReports,
+        filteredReports,
+        reportAttributes,
+        activeTab,
+        inboxTabCounts,
+        reportsToDisplayInLHN,
+    ]);
 
-    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache}), [clearLHNCache]);
+    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache, setActiveTab, setStickyReportID}), [clearLHNCache, setActiveTab, setStickyReportID]);
 
     useEffect(() => {
         const hookExecutionDuration = performance.now() - hookStartTime.current;
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 884e41cab1b3..8fd0f0768da0 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -108,7 +109,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Mehrfachauswahl',
         saveChanges: 'Änderungen speichern',
         submit: 'Senden',
+        markAsDone: 'Als erledigt markieren',
         submitted: 'Übermittelt',
+        markedAsDoneStatus: 'Als erledigt markiert',
         rotate: 'Drehen',
         zoom: 'Zoom',
         password: 'Passwort',
@@ -293,7 +296,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Beschreibung',
         title: 'Titel',
         assignee: 'Zuständige Person',
-        createdBy: 'Erstellt von',
         with: 'mit',
         shareCode: 'Code teilen',
         share: 'Teilen',
@@ -314,6 +316,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Händler',
         change: 'Ändern',
         category: 'Kategorie',
+        vendor: 'Anbieter',
         report: 'Bericht',
         billable: 'Abrechenbar',
         nonBillable: 'Nicht abrechenbar',
@@ -356,6 +359,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Finde einen Chat über die',
             subtitleText2: 'Schaltfläche oben oder erstellen Sie etwas mit der',
             subtitleText3: 'Schaltfläche unten.',
+            noUnreadChats: 'Keine ungelesenen Chats',
+            noTodos: 'Keine To-dos',
+            caughtUp: 'Sie sind auf dem neuesten Stand. Gut gemacht!',
+            seeAllChats: 'Alle Chats anzeigen',
         },
         businessName: 'Firmenname',
         clear: 'Löschen',
@@ -853,6 +860,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Dieser Chat ist mit ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `Hier reicht <strong>${submitterDisplayName}</strong> Auslagen bei <strong>${workspaceName}</strong> ein. Nutze einfach die +-Taste.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Hier können Sie Ausgaben nachverfolgen',
         beginningOfChatHistorySelfDM: 'Dies ist dein persönlicher Bereich. Nutze ihn für Notizen, Aufgaben, Entwürfe und Erinnerungen.',
         beginningOfChatHistorySystemDM: 'Willkommen! Lassen Sie uns Ihre Einrichtung vornehmen.',
         chatWithAccountManager: 'Chatte hier mit deiner/deinem Account Manager',
@@ -958,7 +966,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Verbindung der persönlichen Karte ${cardName} reparieren` : 'Verbindung der persönlichen Karte reparieren'),
                 subtitle: 'Wallet',
             },
-            validateAccount: {title: 'Bestätigen Sie Ihr Konto, um Expensify weiter zu verwenden', subtitle: 'Konto', cta: 'Bestätigen'},
+            validateAccount: {title: 'Bestätigen Sie Ihr Konto', subtitle: 'Konto', cta: 'Bestätigen'},
             fixFailedBilling: {title: 'Wir konnten Ihre hinterlegte Karte nicht belasten', subtitle: 'Abonnement'},
             unlockBankAccount: {
                 workspaceTitle: 'Ihr Geschäftskonto wurde gesperrt',
@@ -1013,6 +1021,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Alles erledigt',
                 f1FlagsDescription: 'Sie haben alle offenen Aufgaben abgeschlossen.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Überprüfen Sie ${count} ${count === 1 ? 'Ausgabe' : 'Spesen'}`,
         },
         upcomingTravel: 'Bevorstehende Reisen',
         upcomingTravelSection: {
@@ -1349,6 +1358,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `${amount}-Rechnung senden`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `für ${comment}` : ''}`,
         submitted: (memo?: string) => `eingereicht${memo ? `, mit dem Vermerk ${memo}` : ''}`,
+        markedAsDone: (memo) => `als erledigt markiert${memo ? `, mit dem Vermerk ${memo}` : ''}`,
         automaticallySubmitted: `eingereicht über <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">Einreichungen verzögern</a>`,
         queuedToSubmitViaDEW: 'zur Einreichung über benutzerdefinierten Genehmigungsworkflow eingereiht',
         queuedToApproveViaDEW: 'Zur Genehmigung über benutzerdefinierten Genehmigungsworkflow eingereiht',
@@ -1565,6 +1575,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'entfernt',
         transactionPending: 'Transaktion ausstehend.',
         chooseARate: 'Wähle einen Rückerstattungssatz pro Meile oder Kilometer für den Workspace aus',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} bis ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Gültig ab ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Gültig bis ${endDate}`,
         unapprove: 'Genehmigung aufheben',
         unapproveReport: 'Bericht ablehnen',
         headsUp: 'Achtung!',
@@ -1665,6 +1678,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Beheben Sie den Kursfehler und versuchen Sie es erneut.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Erklären<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge hat diese Ausgabe <strong>${vendorName}</strong> zugeordnet`,
         duplicateNonDefaultWorkspacePerDiemError:
             'Sie können Per-Diem-Ausgaben nicht über mehrere Workspaces hinweg duplizieren, da sich die Sätze zwischen den Workspaces unterscheiden können.',
         rulesModifiedFields: {
@@ -1794,6 +1808,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Warten darauf, dass ein Admin Spesen einreicht.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Wartet darauf, dass <strong>Sie</strong> dies als erledigt markieren.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Warten darauf, dass <strong>${actor}</strong> dies als erledigt markiert.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Warten darauf, dass ein Admin dies als erledigt markiert.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
@@ -2227,10 +2256,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Verdächtige Aktivität melden',
         lockAccount: 'Konto sperren',
+        lockMyAccount: 'Sperren Sie mein Konto',
         unlockAccount: 'Konto entsperren',
-        compromisedDescription:
-            'Ist Ihnen etwas Ungewöhnliches mit Ihrem Konto aufgefallen? Wenn Sie es melden, wird Ihr Konto sofort gesperrt, neue Expensify Karte-Transaktionen werden blockiert und alle Kontenänderungen verhindert.',
-        domainAdminsDescription: 'Für Domain-Admins: Dadurch werden auch alle Aktivitäten der Expensify Karte und alle Administratoraktionen in Ihrer/Ihren Domain(s) pausiert.',
+        findYourSituation: 'Die meisten Probleme erfordern keine Sperrung Ihres Kontos! Finden Sie Ihre Situation unten:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Karte verloren oder unbekannte Abbuchungen</a>: Sperren Sie Ihre Karte und kontaktieren Sie Concierge, um unbekannte Transaktionen anzufechten.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Unbefugter Kontozugriff</a>: Sperren Sie Ihr Konto unten. Dadurch werden neue Expensify Karte-Transaktionen, Kartenbestellungen und Kontenänderungen blockiert. Wenn Sie ein Domain-Admin sind, wird dadurch außerdem alle domänenweite Kartenaktivität und Administratoraktionen angehalten.',
+        securityTeamFollowUp: 'Unser Sicherheitsteam wird sich nach der Sperrung von <a href="mailto:risk@expensify.com">risk@expensify.com</a> bei Ihnen melden.',
         areYouSure: 'Möchtest du dein Expensify-Konto wirklich sperren?',
         onceLocked: 'Sobald Ihr Konto gesperrt ist, wird es eingeschränkt, bis eine Entsperrungsanfrage gestellt und eine Sicherheitsprüfung durchgeführt wurde',
         unlockTitle: 'Wir haben Ihre Anfrage erhalten',
@@ -2599,13 +2632,10 @@ ${amount} für ${merchant} – ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `Ausgaben von ${members} und die genehmigende Person ist ${approvers}`,
         addApprovalButton: 'Genehmigungsablauf hinzufügen',
         editWorkflowAction: 'Bearbeiten',
-        addAgentAction: 'Agent hinzufügen',
         findWorkflow: 'Workflow suchen',
         addApprovalTip: 'Dieser Standard-Workflow gilt für alle Mitglieder, sofern kein spezifischerer Workflow vorhanden ist.',
         approver: 'Genehmiger',
         addApprovalsDescription: 'Zusätzliche Genehmigung einholen, bevor eine Zahlung autorisiert wird.',
-        automateApprovalsWithAgentsTitle: 'Genehmigungen mit Agenten automatisieren',
-        automateApprovalsWithAgentsSubtitle: 'Fügen Sie die untenstehende Person zum Workflow hinzu, um Genehmigungen zu automatisieren.',
         makeOrTrackPaymentsTitle: 'Zahlungen',
         makeOrTrackPaymentsDescription:
             'Fügen Sie eine bevollmächtigte zahlende Person für in Expensify getätigte Zahlungen hinzu oder verfolgen Sie Zahlungen, die andernorts getätigt wurden.',
@@ -2901,6 +2931,12 @@ ${amount} für ${merchant} – ${date}`,
             },
         },
     },
+    focusModeUpdateModal: {
+        title: 'Willkommen im #Focus-Modus!',
+        prompt: (priorityModePageUrl: string) =>
+            `Behalten Sie den Überblick, indem Sie nur ungelesene Chats oder Chats sehen, die Ihre Aufmerksamkeit erfordern. Keine Sorge, Sie können dies jederzeit in den <a href="${priorityModePageUrl}">Einstellungen</a> ändern.`,
+    },
+    inboxTabs: {all: 'Alle', todo: 'Aufgaben', unread: 'Ungelesen'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
         generatingPDF: 'PDF erstellen',
@@ -3468,11 +3504,6 @@ ${amount} für ${merchant} – ${date}`,
         year: 'Jahr',
         selectYear: 'Bitte ein Jahr auswählen',
     },
-    focusModeUpdateModal: {
-        title: 'Willkommen im #Fokusmodus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Behalte den Überblick, indem du nur ungelesene Chats oder Chats siehst, die deine Aufmerksamkeit benötigen. Keine Sorge, du kannst das jederzeit in den <a href="${priorityModePageUrl}">Einstellungen</a> ändern.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'Der Chat, den du suchst, kann nicht gefunden werden.',
         getMeOutOfHere: 'Hol mich hier raus',
@@ -4136,28 +4167,31 @@ ${amount} für ${merchant} – ${date}`,
         verificationFailed: 'Die Verifizierung ist fehlgeschlagen, daher benötigen wir zusätzliche Dokumente, um dich und dein Unternehmen zu überprüfen',
         taxIDVerification: 'Steuer-ID-Verifizierung',
         taxIDVerificationDescription: dedent(`
-        Bitte lade eine der folgenden Dateien hoch:
-        • IRS TIN/EIN-Zuweisungsschreiben
-        • IRS TIN/EIN-Antragsbestätigung (enthält normalerweise „Congratulations! The EIN has been successfully assigned“)
-        • IRS-Steuerbefreiungsschreiben mit Firmenname und EIN`),
+            Bitte lade eine der folgenden Dateien hoch:
+            • IRS TIN/EIN-Zuweisungsschreiben
+            • IRS TIN/EIN-Antragsbestätigung (enthält normalerweise „Congratulations! The EIN has been successfully assigned“)
+            • IRS-Steuerbefreiungsschreiben mit Firmenname und EIN
+        `),
         nameChangeDocument: 'Dokument zur Namensänderung',
         nameChangeDocumentDescription:
             'Wenn sich der Name deines Unternehmens seit der Beantragung der TIN/EIN geändert hat, benötigen wir dieses Dokument zur Verifizierung der angegebenen Steuer-ID',
         companyAddressVerification: 'Verifizierung der Unternehmensadresse',
         companyAddressVerificationDescription: dedent(`
-        Bitte lade eine der folgenden Dateien hoch:
-        • Aktuelle Strom-, Wasser- oder Gasrechnung mit Firmenname und Adresse
-        • Kontoauszug mit Firmenname und Adresse
-        • Aktueller Miet- oder Leasingvertrag inkl. Unterschriftsseite mit Firmenname und aktueller Adresse
-        • Versicherungsnachweis mit Firmenname und Adresse
-        • TIN-Zuweisungsdokument mit Firmenname und Adresse`),
+            Bitte lade eine der folgenden Dateien hoch:
+            • Aktuelle Strom-, Wasser- oder Gasrechnung mit Firmenname und Adresse
+            • Kontoauszug mit Firmenname und Adresse
+            • Aktueller Miet- oder Leasingvertrag inkl. Unterschriftsseite mit Firmenname und aktueller Adresse
+            • Versicherungsnachweis mit Firmenname und Adresse
+            • TIN-Zuweisungsdokument mit Firmenname und Adresse
+        `),
         userAddressVerification: 'Adressverifizierung',
         userAddressVerificationDescription: dedent(`
-        Bitte lade eine der folgenden Dateien hoch:
-        • Wählerregistrierungskarte
-        • Führerschein
-        • Kontoauszug
-        • Versorgungsrechnung`),
+            Bitte lade eine der folgenden Dateien hoch:
+            • Wählerregistrierungskarte
+            • Führerschein
+            • Kontoauszug
+            • Versorgungsrechnung
+        `),
         userDOBVerification: 'Geburtsdatumsverifizierung',
         userDOBVerificationDescription: 'Bitte lade einen in den USA ausgestellten Ausweis hoch',
         finishViaChat: 'Über Chat abschließen',
@@ -4340,7 +4374,6 @@ ${amount} für ${merchant} – ${date}`,
             customFieldHint: 'Füge benutzerdefinierte Codierung hinzu, die für alle Ausgaben dieses Mitglieds gilt.',
             reports: 'Berichte',
             reportFields: 'Berichtsfelder',
-            invoiceFields: 'Rechnungsfelder',
             reportTitle: 'Berichtstitel',
             reportField: 'Berichts­feld',
             taxes: 'Steuern',
@@ -4424,13 +4457,13 @@ ${amount} für ${merchant} – ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Workspace-Administrator';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Prüfer';
                     case CONST.POLICY.ROLE.EDITOR:
                         return 'Editor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Kartenverwaltung';
+                        return 'Kartenadministrator';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'Personenverwaltung';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
@@ -6025,29 +6058,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             reportFieldInitialValueRequiredError: 'Bitte wähle einen Anfangswert für ein Berichtsfeld aus',
             genericFailureMessage: 'Beim Aktualisieren des Berichtfelds ist ein Fehler aufgetreten. Bitte versuche es erneut.',
         },
-        invoiceFields: {
-            subtitle: 'Rechnungsfelder können hilfreich sein, wenn du zusätzliche Informationen einfügen möchtest.',
-            importedFromAccountingSoftware: 'Die folgenden Rechnungsfelder werden importiert aus Ihrem',
-            disableInvoiceFields: 'Rechnungsfelder deaktivieren',
-            disableInvoiceFieldsConfirmation: 'Sind Sie sicher? Rechnungsfelder werden auf Rechnungen deaktiviert.',
-            delete: 'Rechnungsfeld löschen',
-            deleteConfirmation: 'Sind Sie sicher, dass Sie dieses Rechnungsfeld löschen möchten?',
-            findInvoiceField: 'Rechnungsfeld suchen',
-            nameInputSubtitle: 'Wähle einen Namen für das Rechnungsfeld.',
-            typeInputSubtitle: 'Wähle aus, welcher Rechnungsfeldtyp verwendet werden soll.',
-            initialValueInputSubtitle: 'Gib einen Startwert ein, der im Rechnungsfeld angezeigt werden soll.',
-            listValuesInputSubtitle: 'Diese Werte werden im Dropdown-Menü des Rechnungsfelds angezeigt. Aktivierte Werte können von Mitgliedern ausgewählt werden.',
-            listInputSubtitle: 'Diese Werte werden in der Rechnungsfeldliste angezeigt. Aktivierte Werte können von Mitgliedern ausgewählt werden.',
-            emptyInvoiceFieldsValues: {
-                title: 'Noch keine Listenwerte',
-                subtitle: 'Füge benutzerdefinierte Werte hinzu, die auf Rechnungen angezeigt werden.',
-            },
-            existingInvoiceFieldNameError: 'Ein Rechnungsfeld mit diesem Namen existiert bereits',
-            invoiceFieldNameRequiredError: 'Bitte gib einen Namen für das Rechnungsfeld ein',
-            invoiceFieldTypeRequiredError: 'Bitte wähle einen Rechnungsfeldtyp aus',
-            invoiceFieldInitialValueRequiredError: 'Bitte wähle einen Anfangswert für ein Rechnungsfeld aus',
-            addField: 'Feld hinzufügen',
-        },
         tags: {
             tagName: 'Tag-Name',
             requiresTag: 'Mitglieder müssen alle Ausgaben taggen',
@@ -6271,8 +6281,8 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 other: 'Mitglieder erstellen',
             }),
             makeAdmin: () => ({
-                one: 'Als Admin festlegen',
-                other: 'Admins ernennen',
+                one: 'Als Workspace-Admin festlegen',
+                other: 'Workspace-Admins ernennen',
             }),
             makeAuditor: () => ({
                 one: 'Zum Prüfer machen',
@@ -6301,12 +6311,14 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} hat einen ausstehenden Bericht in Bearbeitung, zu dem eine Aktion erforderlich ist. Bitte bitten Sie diese Person, die erforderliche Aktion abzuschließen, bevor Sie sie aus dem Workspace entfernen.`,
             allMembers: 'Alle Mitglieder',
-            admins: 'Admins',
+            admins: 'Workspace-Administratoren',
             approvers: 'Genehmigende',
             auditors: 'Prüfer',
             emptyRoleFilter: {title: 'Keine Mitglieder entsprechen diesem Filter', subtitle: 'Laden Sie ein Mitglied ein oder ändern Sie den Filter oben.'},
             configureHRSync: (providerName: string) => `Synchronisierung mit ${providerName} einrichten.`,
             syncWithHR: (providerName: string) => `Mit ${providerName} synchronisieren`,
+            makeCardAdmin: () => ({one: 'Zum Karten-Admin machen', other: 'Karten-Admins festlegen'}),
+            cardAdmins: 'Karten-Admins',
         },
         card: {
             getStartedIssuing: 'Beginne, indem du deine erste virtuelle oder physische Karte ausstellst.',
@@ -6724,6 +6736,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             }),
             enableRate: 'Kurs aktivieren',
             status: 'Status',
+            statusActive: 'Aktiv',
+            statusFuture: 'Zukünftig',
+            statusExpired: 'Abgelaufen',
+            statusInactive: 'Inaktiv',
             unit: 'Einheit',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Steuern müssen im Workspace aktiviert sein, um diese Funktion zu verwenden. Gehe zu <a href="#">Weitere Funktionen</a>, um das zu ändern.</muted-text>',
@@ -6852,12 +6868,6 @@ Möchten Sie sie wirklich noch einmal exportieren?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Berichtsfelder sind nur im Control-Tarif verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Rechnungsfelder',
-                description: `Mit Rechnungsfeldern kannst du zusätzliche Details auf Rechnungsebene in Rechnungen aufnehmen.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Rechnungsfelder sind nur im Control-Tarif verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Profitiere von automatischer Synchronisierung und reduziere manuelle Eingaben mit der Expensify + NetSuite-Integration. Gewinne detaillierte Finanzanalysen in Echtzeit mit nativer und benutzerdefinierter Segmentunterstützung, einschließlich Projekt- und Kundenzuordnung.`,
@@ -6959,12 +6969,6 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Entfernungsraten sind im Collect-Tarif verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Prüfer',
-                description: 'Prüfer erhalten schreibgeschützten Zugriff auf alle Berichte für vollständige Transparenz und Compliance-Überwachung.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Auditor:innen sind nur im Control-Tarif verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Mehrere Genehmigungsstufen',
                 description:
@@ -7064,6 +7068,12 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Die Rechnungsstellung ist in den Collect- und Control-Tarifen verfügbar, beginnend ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Rollen für Richtliniensteuerung',
+                description: 'Verwenden Sie spezialisierte Rollen wie Auditor und Karten-Admin, um Mitgliedern nur den Zugriff zu gewähren, den sie benötigen.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Spezialisierte Arbeitsbereichsrollen sind nur im Control-Tarif verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -7390,6 +7400,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 deleteRuleConfirmation: 'Sind Sie sicher, dass Sie diese Regel löschen möchten?',
                 describeRuleTitle: 'Beschreiben Sie Ihre Regel',
                 describeRuleSubtitle: 'Beschreiben Sie Ihre Regel und Concierge erstellt sie',
+                disclaimer: 'KI-Agenten können Fehler machen.',
             },
         },
         planTypePage: {
@@ -8070,21 +8081,19 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} von ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `hat den Standardsteuersatz der Kategorie „${categoryName}“ auf „${newTax}“ geändert (zuvor „${oldTax}“)`,
         addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `„${rateName}“-Satz von ${rateValue} hinzugefügt`,
         addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `„${rateName}“-Satz von ${rateValue} hinzugefügt, gültig ab ${startDate}`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `„${rateName}“-Satz von ${rateValue} hinzugefügt, gültig bis ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `hat den Tarif „${rateName}“ mit ${rateValue} hinzugefügt, gültig vom ${startDate} bis ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `Startdatum des Tarifs „${rateName}“ auf ${newDate} aktualisiert (zuvor ${oldDate})` : `Startdatum des Tarifs „${rateName}“ auf ${newDate} festlegen`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `Enddatum des Tarifs „${rateName}“ auf ${newDate} aktualisiert (zuvor ${oldDate})` : `Enddatum des Tarifs „${rateName}“ auf ${newDate} setzen`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `Start- und Enddatum des Tarifs „${rateName}“ auf ${newStartDate} - ${newEndDate} aktualisiert (zuvor ${oldStartDate} - ${oldEndDate})`
-                : `Start- und Enddatum des Tarifs „${rateName}“ auf ${newStartDate} – ${newEndDate} festlegen`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `Startdatum aus Tarif „${rateName}“ entfernt (zuvor ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `Enddatum aus dem Tarif „${rateName}“ entfernt (zuvor ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `hat den Entfernungs­tarif „${rateName}“ aktualisiert, sodass er für ${newDateRange} gilt (zuvor ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `ab dem ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `bis ${date}`,
+        customUnitRateDateRangeAllDates: () => `für alle Daten`,
     },
     roomMembersPage: {
         memberNotFound: 'Mitglied nicht gefunden.',
@@ -8526,8 +8535,11 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                     `Die Verbindung für ${feedName} ist unterbrochen. Um Kartenimporte wiederherzustellen, <a href='${workspaceCompanyCardRoute}'>melden Sie sich bei Ihrer Bank an</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} als ${role === 'member' ? 'a' : 'an'} ${role} hinzugefügt`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'a';
+                    return didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} wurde als ${article} ${translatedRole} hinzugefügt`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `hat die Rolle von ${email} in ${newRole} geändert (zuvor ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
@@ -9425,6 +9437,11 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Als <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">Copilot</a> von ${accountOwnerEmail} hast du keine Berechtigung, diese Aktion auszuführen. Entschuldigung!`,
+        removeCopilotAccess: 'Meinen Copilot-Zugriff entfernen',
+        removeCopilotAccessTitle: 'Copilot-Zugriff entfernen?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Sind Sie sicher, dass Sie Ihren Copilot-Zugriff auf das Expensify-Konto von ${delegatorName} entfernen möchten? Diese Aktion kann nicht rückgängig gemacht werden.`,
+        removeCopilotAccessConfirm: 'Zugriff entfernen',
         copilotAccess: 'Copilot-Zugriff',
     },
     debug: {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 6afe4e0574a8..cdf27de7f1a7 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -28,6 +28,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -109,8 +110,11 @@ const translations = {
         selectMultiple: 'Select multiple',
         saveChanges: 'Save changes',
         submit: 'Submit',
+        markAsDone: 'Mark as done',
         // @context Status label meaning an item has already been sent or submitted (e.g., a form or report). Not the action “to submit.”
         submitted: 'Submitted',
+        // @context Status label meaning an item has been marked as done (track-intent users). Not the action “to mark as done.”
+        markedAsDoneStatus: 'Marked as done',
         rotate: 'Rotate',
         zoom: 'Zoom',
         password: 'Password',
@@ -307,7 +311,6 @@ const translations = {
         description: 'Description',
         title: 'Title',
         assignee: 'Assignee',
-        createdBy: 'Created by',
         with: 'with',
         shareCode: 'Share code',
         share: 'Share',
@@ -329,6 +332,7 @@ const translations = {
         merchant: 'Merchant',
         change: 'Change',
         category: 'Category',
+        vendor: 'Vendor',
         report: 'Report',
         billable: 'Billable',
         nonBillable: 'Non-billable',
@@ -372,6 +376,10 @@ const translations = {
             subtitleText1: 'Find a chat using the',
             subtitleText2: 'button above, or create something using the',
             subtitleText3: 'button below.',
+            noUnreadChats: 'No unread chats',
+            noTodos: 'No to-dos',
+            caughtUp: "You're all caught up. Well done!",
+            seeAllChats: 'See all chats',
         },
         businessName: 'Business name',
         clear: 'Clear',
@@ -886,6 +894,7 @@ const translations = {
         beginningOfChatHistory: (users: string) => `This chat is with ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `This is where <strong>${submitterDisplayName}</strong> will submit expenses to <strong>${workspaceName}</strong>. Just use the + button.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: "This is where you'll track expenses.",
         beginningOfChatHistorySelfDM: 'This is your personal space. Use it for notes, tasks, drafts, and reminders.',
         beginningOfChatHistorySystemDM: "Welcome! Let's get you set up.",
         chatWithAccountManager: 'Chat with your account manager here',
@@ -1004,7 +1013,7 @@ const translations = {
                 cta: 'Review',
             },
             validateAccount: {
-                title: 'Validate your account to continue using Expensify',
+                title: 'Validate your account',
                 subtitle: 'Account',
                 cta: 'Validate',
             },
@@ -1051,6 +1060,7 @@ const translations = {
             menuItemDescription: 'See what Expensify can do in 2 min',
         },
         forYouSection: {
+            reviewExpenses: ({count}: {count: number}) => `Review ${count} ${count === 1 ? 'expense' : 'expenses'}`,
             submit: ({count}: {count: number}) => `Submit ${count} ${count === 1 ? 'report' : 'reports'}`,
             approve: ({count}: {count: number}) => `Approve ${count} ${count === 1 ? 'report' : 'reports'}`,
             pay: ({count}: {count: number}) => `Pay ${count} ${count === 1 ? 'report' : 'reports'}`,
@@ -1409,6 +1419,7 @@ const translations = {
         sendInvoice: (amount: string) => `Send ${amount} invoice`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? ` for ${comment}` : ''}`,
         submitted: (memo?: string) => `submitted${memo ? `, saying ${memo}` : ''}`,
+        markedAsDone: (memo?: string) => `marked as done${memo ? `, saying ${memo}` : ''}`,
         automaticallySubmitted: `submitted via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">delay submissions</a>`,
         queuedToSubmitViaDEW: 'queued to submit via custom approval workflow',
         failedToAutoSubmitViaDEW: (reason: string) => `failed to submit the report via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">delay submissions</a>. ${reason}`,
@@ -1625,6 +1636,9 @@ const translations = {
         removed: 'removed',
         transactionPending: 'Transaction pending.',
         chooseARate: 'Select a workspace reimbursement rate per mile or kilometer',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} to ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Valid from ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Valid until ${endDate}`,
         unapprove: 'Unapprove',
         unapproveReport: 'Unapprove report',
         headsUp: 'Heads up!',
@@ -1725,6 +1739,7 @@ const translations = {
         },
         correctRateError: 'Fix the rate error and try again.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explain<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge matched this expense to <strong>${vendorName}</strong>`,
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'marked the expense as "reimbursable"' : 'marked the expense as "non-reimbursable"'),
             billable: (value: boolean) => (value ? 'marked the expense as "billable"' : 'marked the expense as "non-billable"'),
@@ -1853,6 +1868,22 @@ const translations = {
                         return `Waiting for an admin to submit expenses.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                // eslint-disable-next-line default-case
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Waiting for <strong>you</strong> to mark this as done.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Waiting for <strong>${actor}</strong> to mark this as done.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Waiting for an admin to mark this as done.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
@@ -2309,12 +2340,16 @@ const translations = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Report suspicious activity',
         lockAccount: 'Lock account',
+        lockMyAccount: 'Lock my account',
         unlockAccount: 'Unlock account',
         unlockTitle: 'We’ve received your request',
         unlockDescription: 'We’ll review the account to verify it’s safe to unlock and reach out via Concierge with any questions.',
-        compromisedDescription:
-            'Notice something off with your account? Reporting it will immediately lock your account, block new Expensify Card transactions, and prevent any account changes.',
-        domainAdminsDescription: 'For domain admins: This also pauses all Expensify Card activity and admin actions across your domain(s).',
+        findYourSituation: 'Most issues don’t require locking your account! Find your situation below:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Lost card or unfamiliar charges</a>: Cancel your card and contact Concierge to dispute unknown transactions.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Unauthorized account access</a>: Lock your account below. This blocks new Expensify Card transactions, card orders, and account changes. If you’re a domain admin, this also pauses all domain-wide card activity and admin actions.',
+        securityTeamFollowUp: 'Our security team will follow up from <a href="mailto:risk@expensify.com">risk@expensify.com</a> after locking.',
         areYouSure: 'Are you sure you want to lock your Expensify account?',
         onceLocked: 'Once locked, your account will be restricted pending an unlock request and a security review',
     },
@@ -2664,13 +2699,10 @@ const translations = {
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `expenses from ${members}, and the approver is ${approvers}`,
         addApprovalButton: 'Add approval workflow',
         editWorkflowAction: 'Edit',
-        addAgentAction: 'Add agent',
         findWorkflow: 'Find workflow',
         addApprovalTip: 'This default workflow applies to all members, unless a more specific workflow exists.',
         approver: 'Approver',
         addApprovalsDescription: 'Require additional approval before authorizing a payment.',
-        automateApprovalsWithAgentsTitle: 'Automate approvals with agents',
-        automateApprovalsWithAgentsSubtitle: 'Add agent below to workflow to automate approvals.',
         configureViaHR: ({provider}: {provider: string}) => `Configure via ${provider}.`,
         hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
             `Approvals are managed by your ${provider} integration. To update your approval workflow, head to your ${provider} connection settings.`,
@@ -2981,6 +3013,16 @@ const translations = {
             },
         },
     },
+    focusModeUpdateModal: {
+        title: 'Welcome to #focus mode!',
+        prompt: (priorityModePageUrl: string) =>
+            `Stay on top of things by only seeing unread chats or chats that need your attention. Don’t worry, you can change this at any point in <a href="${priorityModePageUrl}">settings</a>.`,
+    },
+    inboxTabs: {
+        all: 'All',
+        todo: 'To-dos',
+        unread: 'Unread',
+    },
     reportDetailsPage: {
         goToRoom: 'Go to room',
         inWorkspace: (policyName: string) => `in ${policyName}`,
@@ -3557,11 +3599,6 @@ const translations = {
         month: 'Month',
         selectMonth: 'Please select a month',
     },
-    focusModeUpdateModal: {
-        title: 'Welcome to #focus mode!',
-        prompt: (priorityModePageUrl: string) =>
-            `Stay on top of things by only seeing unread chats or chats that need your attention. Don’t worry, you can change this at any point in <a href="${priorityModePageUrl}">settings</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'The chat you are looking for cannot be found.',
         getMeOutOfHere: 'Get me out of here',
@@ -4429,7 +4466,6 @@ const translations = {
             customFieldHint: 'Add custom coding that applies to all spend from this member.',
             reports: 'Reports',
             reportFields: 'Report fields',
-            invoiceFields: 'Invoice fields',
             reportTitle: 'Report title',
             reportField: 'Report field',
             taxes: 'Taxes',
@@ -4525,7 +4561,7 @@ const translations = {
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Workspace Admin';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.EDITOR:
@@ -6072,29 +6108,6 @@ const translations = {
             reportFieldInitialValueRequiredError: 'Please choose a report field initial value',
             genericFailureMessage: 'An error occurred while updating the report field. Please try again.',
         },
-        invoiceFields: {
-            subtitle: "Invoice fields can be helpful when you'd like to include extra information.",
-            importedFromAccountingSoftware: 'The invoice fields below are imported from your',
-            disableInvoiceFields: 'Disable invoice fields',
-            disableInvoiceFieldsConfirmation: 'Are you sure? Invoice fields will be disabled on invoices.',
-            delete: 'Delete invoice field',
-            deleteConfirmation: 'Are you sure you want to delete this invoice field?',
-            findInvoiceField: 'Find invoice field',
-            nameInputSubtitle: 'Choose a name for the invoice field.',
-            typeInputSubtitle: 'Choose what type of invoice field to use.',
-            initialValueInputSubtitle: 'Enter a starting value to show in the invoice field.',
-            listValuesInputSubtitle: 'These values will appear in your invoice field dropdown. Enabled values can be selected by members.',
-            listInputSubtitle: 'These values will appear in your invoice field list. Enabled values can be selected by members.',
-            emptyInvoiceFieldsValues: {
-                title: 'No list values yet',
-                subtitle: 'Add custom values to appear on invoices.',
-            },
-            existingInvoiceFieldNameError: 'An invoice field with this name already exists',
-            invoiceFieldNameRequiredError: 'Please enter an invoice field name',
-            invoiceFieldTypeRequiredError: 'Please choose an invoice field type',
-            invoiceFieldInitialValueRequiredError: 'Please choose an invoice field initial value',
-            addField: 'Add field',
-        },
         tags: {
             tagName: 'Tag name',
             requiresTag: 'Members must tag all expenses',
@@ -6321,13 +6334,17 @@ const translations = {
                 other: 'Make members',
             }),
             makeAdmin: () => ({
-                one: 'Make admin',
-                other: 'Make admins',
+                one: 'Make workspace admin',
+                other: 'Make workspace admins',
             }),
             makeAuditor: () => ({
                 one: 'Make auditor',
                 other: 'Make auditors',
             }),
+            makeCardAdmin: () => ({
+                one: 'Make card admin',
+                other: 'Make card admins',
+            }),
             selectAll: 'Select all',
             error: {
                 genericAdd: 'There was a problem adding this workspace member',
@@ -6340,7 +6357,8 @@ const translations = {
             configureHRSync: (providerName: string) => `Configure ${providerName} sync.`,
             syncWithHR: (providerName: string) => `Sync with ${providerName}`,
             allMembers: 'All members',
-            admins: 'Admins',
+            admins: 'Workspace Admins',
+            cardAdmins: 'Card Admins',
             approvers: 'Approvers',
             auditors: 'Auditors',
             emptyRoleFilter: {
@@ -6863,6 +6881,10 @@ const translations = {
             }),
             enableRate: 'Enable rate',
             status: 'Status',
+            statusActive: 'Active',
+            statusFuture: 'Future',
+            statusExpired: 'Expired',
+            statusInactive: 'Inactive',
             unit: 'Unit',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Taxes must be enabled on the workspace to use this feature. Head over to <a href="#">More features</a> to make that change.</muted-text>',
@@ -6975,12 +6997,6 @@ const translations = {
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Report fields are only available on the Control plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Invoice fields',
-                description: `Invoice fields let you include extra invoice-level details on invoices.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Invoice fields are only available on the Control plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Enjoy automated syncing and reduce manual entries with the Expensify + NetSuite integration. Gain in-depth, realtime financial insights with native and custom segment support, including project and customer mapping.`,
@@ -7104,11 +7120,11 @@ const translations = {
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Distance rates are available on the Collect plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditor',
-                description: 'Auditors get read-only access to all reports for full visibility and compliance monitoring.',
+            controlPolicyRoles: {
+                title: 'Control policy roles',
+                description: 'Use specialized roles like Auditor and Card Admin to grant members access only to what they need.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Auditors are only available on the Control plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
+                    `<muted-text>Specialized workspace roles are only available on the Control plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
             },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Multiple approval levels',
@@ -7497,6 +7513,7 @@ const translations = {
                 deleteRuleConfirmation: 'Are you sure you want to delete this rule?',
                 describeRuleTitle: 'Describe your rule',
                 describeRuleSubtitle: 'Describe your rule and Concierge will build it',
+                disclaimer: 'AI agents can make mistakes.',
             },
         },
         planTypePage: {
@@ -7736,16 +7753,12 @@ const translations = {
         updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
             return `${newValue ? 'enabled' : 'disabled'} the ${customUnitName} rate "${customUnitRateName}"`;
         },
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `updated start date of "${rateName}" rate to ${newDate} (previously ${oldDate})` : `set start date of "${rateName}" rate to ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `updated end date of "${rateName}" rate to ${newDate} (previously ${oldDate})` : `set end date of "${rateName}" rate to ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `updated start and end date of "${rateName}" rate to ${newStartDate} - ${newEndDate} (previously ${oldStartDate} - ${oldEndDate})`
-                : `set start and end date of "${rateName}" rate to ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `removed start date from "${rateName}" rate (previously ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `removed end date from "${rateName}" rate (previously ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `updated the distance rate "${rateName}" to apply ${newDateRange} (previously ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `from ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `until ${date}`,
+        customUnitRateDateRangeAllDates: () => `for all dates`,
         updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `set the default value of report field "${fieldName}" to "${defaultValue}"`,
         addedReportFieldOption: (fieldName: string, optionName: string) => `added the option "${optionName}" to the report field "${fieldName}"`,
         removedReportFieldOption: (fieldName: string, optionName: string) => `removed the option "${optionName}" from the report field "${fieldName}"`,
@@ -8029,6 +8042,8 @@ const translations = {
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `changed the auto-pay approved reports threshold to "${newLimit}" (previously "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'removed the auto-pay approved reports threshold',
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `changed the "${categoryName}" category default tax rate to "${newTax}" (previously "${oldTax}")`,
         updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
             `changed the default spend category for "${mccGroupName}" to "${newCategory}" (previously "${oldCategory}")`,
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
@@ -8572,8 +8587,11 @@ const translations = {
                     `The ${feedName} connection is broken. To restore card imports, <a href='${workspaceCompanyCardRoute}'>log into your bank</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `the Plaid connection to your business bank account is broken. Please <a href='${walletRoute}'>reconnect your bank account ${maskedAccountNumber}</a> so you can continue to use your Expensify Cards.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} joined via the workspace invite link` : `added ${email} as ${role === 'member' ? 'a' : 'an'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'a';
+                    return didJoinPolicy ? `${email} joined via the workspace invite link` : `added ${email} as ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `updated the role of ${email} to ${newRole} (previously ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
@@ -9463,6 +9481,11 @@ const translations = {
         },
         removeCopilot: 'Remove copilot',
         removeCopilotConfirmation: 'Are you sure you want to remove this copilot?',
+        removeCopilotAccess: 'Remove my copilot access',
+        removeCopilotAccessTitle: 'Remove copilot access?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Are you sure you want to remove your copilot access to ${delegatorName}'s Expensify account? This action cannot be undone.`,
+        removeCopilotAccessConfirm: 'Remove access',
         changeAccessLevel: 'Change access level',
         makeSureItIsYou: "Let's make sure it's you",
         enterMagicCode: (contactMethod: string) => `Please enter the magic code sent to ${contactMethod} to add a copilot. It should arrive within a minute or two.`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index dcdb87c44509..be753ba8c002 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -14,7 +14,7 @@ import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
 import type en from './en';
-import type {ConciergeBrokenCardConnectionParams, PaidElsewhereParams, UnsupportedFormulaValueErrorParams} from './params';
+import type {ConciergeBrokenCardConnectionParams, PaidElsewhereParams, RemoveCopilotAccessConfirmationParams, UnsupportedFormulaValueErrorParams} from './params';
 import type {TranslationDeepObject} from './types';
 
 const translations: TranslationDeepObject<typeof en> = {
@@ -63,7 +63,9 @@ const translations: TranslationDeepObject<typeof en> = {
         save: 'Guardar',
         saveChanges: 'Guardar cambios',
         submit: 'Enviar',
+        markAsDone: 'Marcar como listo',
         submitted: 'Enviado',
+        markedAsDoneStatus: 'Marcado como listo',
         rotate: 'Rotar',
         zoom: 'Zoom',
         password: 'Contraseña',
@@ -249,7 +251,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Descripción',
         title: 'Título',
         assignee: 'Asignado a',
-        createdBy: 'Creado por',
         with: 'con',
         shareCode: 'Compartir código',
         share: 'Compartir',
@@ -270,6 +271,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Comerciante',
         change: 'Cambio',
         category: 'Categoría',
+        vendor: 'Proveedor',
         report: 'Informe',
         billable: 'Facturable',
         nonBillable: 'No facturable',
@@ -312,6 +314,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Encuentra un chat usando el botón',
             subtitleText2: 'o crea algo usando el botón',
             subtitleText3: '.',
+            noUnreadChats: 'No hay chats sin leer',
+            noTodos: 'No hay tareas pendientes',
+            caughtUp: 'Te has puesto al día. ¡Bien hecho!',
+            seeAllChats: 'Ver todos los chats',
         },
         businessName: 'Nombre de la empresa',
         clear: 'Borrar',
@@ -801,6 +807,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users) => `Este chat es con ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName, submitterDisplayName) =>
             `Aquí es donde <strong>${submitterDisplayName}</strong> enviará los gastos al espacio de trabajo <strong>${workspaceName}</strong>. Solo usa el botón +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Aquí es donde harás seguimiento de los gastos',
         beginningOfChatHistorySelfDM: 'Este es tu espacio personal. Úsalo para notas, tareas, borradores y recordatorios.',
         beginningOfChatHistorySystemDM: '¡Bienvenido! Vamos a configurar tu cuenta.',
         chatWithAccountManager: 'Chatea con tu gestor de cuenta aquí',
@@ -916,7 +923,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 cta: 'Revisar',
             },
             validateAccount: {
-                title: 'Valida tu cuenta para continuar usando Expensify',
+                title: 'Valida tu cuenta',
                 subtitle: 'Cuenta',
                 cta: 'Validar',
             },
@@ -996,6 +1003,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Todo al día',
                 f1FlagsDescription: 'Has completado todas las tareas pendientes.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Revisa ${count} ${count === 1 ? 'gasto' : 'gastos'}`,
         },
         gettingStartedSection: {
             title: 'Primeros pasos',
@@ -1312,6 +1320,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount) => `Enviar factura de ${amount}`,
         expenseAmount: (formattedAmount, comment) => `${formattedAmount}${comment ? ` para ${comment}` : ''}`,
         submitted: (memo) => `enviado${memo ? `, dijo ${memo}` : ''}`,
+        markedAsDone: (memo) => `marcado como listo${memo ? `, dijo ${memo}` : ''}`,
         automaticallySubmitted: `envió mediante <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">retrasar envíos</a>`,
         queuedToSubmitViaDEW: 'en cola para enviar a través del flujo de aprobación personalizado',
         failedToAutoSubmitViaDEW: (reason: string) => `no ha podido enviar este informe mediante <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">retrasar envíos</a>. ${reason}`,
@@ -1531,6 +1540,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'eliminó',
         transactionPending: 'Transacción pendiente.',
         chooseARate: 'Selecciona una tasa de reembolso por milla o kilómetro para el espacio de trabajo',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} a ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Válido desde ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Válido hasta ${endDate}`,
         unapprove: 'Desaprobar',
         unapproveReport: 'Anular la aprobación del informe',
         headsUp: 'Atención!',
@@ -1631,6 +1643,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Corrige el error de la tasa y vuelve a intentarlo.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explicar<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge asoció este gasto con <strong>${vendorName}</strong>`,
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'marcó el gasto como "reembolsable"' : 'marcó el gasto como "no reembolsable"'),
             billable: (value: boolean) => (value ? 'marcó el gasto como "facturable"' : 'marcó el gasto como "no facturable"'),
@@ -1739,6 +1752,17 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador envíe los gastos.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (actor, actorType, _eta, _etaType) => {
+                // eslint-disable-next-line default-case
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Esperando a que <strong>tú</strong> lo marques como listo.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Esperando a que <strong>${actor}</strong> lo marque como listo.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Esperando a que un administrador lo marque como listo.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_actor, _actorType, _eta, _etaType) => `¡No se requiere ninguna acción adicional!`,
             [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (actor, actorType, _eta, _etaType) => {
                 switch (actorType) {
@@ -2116,12 +2140,16 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Informar de actividad sospechosa',
         lockAccount: 'Bloquear cuenta',
+        lockMyAccount: 'Bloquear mi cuenta',
         unlockAccount: 'Desbloquear cuenta',
         unlockTitle: 'Hemos recibido tu solicitud',
         unlockDescription: 'Revisaremos la cuenta para verificar que sea seguro desbloquearla y nos comunicaremos a través de Concierge si tenemos alguna pregunta.',
-        compromisedDescription:
-            '¿Notas algo extraño en tu cuenta? Informarlo bloqueará tu cuenta de inmediato, detendrá nuevas transacciones con la Tarjeta Expensify y evitará cualquier cambio en la cuenta.',
-        domainAdminsDescription: 'Para administradores de dominio: Esto también detiene toda la actividad de la Tarjeta Expensify y las acciones administrativas en tus dominios.',
+        findYourSituation: '¡La mayoría de los problemas no requieren bloquear tu cuenta! Busca tu situación a continuación:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Tarjeta perdida o cargos desconocidos</a>: Cancela tu tarjeta y contacta con Concierge para disputar transacciones desconocidas.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Acceso no autorizado a la cuenta</a>: Bloquea tu cuenta abajo. Esto bloquea nuevas transacciones con la Tarjeta Expensify, pedidos de tarjetas y cambios en la cuenta. Si eres administrador de dominio, esto también pausa toda la actividad de tarjetas y las acciones de administrador en todo el dominio.',
+        securityTeamFollowUp: 'Nuestro equipo de seguridad hará un seguimiento desde <a href="mailto:risk@expensify.com">risk@expensify.com</a> después del bloqueo.',
         areYouSure: '¿Estás seguro de que deseas bloquear tu cuenta de Expensify?',
         onceLocked: 'Una vez bloqueada, tu cuenta estará restringida hasta que se solicite el desbloqueo y se realice una revisión de seguridad.',
     },
@@ -2474,13 +2502,10 @@ ${amount} para ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `gastos de ${members}, y el aprobador es ${approvers}`,
         addApprovalButton: 'Añadir flujo de aprobación',
         editWorkflowAction: 'Editar',
-        addAgentAction: 'Añadir agente',
         findWorkflow: 'Buscar flujo de trabajo',
         addApprovalTip: 'Este flujo de trabajo por defecto se aplica a todos los miembros, a menos que exista un flujo de trabajo más específico.',
         approver: 'Aprobador',
         addApprovalsDescription: 'Requiere una aprobación adicional antes de autorizar un pago.',
-        automateApprovalsWithAgentsTitle: 'Automatiza las aprobaciones con agentes',
-        automateApprovalsWithAgentsSubtitle: 'Añade el agente de abajo al flujo de trabajo para automatizar las aprobaciones.',
         configureViaHR: ({provider}: {provider: string}) => `Configurar mediante ${provider}.`,
         hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
             `Las aprobaciones se gestionan mediante tu integración de ${provider}. Para actualizar tu flujo de aprobación, ve a la configuración de conexión de ${provider}.`,
@@ -2779,6 +2804,12 @@ ${amount} para ${merchant} - ${date}`,
             },
         },
     },
+    focusModeUpdateModal: {
+        title: '¡Bienvenido al modo #focus!',
+        prompt: (priorityModePageUrl: string) =>
+            `Mantente al tanto de todo viendo solo los chats no leídos o los chats que necesitan tu atención. No te preocupes, puedes cambiarlo en cualquier momento en los <a href="${priorityModePageUrl}">ajustes</a>.`,
+    },
+    inboxTabs: {all: 'Todo', todo: 'Tareas pendientes', unread: 'No leído'},
     reportDetailsPage: {
         goToRoom: 'Ir a la sala',
         inWorkspace: (policyName) => `en ${policyName}`,
@@ -3344,11 +3375,6 @@ ${amount} para ${merchant} - ${date}`,
         month: 'Mes',
         selectMonth: 'Por favor, selecciona un mes',
     },
-    focusModeUpdateModal: {
-        title: '¡Bienvenido al modo #concentración!',
-        prompt: (priorityModePageUrl) =>
-            `Mantente al tanto de todo viendo sólo los chats no leídos o los que necesitan tu atención. No te preocupes, puedes cambiar el ajuste en cualquier momento desde la <a href="${priorityModePageUrl}">configuración</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'El chat que estás buscando no se pudo encontrar.',
         getMeOutOfHere: 'Sácame de aquí',
@@ -4019,27 +4045,30 @@ ${amount} para ${merchant} - ${date}`,
         verificationFailed: 'La verificación falló, por lo que necesitaremos documentos adicionales para verificarte a ti y a tu empresa',
         taxIDVerification: 'Verificación del ID fiscal',
         taxIDVerificationDescription: dedent(`
-        Por favor, sube uno de los siguientes archivos:
-        • Carta de asignación de TIN/EIN del IRS
-        • Confirmación de solicitud de TIN/EIN del IRS (normalmente indica "Congratulations! The EIN has been successfully assigned")
-        • Carta de exención fiscal del IRS que incluya el nombre de la empresa y el EIN`),
+            Por favor, sube uno de los siguientes archivos:
+            • Carta de asignación de TIN/EIN del IRS
+            • Confirmación de solicitud de TIN/EIN del IRS (normalmente indica "Congratulations! The EIN has been successfully assigned")
+            • Carta de exención fiscal del IRS que incluya el nombre de la empresa y el EIN
+        `),
         nameChangeDocument: 'Documento de cambio de nombre',
         nameChangeDocumentDescription: 'Si el nombre de tu empresa cambió desde que solicitaste el TIN/EIN, necesitamos este documento para verificar el número de ID fiscal proporcionado',
         companyAddressVerification: 'Verificación de la dirección de la empresa',
         companyAddressVerificationDescription: dedent(`
-        Por favor, sube uno de los siguientes archivos:
-        • Factura reciente de servicios públicos con nombre y dirección de la empresa
-        • Estado de cuenta bancario con nombre y dirección de la empresa
-        • Contrato de arrendamiento vigente con página de firmas que muestre el nombre y la dirección actual de la empresa
-        • Estado de seguro con nombre y dirección de la empresa
-        • Documento de asignación de TIN con nombre y dirección de la empresa`),
+            Por favor, sube uno de los siguientes archivos:
+            • Factura reciente de servicios públicos con nombre y dirección de la empresa
+            • Estado de cuenta bancario con nombre y dirección de la empresa
+            • Contrato de arrendamiento vigente con página de firmas que muestre el nombre y la dirección actual de la empresa
+            • Estado de seguro con nombre y dirección de la empresa
+            • Documento de asignación de TIN con nombre y dirección de la empresa
+        `),
         userAddressVerification: 'Verificación de dirección',
         userAddressVerificationDescription: dedent(`
-        Por favor, sube uno de los siguientes archivos:
-        • Tarjeta de registro de votante
-        • Licencia de conducir
-        • Estado de cuenta bancario
-        • Factura de servicios públicos`),
+            Por favor, sube uno de los siguientes archivos:
+            • Tarjeta de registro de votante
+            • Licencia de conducir
+            • Estado de cuenta bancario
+            • Factura de servicios públicos
+        `),
         userDOBVerification: 'Verificación de fecha de nacimiento',
         userDOBVerificationDescription: 'Por favor, sube una identificación emitida en EE. UU.',
         finishViaChat: 'Finalizar por chat',
@@ -4222,7 +4251,6 @@ ${amount} para ${merchant} - ${date}`,
             customFieldHint: 'Añade una codificación personalizada que se aplique a todos los gastos de este miembro.',
             reports: 'Informes',
             reportFields: 'Campos de informe',
-            invoiceFields: 'Campos de factura',
             reportTitle: 'El título del informe.',
             taxes: 'Impuestos',
             bills: 'Pagar facturas',
@@ -4315,13 +4343,13 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrador';
+                        return 'Administrador del espacio de trabajo';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.EDITOR:
                         return 'Editor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Administrador de tarjeta';
+                        return 'Administrador de tarjetas';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'Administrador de personas';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
@@ -5865,29 +5893,6 @@ ${amount} para ${merchant} - ${date}`,
             reportFieldInitialValueRequiredError: 'Elige un valor inicial de campo de informe',
             genericFailureMessage: 'Se ha producido un error al actualizar el campo de informe. Por favor, inténtalo de nuevo.',
         },
-        invoiceFields: {
-            subtitle: 'Los campos de factura pueden ayudarte cuando quieras incluir información adicional.',
-            importedFromAccountingSoftware: 'Campos de factura importados desde',
-            disableInvoiceFields: 'Desactivar campos de factura',
-            disableInvoiceFieldsConfirmation: '¿Estás seguro? Los campos de factura se desactivarán en las facturas.',
-            delete: 'Eliminar campo de factura',
-            deleteConfirmation: '¿Seguro que deseas eliminar este campo de factura?',
-            findInvoiceField: 'Buscar campo de factura',
-            nameInputSubtitle: 'Elige un nombre para el campo de factura.',
-            typeInputSubtitle: 'Elige qué tipo de campo de factura usar.',
-            initialValueInputSubtitle: 'Ingresa un valor inicial para mostrar en el campo de factura.',
-            listValuesInputSubtitle: 'Estos valores aparecerán en el menú desplegable del campo de factura. Los miembros pueden seleccionar los valores activados.',
-            listInputSubtitle: 'Estos valores aparecerán en la lista del campo de factura. Los miembros pueden seleccionar los valores activados.',
-            emptyInvoiceFieldsValues: {
-                title: 'Aún no hay valores de lista',
-                subtitle: 'Agrega valores personalizados para que aparezcan en las facturas.',
-            },
-            existingInvoiceFieldNameError: 'Ya existe un campo de factura con este nombre',
-            invoiceFieldNameRequiredError: 'Ingresa un nombre para el campo de factura',
-            invoiceFieldTypeRequiredError: 'Elige un tipo de campo de factura',
-            invoiceFieldInitialValueRequiredError: 'Elige un valor inicial para el campo de factura',
-            addField: 'Añadir campo',
-        },
         tags: {
             tagName: 'Nombre de etiqueta',
             requiresTag: 'Los miembros deben etiquetar todos los gastos',
@@ -6110,8 +6115,8 @@ ${amount} para ${merchant} - ${date}`,
                 other: 'Convertir en miembros',
             }),
             makeAdmin: () => ({
-                one: 'Hacer administrador',
-                other: 'Convertir en administradores',
+                one: 'Hacer administrador del espacio de trabajo',
+                other: 'Convertir en administradores del espacio de trabajo',
             }),
             makeAuditor: () => ({
                 one: 'Convertir en auditor',
@@ -6127,7 +6132,7 @@ ${amount} para ${merchant} - ${date}`,
             invitedBySecondaryLogin: (secondaryLogin) => `Agregado por nombre de usuario secundario ${secondaryLogin}.`,
             workspaceMembersCount: (count) => `Total de miembros del espacio de trabajo: ${count}`,
             allMembers: 'Todos los miembros',
-            admins: 'Administradores',
+            admins: 'Administradores del espacio de trabajo',
             approvers: 'Aprobadores',
             auditors: 'Auditores',
             emptyRoleFilter: {
@@ -6149,6 +6154,8 @@ ${amount} para ${merchant} - ${date}`,
                 `${memberName} tiene un informe en proceso pendiente de acción. Pídele que complete la acción requerida antes de eliminarlo del espacio de trabajo.`,
             configureHRSync: (providerName: string) => `Configura la sincronización de ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar con ${providerName}`,
+            makeCardAdmin: () => ({one: 'Hacer administrador de tarjetas', other: 'Hacer administradores de tarjetas'}),
+            cardAdmins: 'Administradores de tarjetas',
         },
         accounting: {
             settings: 'configuración',
@@ -6648,6 +6655,10 @@ ${amount} para ${merchant} - ${date}`,
             }),
             enableRate: 'Activar tasa',
             status: 'Estado',
+            statusActive: 'Activo',
+            statusFuture: 'Futuro',
+            statusExpired: 'Expirado',
+            statusInactive: 'Inactivo',
             unit: 'Unidad',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Los impuestos deben estar activados en el área de trabajo para poder utilizar esta función. Dirígete a <a href="#">Más funcionalidades</a> para hacer ese cambio.</muted-text>',
@@ -6784,12 +6795,6 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Los campos de informe sólo están disponibles en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Campos de factura',
-                description: `Los campos de factura te permiten incluir detalles adicionales a nivel de factura.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>Los campos de factura sólo están disponibles en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Disfruta de la sincronización automática y reduce las entradas manuales con la integración Expensify + NetSuite. Obtén información financiera en profundidad y en tiempo real con la compatibilidad nativa y personalizada con segmentos, incluida la asignación de proyectos y clientes.`,
@@ -6914,12 +6919,6 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Las tasas de distancia están disponibles en el plan Recopilar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditor',
-                description: 'Los auditores tienen acceso de lectura a todos los informes para una visibilidad completa y la supervisión del cumplimiento.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Los auditores solo están disponibles con el plan Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Múltiples niveles de aprobación',
                 description:
@@ -6993,6 +6992,12 @@ ${amount} para ${merchant} - ${date}`,
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt:
                     'Su empresa ha restringido la creación de espacios de trabajo. Por favor, contacte a un administrador para obtener ayuda.',
             },
+            controlPolicyRoles: {
+                title: 'Controlar roles de la política',
+                description: 'Usa roles especializados como Auditor y Administrador de tarjetas para dar a los miembros acceso solo a lo que necesitan.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Los roles especializados del espacio de trabajo solo están disponibles en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -7291,6 +7296,7 @@ ${amount} para ${merchant} - ${date}`,
                 editRuleTitle: 'Editar regla',
                 deleteRule: 'Eliminar regla',
                 deleteRuleConfirmation: '¿Seguro que quieres eliminar esta regla?',
+                disclaimer: 'Los agentes de IA pueden cometer errores.',
             },
         },
         emptyDomain: {
@@ -7779,6 +7785,8 @@ ${amount} para ${merchant} - ${date}`,
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `cambió el umbral de autopago de informes aprobados a "${newLimit}" (previamente "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'eliminó el umbral de autopago de informes aprobados',
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `cambió la tasa de impuesto predeterminada de la categoría "${categoryName}" a "${newTax}" (previamente "${oldTax}")`,
         updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
             `cambió la categoría de gasto predeterminada para "${mccGroupName}" a "${newCategory}" (previamente "${oldCategory}")`,
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
@@ -7873,18 +7881,12 @@ ${amount} para ${merchant} - ${date}`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `añadió la tasa "${rateName}" de ${rateValue}, válida hasta ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `añadió la tasa "${rateName}" de ${rateValue}, válida del ${startDate} al ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `actualizó la fecha de inicio de la tasa "${rateName}" a ${newDate} (previamente ${oldDate})` : `establecer la fecha de inicio de la tasa "${rateName}" a ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate
-                ? `actualizó la fecha de finalización de la tasa "${rateName}" a ${newDate} (previamente ${oldDate})`
-                : `establecer la fecha de finalización de la tasa "${rateName}" en ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `actualizó la fecha de inicio y fin de la tasa "${rateName}" a ${newStartDate} - ${newEndDate} (previamente ${oldStartDate} - ${oldEndDate})`
-                : `establece la fecha de inicio y fin de la tasa "${rateName}" a ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `se eliminó la fecha de inicio de la tasa "${rateName}" (previamente ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `eliminó la fecha de finalización de la tasa «${rateName}» (previamente ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `actualizó la tasa de distancia «${rateName}» para aplicar ${newDateRange} (previamente ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `desde ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `hasta ${date}`,
+        customUnitRateDateRangeAllDates: () => `para todas las fechas`,
     },
     roomMembersPage: {
         memberNotFound: 'Miembro no encontrado.',
@@ -8322,8 +8324,11 @@ ${amount} para ${merchant} - ${date}`,
                     `La conexión ${feedName} está rota. Para restaurar las importaciones de tarjetas, <a href='${workspaceCompanyCardRoute}'>inicia sesión en tu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `se añadió ${email} como ${role === 'member' ? 'a' : 'a un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `añadió ${email} como ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}) => `actualizó el rol ${email} a ${newRole} (previamente ${currentRole})`,
                 updatedCustomField1: (email, newValue, previousValue) => {
                     if (!newValue) {
@@ -9582,6 +9587,11 @@ ${amount} para ${merchant} - ${date}`,
         },
         removeCopilot: 'Eliminar copiloto',
         removeCopilotConfirmation: '¿Estás seguro de que quieres eliminar este copiloto?',
+        removeCopilotAccess: 'Eliminar mi acceso de copiloto',
+        removeCopilotAccessTitle: '¿Eliminar acceso de copiloto?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `¿Estás seguro de que quieres eliminar tu acceso de copiloto a la cuenta de Expensify de ${delegatorName}? Esta acción no se puede deshacer.`,
+        removeCopilotAccessConfirm: 'Eliminar acceso',
         changeAccessLevel: 'Cambiar nivel de acceso',
         makeSureItIsYou: 'Vamos a asegurarnos de que eres tú',
         enterMagicCode: (contactMethod) => `Por favor, introduce el código mágico enviado a ${contactMethod} para agregar un copiloto. Debería llegar en un par de minutos.`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index cae4d17519d5..bfef9ba65a21 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1,7 +1,6 @@
 /**
  *   _____                      __         __
  *  / ___/__ ___  ___ _______ _/ /____ ___/ /
- * / (_ / -_) _ \/ -_) __/ _ \`/ __/ -_) _  /
  * \___/\__/_//_/\__/_/  \_,_/\__/\__/\_,_/
  *
  * This file was automatically generated. Please consider these alternatives before manually editing it:
@@ -40,6 +39,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -108,7 +108,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Sélection multiple',
         saveChanges: 'Enregistrer les modifications',
         submit: 'Soumettre',
+        markAsDone: 'Marquer comme terminé',
         submitted: 'Soumis',
+        markedAsDoneStatus: 'Marqué comme terminé',
         rotate: 'Pivoter',
         zoom: 'Zoom',
         password: 'Mot de passe',
@@ -293,7 +295,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Description',
         title: 'Titre',
         assignee: 'Attribué',
-        createdBy: 'Créé par',
         with: 'avec',
         shareCode: 'Partager le code',
         share: 'Partager',
@@ -314,6 +315,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Commerçant',
         change: 'Modifier',
         category: 'Catégorie',
+        vendor: 'Fournisseur',
         report: 'Note de frais',
         billable: 'Facturable',
         nonBillable: 'Non refacturable',
@@ -355,6 +357,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Recherchez une discussion à l’aide de la',
             subtitleText2: 'bouton ci-dessus, ou créez quelque chose en utilisant le',
             subtitleText3: 'bouton ci-dessous.',
+            noUnreadChats: 'Aucune discussion non lue',
+            noTodos: 'Aucune tâche à faire',
+            caughtUp: 'Vous êtes à jour. Bravo !',
+            seeAllChats: 'Voir toutes les discussions',
         },
         businessName: 'Nom de l’entreprise',
         clear: 'Effacer',
@@ -856,6 +862,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Cette discussion est avec ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `C’est ici que <strong>${submitterDisplayName}</strong> soumettra des dépenses à <strong>${workspaceName}</strong>. Utilisez simplement le bouton +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'C\u2019est ici que vous suivrez vos dépenses',
         beginningOfChatHistorySelfDM: 'Ceci est votre espace personnel. Utilisez-le pour vos notes, tâches, brouillons et rappels.',
         beginningOfChatHistorySystemDM: 'Bienvenue ! Procédons à la configuration.',
         chatWithAccountManager: 'Discutez avec votre gestionnaire de compte ici',
@@ -961,7 +968,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Réparer la connexion de la carte personnelle ${cardName}` : 'Corriger la connexion de la carte personnelle'),
                 subtitle: 'Portefeuille',
             },
-            validateAccount: {title: 'Validez votre compte pour continuer à utiliser Expensify', subtitle: 'Compte', cta: 'Valider'},
+            validateAccount: {title: 'Validez votre compte', subtitle: 'Compte', cta: 'Valider'},
             fixFailedBilling: {title: 'Nous n’avons pas pu débiter votre carte enregistrée', subtitle: 'Abonnement'},
             unlockBankAccount: {
                 workspaceTitle: 'Votre compte bancaire professionnel a été verrouillé',
@@ -1016,6 +1023,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Tout est à jour',
                 f1FlagsDescription: 'Vous avez terminé toutes les tâches en cours.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Examiner ${count} ${count === 1 ? 'dépense' : 'dépenses'}`,
         },
         upcomingTravel: 'Voyages à venir',
         upcomingTravelSection: {
@@ -1354,6 +1362,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Envoyer la facture de ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `pour ${comment}` : ''}`,
         submitted: (memo?: string) => `soumis${memo ? `, indiquant « ${memo} »` : ''}`,
+        markedAsDone: (memo?: string) => `marqué comme terminé${memo ? `, en indiquant « ${memo} »` : ''}`,
         automaticallySubmitted: `soumis via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">soumissions différées</a>`,
         queuedToSubmitViaDEW: 'en file d’attente pour être soumis via le circuit d’approbation personnalisé',
         queuedToApproveViaDEW: 'mis en file d’attente pour approbation via un processus d’approbation personnalisé',
@@ -1570,6 +1579,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'supprimé',
         transactionPending: 'Transaction en attente.',
         chooseARate: 'Sélectionnez un taux de remboursement par mile ou kilomètre pour l’espace de travail',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} au ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Valide à partir du ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Valide jusqu’au ${endDate}`,
         unapprove: 'Annuler l’approbation',
         unapproveReport: 'Retirer l’approbation de la note de frais',
         headsUp: 'Attention !',
@@ -1671,6 +1683,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Corrigez l’erreur de taux et réessayez.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Expliquer<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge a associé cette dépense au fournisseur <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError:
             'Vous ne pouvez pas dupliquer les indemnités journalières entre plusieurs espaces de travail, car les taux peuvent différer d’un espace de travail à l’autre.',
         rulesModifiedFields: {
@@ -1800,6 +1813,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `En attente qu’un administrateur soumette des dépenses.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `En attente que <strong>vous</strong> marquiez ceci comme terminé.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `En attente que <strong>${actor}</strong> marque ceci comme terminé.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `En attente qu'un administrateur marque ceci comme terminé.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
@@ -2233,11 +2261,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Signaler une activité suspecte',
         lockAccount: 'Verrouiller le compte',
+        lockMyAccount: 'Verrouiller mon compte',
         unlockAccount: 'Déverrouiller le compte',
-        compromisedDescription:
-            'Vous remarquez quelque chose d’inhabituel sur votre compte ? Le signaler bloquera immédiatement votre compte, empêchera les nouvelles transactions avec la Carte Expensify et interdira toute modification du compte.',
-        domainAdminsDescription:
-            "Pour les administrateurs de domaine : cela met également en pause toute l'activité de Carte Expensify et toutes les actions d'administration sur l’ensemble de votre (vos) domaine(s).",
+        findYourSituation: 'La plupart des problèmes ne nécessitent pas de verrouiller votre compte ! Trouvez votre situation ci-dessous :',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Carte perdue ou frais inconnus</a> : Annulez votre carte et contactez Concierge pour contester les transactions inconnues.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Accès non autorisé au compte</a> : Verrouillez votre compte ci-dessous. Cela bloque les nouvelles transactions Carte Expensify, les commandes de carte et les modifications de compte. Si vous êtes administrateur de domaine, cela met également en pause toute l’activité de carte au niveau du domaine et les actions des administrateurs.',
+        securityTeamFollowUp: 'Notre équipe de sécurité effectuera un suivi depuis <a href="mailto:risk@expensify.com">risk@expensify.com</a> après le verrouillage.',
         areYouSure: 'Voulez-vous vraiment verrouiller votre compte Expensify ?',
         onceLocked: 'Une fois verrouillé, votre compte sera restreint en attendant une demande de déverrouillage et un contrôle de sécurité',
         unlockTitle: 'Nous avons bien reçu votre demande',
@@ -2607,13 +2638,10 @@ ${amount} pour ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `dépenses de ${members}, et l'approbateur est ${approvers}`,
         addApprovalButton: 'Ajouter un workflow d’approbation',
         editWorkflowAction: 'Modifier',
-        addAgentAction: 'Ajouter un agent',
         findWorkflow: 'Rechercher un flux de travail',
         addApprovalTip: 'Ce workflow par défaut s’applique à tous les membres, sauf si un workflow plus spécifique existe.',
         approver: 'Approbateur',
         addApprovalsDescription: 'Exiger une approbation supplémentaire avant d’autoriser un paiement.',
-        automateApprovalsWithAgentsTitle: 'Automatisez les approbations avec des agents',
-        automateApprovalsWithAgentsSubtitle: 'Ajoutez l’agent ci-dessous au flux de travail pour automatiser les approbations.',
         makeOrTrackPaymentsTitle: 'Paiements',
         makeOrTrackPaymentsDescription: 'Ajoutez un payeur autorisé pour les paiements effectués dans Expensify ou suivez les paiements effectués ailleurs.',
         customApprovalWorkflowEnabled:
@@ -2909,6 +2937,12 @@ ${amount} pour ${merchant} - ${date}`,
             },
         },
     },
+    focusModeUpdateModal: {
+        title: 'Bienvenue dans le mode #focus !',
+        prompt: (priorityModePageUrl: string) =>
+            `Gardez le contrôle en n’affichant que les discussions non lues ou celles qui nécessitent votre attention. Ne vous inquiétez pas, vous pouvez modifier ce réglage à tout moment dans les <a href="${priorityModePageUrl}">paramètres</a>.`,
+    },
+    inboxTabs: {all: 'Tout', todo: 'Tâches', unread: 'Non lu'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `dans ${policyName}`,
         generatingPDF: 'Générer le PDF',
@@ -3480,11 +3514,6 @@ ${amount} pour ${merchant} - ${date}`,
         year: 'Année',
         selectYear: 'Veuillez sélectionner une année',
     },
-    focusModeUpdateModal: {
-        title: 'Bienvenue en mode #focus !',
-        prompt: (priorityModePageUrl: string) =>
-            `Gardez le contrôle en affichant uniquement les discussions non lues ou celles qui nécessitent votre attention. Ne vous inquiétez pas, vous pouvez modifier ce paramètre à tout moment dans les <a href="${priorityModePageUrl}">paramètres</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'La discussion que vous recherchez est introuvable.',
         getMeOutOfHere: 'Faites-moi sortir d’ici',
@@ -4149,28 +4178,31 @@ ${amount} pour ${merchant} - ${date}`,
         verificationFailed: 'La vérification a échoué, nous aurons donc besoin de documents supplémentaires pour te vérifier ainsi que ton entreprise',
         taxIDVerification: 'Vérification de l’identifiant fiscal',
         taxIDVerificationDescription: dedent(`
-        Veuillez téléverser l’un des fichiers suivants :
-        • Lettre d’attribution TIN/EIN de l’IRS
-        • Confirmation de demande TIN/EIN de l’IRS (indique généralement « Congratulations! The EIN has been successfully assigned »)
-        • Lettre d’exonération fiscale de l’IRS indiquant le nom de l’entreprise et l’EIN`),
+            Veuillez téléverser l’un des fichiers suivants :
+            • Lettre d’attribution TIN/EIN de l’IRS
+            • Confirmation de demande TIN/EIN de l’IRS (indique généralement « Congratulations! The EIN has been successfully assigned »)
+            • Lettre d’exonération fiscale de l’IRS indiquant le nom de l’entreprise et l’EIN
+        `),
         nameChangeDocument: 'Document de changement de nom',
         nameChangeDocumentDescription:
             'Si le nom de ton entreprise a changé depuis la demande du TIN/EIN, ce document est nécessaire pour vérifier le numéro d’identification fiscale fourni',
         companyAddressVerification: 'Vérification de l’adresse de l’entreprise',
         companyAddressVerificationDescription: dedent(`
-        Veuillez téléverser l’un des fichiers suivants :
-        • Facture récente de services publics indiquant le nom et l’adresse de l’entreprise
-        • Relevé bancaire indiquant le nom et l’adresse de l’entreprise
-        • Contrat de location en cours incluant la page de signature avec le nom et l’adresse actuelle de l’entreprise
-        • Attestation d’assurance indiquant le nom et l’adresse de l’entreprise
-        • Document d’attribution TIN indiquant le nom et l’adresse de l’entreprise`),
+            Veuillez téléverser l’un des fichiers suivants :
+            • Facture récente de services publics indiquant le nom et l’adresse de l’entreprise
+            • Relevé bancaire indiquant le nom et l’adresse de l’entreprise
+            • Contrat de location en cours incluant la page de signature avec le nom et l’adresse actuelle de l’entreprise
+            • Attestation d’assurance indiquant le nom et l’adresse de l’entreprise
+            • Document d’attribution TIN indiquant le nom et l’adresse de l’entreprise
+        `),
         userAddressVerification: 'Vérification de l’adresse',
         userAddressVerificationDescription: dedent(`
-        Veuillez téléverser l’un des fichiers suivants :
-        • Carte d’inscription électorale
-        • Permis de conduire
-        • Relevé bancaire
-        • Facture de services publics`),
+            Veuillez téléverser l’un des fichiers suivants :
+            • Carte d’inscription électorale
+            • Permis de conduire
+            • Relevé bancaire
+            • Facture de services publics
+        `),
         userDOBVerification: 'Vérification de la date de naissance',
         userDOBVerificationDescription: 'Veuillez téléverser une pièce d’identité délivrée aux États-Unis',
         finishViaChat: 'Finaliser via le chat',
@@ -4352,7 +4384,6 @@ ${amount} pour ${merchant} - ${date}`,
             customFieldHint: 'Ajoutez un codage personnalisé qui s’applique à toutes les dépenses de ce membre.',
             reports: 'Notes de frais',
             reportFields: 'Champs de note de frais',
-            invoiceFields: 'Champs de facture',
             reportTitle: 'Titre de la note de frais',
             reportField: 'Champ de note de frais',
             taxes: 'Taxes',
@@ -4436,7 +4467,7 @@ ${amount} pour ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrateur';
+                        return 'Administrateur d’espace de travail';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditeur';
                     case CONST.POLICY.ROLE.EDITOR:
@@ -4444,7 +4475,7 @@ ${amount} pour ${merchant} - ${date}`,
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return 'Administrateur de carte';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Administration des personnes';
+                        return 'Admin personnes';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Administrateur des paiements';
                     case CONST.POLICY.ROLE.USER:
@@ -6051,29 +6082,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             reportFieldInitialValueRequiredError: 'Veuillez choisir une valeur initiale pour le champ de note de frais',
             genericFailureMessage: 'Une erreur s’est produite lors de la mise à jour du champ de note de frais. Veuillez réessayer.',
         },
-        invoiceFields: {
-            subtitle: 'Les champs de facture peuvent être utiles lorsque vous souhaitez inclure des informations supplémentaires.',
-            importedFromAccountingSoftware: 'Les champs de facture ci-dessous sont importés depuis votre',
-            disableInvoiceFields: 'Désactiver les champs de facture',
-            disableInvoiceFieldsConfirmation: 'Êtes-vous sûr ? Les champs de facture seront désactivés sur les factures.',
-            delete: 'Supprimer le champ de facture',
-            deleteConfirmation: 'Voulez-vous vraiment supprimer ce champ de facture ?',
-            findInvoiceField: 'Trouver un champ de facture',
-            nameInputSubtitle: 'Choisissez un nom pour le champ de facture.',
-            typeInputSubtitle: 'Choisissez le type de champ de facture à utiliser.',
-            initialValueInputSubtitle: 'Saisissez une valeur de départ à afficher dans le champ de facture.',
-            listValuesInputSubtitle: 'Ces valeurs apparaîtront dans la liste déroulante du champ de facture. Les valeurs activées peuvent être sélectionnées par les membres.',
-            listInputSubtitle: 'Ces valeurs apparaîtront dans la liste du champ de facture. Les valeurs activées peuvent être sélectionnées par les membres.',
-            emptyInvoiceFieldsValues: {
-                title: 'Aucune valeur de liste pour le moment',
-                subtitle: 'Ajoutez des valeurs personnalisées à afficher sur les factures.',
-            },
-            existingInvoiceFieldNameError: 'Un champ de facture portant ce nom existe déjà',
-            invoiceFieldNameRequiredError: 'Veuillez saisir un nom de champ de facture',
-            invoiceFieldTypeRequiredError: 'Veuillez choisir un type de champ de facture',
-            invoiceFieldInitialValueRequiredError: 'Veuillez choisir une valeur initiale de champ de facture',
-            addField: 'Ajouter un champ',
-        },
         tags: {
             tagName: 'Nom du tag',
             requiresTag: 'Les membres doivent taguer toutes les dépenses',
@@ -6296,8 +6304,8 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 other: 'Créer des membres',
             }),
             makeAdmin: () => ({
-                one: 'Nommer administrateur',
-                other: 'Nommer des administrateurs',
+                one: 'Nommer administrateur de l’espace de travail',
+                other: 'Nommer des administrateurs de l’espace de travail',
             }),
             makeAuditor: () => ({
                 one: 'Nommer auditeur',
@@ -6326,12 +6334,14 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} a une note de frais en cours de traitement sur laquelle il doit agir. Veuillez lui demander d’effectuer l’action requise avant de le retirer de l’espace de travail.`,
             allMembers: 'Tous les membres',
-            admins: 'Administrateurs',
+            admins: 'Administrateurs de l’espace de travail',
             approvers: 'Approbateurs',
             auditors: 'Auditeurs',
             emptyRoleFilter: {title: 'Aucun membre ne correspond à ce filtre', subtitle: 'Invitez un membre ou modifiez le filtre ci-dessus.'},
             configureHRSync: (providerName: string) => `Configurer la synchronisation ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchroniser avec ${providerName}`,
+            makeCardAdmin: () => ({one: 'Nommer administrateur de carte', other: 'Nommer des administrateurs de carte'}),
+            cardAdmins: 'Administrateurs de cartes',
         },
         card: {
             getStartedIssuing: 'Commencez par émettre votre première carte virtuelle ou physique.',
@@ -6751,6 +6761,10 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             }),
             enableRate: 'Activer le taux',
             status: 'Statut',
+            statusActive: 'Actif',
+            statusFuture: 'Futur',
+            statusExpired: 'Expiré',
+            statusInactive: 'Inactif',
             unit: 'Unité',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Les taxes doivent être activées sur l’espace de travail pour utiliser cette fonctionnalité. Rendez-vous dans <a href="#">Plus de fonctionnalités</a> pour effectuer cette modification.</muted-text>',
@@ -6879,12 +6893,6 @@ Voulez-vous vraiment les exporter à nouveau ?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Les champs de note de frais sont uniquement disponibles avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Champs de facture',
-                description: `Les champs de facture vous permettent d'inclure des détails supplémentaires au niveau de la facture.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Les champs de facture sont uniquement disponibles avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Profitez de la synchronisation automatisée et réduisez les saisies manuelles grâce à l’intégration Expensify + NetSuite. Obtenez des informations financières détaillées et en temps réel avec la prise en charge des segments natifs et personnalisés, y compris la correspondance des projets et des clients.`,
@@ -6986,12 +6994,6 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Les taux de distance sont disponibles avec l’abonnement Collect, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditeur',
-                description: 'Les auditeurs obtiennent un accès en lecture seule à toutes les notes de frais pour une visibilité complète et le suivi de la conformité.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Les auditeurs ne sont disponibles que dans l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Niveaux d’approbation multiples',
                 description:
@@ -7092,6 +7094,12 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>La facturation est disponible avec les offres Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Contrôler les rôles de politique',
+                description: 'Utilisez des rôles spécialisés comme Auditeur et Administrateur de cartes pour donner aux membres accès uniquement à ce dont ils ont besoin.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Les rôles spécialisés dans l’espace de travail sont uniquement disponibles avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -7418,6 +7426,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 deleteRuleConfirmation: 'Voulez-vous vraiment supprimer cette règle ?',
                 describeRuleTitle: 'Décrivez votre règle',
                 describeRuleSubtitle: 'Décrivez votre règle et Concierge la créera',
+                disclaimer: 'Les agents IA peuvent faire des erreurs.',
             },
         },
         planTypePage: {
@@ -8105,22 +8114,20 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} de ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `a modifié le taux de taxe par défaut de la catégorie « ${categoryName} » en « ${newTax} » (auparavant « ${oldTax} »)`,
         addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `a ajouté le taux « ${rateName} » de ${rateValue}`,
         addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) =>
             `a ajouté le taux « ${rateName} » de ${rateValue}, valable à partir du ${startDate}`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `a ajouté le taux « ${rateName} » de ${rateValue}, valable jusqu’au ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `a ajouté le taux « ${rateName} » de ${rateValue}, valable du ${startDate} au ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `a mis à jour la date de début du taux « ${rateName} » à ${newDate} (auparavant ${oldDate})` : `définir la date de début du taux « ${rateName} » sur ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `a mis à jour la date de fin du taux « ${rateName} » à ${newDate} (auparavant ${oldDate})` : `définir la date de fin du taux « ${rateName} » sur ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `a mis à jour les dates de début et de fin du taux « ${rateName} » en ${newStartDate} - ${newEndDate} (précédemment ${oldStartDate} - ${oldEndDate})`
-                : `définir les dates de début et de fin du taux « ${rateName} » sur ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `a supprimé la date de début du taux « ${rateName} » (précédemment ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `a supprimé la date de fin du taux « ${rateName} » (auparavant ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `a mis à jour le taux kilométrique « ${rateName} » pour s’appliquer à ${newDateRange} (précédemment ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `à partir du ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `jusqu’au ${date}`,
+        customUnitRateDateRangeAllDates: () => `pour toutes les dates`,
     },
     roomMembersPage: {
         memberNotFound: 'Membre introuvable.',
@@ -8561,8 +8568,11 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                     `La connexion ${feedName} est interrompue. Pour rétablir l’importation des cartes, <a href='${workspaceCompanyCardRoute}'>connectez-vous à votre banque</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} en tant que ${role === 'member' ? 'a' : 'un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} en tant que ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `a mis à jour le rôle de ${email} en ${newRole} (précédemment ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
@@ -9458,6 +9468,11 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `En tant que <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copilote</a> pour ${accountOwnerEmail}, vous n’avez pas l’autorisation d’effectuer cette action. Désolé !`,
+        removeCopilotAccess: 'Supprimer mon accès copilote',
+        removeCopilotAccessTitle: "Supprimer l'accès copilote ?",
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Êtes-vous sûr de vouloir supprimer votre accès copilote au compte Expensify de ${delegatorName} ? Cette action est irréversible.`,
+        removeCopilotAccessConfirm: "Supprimer l'accès",
         copilotAccess: 'Accès Copilot',
     },
     debug: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 0fcfffdb73b7..c3c0525786ec 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -108,7 +109,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Selezione multipla',
         saveChanges: 'Salva modifiche',
         submit: 'Invia',
+        markAsDone: 'Segna come completata',
         submitted: 'Inviato',
+        markedAsDoneStatus: 'Contrassegnato come completato',
         rotate: 'Ruota',
         zoom: 'Zoom',
         password: 'Password',
@@ -293,7 +296,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Descrizione',
         title: 'Titolo',
         assignee: 'Assegnatario',
-        createdBy: 'Creato da',
         with: 'con',
         shareCode: 'Condividi codice',
         share: 'Condividi',
@@ -314,6 +316,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Esercente',
         change: 'Modifica',
         category: 'Categoria',
+        vendor: 'Fornitore',
         report: 'Report',
         billable: 'Fatturabile',
         nonBillable: 'Non fatturabile',
@@ -356,6 +359,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Trova una chat usando la',
             subtitleText2: 'pulsante sopra oppure crea qualcosa utilizzando il',
             subtitleText3: 'pulsante qui sotto.',
+            noUnreadChats: 'Nessuna chat non letta',
+            noTodos: 'Nessuna attività da fare',
+            caughtUp: 'Hai gestito tutto. Ben fatto!',
+            seeAllChats: 'Vedi tutte le chat',
         },
         businessName: 'Nome azienda',
         clear: 'Pulisci',
@@ -854,6 +861,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Questa chat è con ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `Qui è dove <strong>${submitterDisplayName}</strong> invierà le spese a <strong>${workspaceName}</strong>. Usa semplicemente il pulsante +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Qui è dove terrai traccia delle spese',
         beginningOfChatHistorySelfDM: 'Questo è il tuo spazio personale. Usalo per note, attività, bozze e promemoria.',
         beginningOfChatHistorySystemDM: 'Benvenuto/a! Procediamo con la configurazione.',
         chatWithAccountManager: 'Chatta qui con il tuo account manager',
@@ -959,7 +967,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Correggi la connessione della carta personale ${cardName}` : 'Correggi connessione carta personale'),
                 subtitle: 'Portafoglio',
             },
-            validateAccount: {title: 'Conferma il tuo account per continuare a usare Expensify', subtitle: 'Account', cta: 'Conferma'},
+            validateAccount: {title: 'Conferma il tuo account', subtitle: 'Account', cta: 'Conferma'},
             fixFailedBilling: {title: 'Non abbiamo potuto addebitare la carta salvata nel profilo', subtitle: 'Abbonamento'},
             unlockBankAccount: {
                 workspaceTitle: 'Il conto bancario della tua azienda è stato bloccato',
@@ -1014,6 +1022,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Tutto a posto',
                 f1FlagsDescription: 'Hai completato tutte le attività in sospeso.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Esamina ${count} ${count === 1 ? 'spesa' : 'spese'}`,
         },
         upcomingTravel: 'Prossimi viaggi',
         upcomingTravelSection: {
@@ -1349,6 +1358,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Invia fattura da ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `per ${comment}` : ''}`,
         submitted: (memo?: string) => `inviato${memo ? `, con nota: ${memo}` : ''}`,
+        markedAsDone: (memo) => `contrassegnata come completata${memo ? `, dicendo ${memo}` : ''}`,
         automaticallySubmitted: `inviato tramite <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">invio posticipato</a>`,
         queuedToSubmitViaDEW: 'in coda per l’invio tramite flusso di approvazione personalizzato',
         queuedToApproveViaDEW: 'in coda per l’approvazione tramite flusso di approvazione personalizzato',
@@ -1564,6 +1574,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'rimosso',
         transactionPending: 'Transazione in sospeso.',
         chooseARate: 'Seleziona una tariffa di rimborso per miglio o chilometro per lo spazio di lavoro',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} al ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Valido dal ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Valido fino al ${endDate}`,
         unapprove: 'Revoca approvazione',
         unapproveReport: 'Annulla approvazione rapporto',
         headsUp: 'Attenzione!',
@@ -1664,6 +1677,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: "Correggi l'errore di tariffa e riprova.",
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Spiega<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge ha associato questa spesa al fornitore <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError: 'Non puoi duplicare le spese di diaria tra diversi spazi di lavoro perché le tariffe potrebbero essere diverse tra gli spazi di lavoro.',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'ha contrassegnato la spesa come "rimborsabile"' : 'ha contrassegnato la spesa come "non rimborsabile"'),
@@ -1792,6 +1806,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `In attesa che un amministratore invii le spese.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `In attesa che <strong>tu</strong> lo segni come completato.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `In attesa che <strong>${actor}</strong> lo segni come completato.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `In attesa che un amministratore lo segni come completato.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
@@ -2225,11 +2254,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Segnala attività sospetta',
         lockAccount: 'Blocca account',
+        lockMyAccount: 'Blocca il mio account',
         unlockAccount: 'Sblocca conto',
-        compromisedDescription:
-            'Hai notato qualcosa di strano nel tuo account? Segnalarlo bloccherà immediatamente il tuo account, fermerà le nuove transazioni con la Carta Expensify e impedirà qualsiasi modifica all’account.',
-        domainAdminsDescription:
-            'Per gli amministratori di dominio: questo mette in pausa anche tutta l’attività della Carta Expensify e le azioni di amministratore in tutti i tuoi domini.',
+        findYourSituation: 'La maggior parte dei problemi non richiede il blocco del tuo account! Trova la tua situazione qui sotto:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Carta smarrita o addebiti non riconosciuti</a>: Annulla la tua carta e contatta Concierge per contestare le transazioni sconosciute.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Accesso non autorizzato all’account</a>: Blocca il tuo account qui sotto. Questo blocca le nuove transazioni con la Carta Expensify, gli ordini di carte e le modifiche all’account. Se sei un amministratore di dominio, sospende anche tutta l’attività delle carte a livello di dominio e le azioni amministrative.',
+        securityTeamFollowUp: 'Il nostro team di sicurezza ti ricontatterà da <a href="mailto:risk@expensify.com">risk@expensify.com</a> dopo il blocco.',
         areYouSure: 'Sei sicuro di voler bloccare il tuo account Expensify?',
         onceLocked: 'Una volta bloccato, il tuo account sarà limitato in attesa di una richiesta di sblocco e di una revisione di sicurezza',
         unlockTitle: 'Abbiamo ricevuto la tua richiesta',
@@ -2595,13 +2627,10 @@ ${amount} per ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `spese di ${members} e l'approvatore è ${approvers}`,
         addApprovalButton: 'Aggiungi flusso di approvazione',
         editWorkflowAction: 'Modifica',
-        addAgentAction: 'Aggiungi agente',
         findWorkflow: 'Cerca flusso di lavoro',
         addApprovalTip: 'Questo flusso di lavoro predefinito si applica a tutti i membri, a meno che non esista un flusso di lavoro più specifico.',
         approver: 'Approvante',
         addApprovalsDescription: 'Richiedi un’approvazione aggiuntiva prima di autorizzare un pagamento.',
-        automateApprovalsWithAgentsTitle: 'Automatizza le approvazioni con gli agenti',
-        automateApprovalsWithAgentsSubtitle: 'Aggiungi l’agente qui sotto al workflow per automatizzare le approvazioni.',
         makeOrTrackPaymentsTitle: 'Pagamenti',
         makeOrTrackPaymentsDescription: 'Aggiungi un pagatore autorizzato per i pagamenti effettuati in Expensify o tieni traccia dei pagamenti effettuati altrove.',
         customApprovalWorkflowEnabled:
@@ -2897,6 +2926,12 @@ ${amount} per ${merchant} - ${date}`,
             },
         },
     },
+    focusModeUpdateModal: {
+        title: 'Benvenuto nella modalità #focus!',
+        prompt: (priorityModePageUrl: string) =>
+            `Tieniti al passo vedendo solo le chat non lette o quelle che richiedono la tua attenzione. Non preoccuparti, puoi cambiare questa impostazione in qualsiasi momento nelle <a href="${priorityModePageUrl}">impostazioni</a>.`,
+    },
+    inboxTabs: {all: 'Tutti', todo: 'Attività da fare', unread: 'Non letti'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
         generatingPDF: 'Genera PDF',
@@ -3460,11 +3495,6 @@ ${amount} per ${merchant} - ${date}`,
         year: 'Anno',
         selectYear: 'Seleziona un anno',
     },
-    focusModeUpdateModal: {
-        title: 'Benvenuto/a nella modalità #focus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Resta sempre aggiornato vedendo solo le chat non lette o quelle che richiedono la tua attenzione. Non preoccuparti, puoi modificare questa impostazione in qualsiasi momento nelle <a href="${priorityModePageUrl}">impostazioni</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'La chat che stai cercando non può essere trovata.',
         getMeOutOfHere: 'Fammi uscire di qui',
@@ -4124,28 +4154,31 @@ ${amount} per ${merchant} - ${date}`,
         verificationFailed: 'La verifica non è riuscita, quindi avremo bisogno di documenti aggiuntivi per verificare te e la tua azienda',
         taxIDVerification: 'Verifica dell’ID fiscale',
         taxIDVerificationDescription: dedent(`
-        Carica uno dei seguenti file:
-        • Lettera di assegnazione TIN/EIN dell’IRS
-        • Conferma della richiesta TIN/EIN dell’IRS (di solito indica "Congratulations! The EIN has been successfully assigned")
-        • Lettera di esenzione fiscale dell’IRS con nome dell’azienda ed EIN`),
+            Carica uno dei seguenti file:
+            • Lettera di assegnazione TIN/EIN dell’IRS
+            • Conferma della richiesta TIN/EIN dell’IRS (di solito indica "Congratulations! The EIN has been successfully assigned")
+            • Lettera di esenzione fiscale dell’IRS con nome dell’azienda ed EIN
+        `),
         nameChangeDocument: 'Documento di cambio nome',
         nameChangeDocumentDescription:
             'Se il nome della tua azienda è cambiato dopo la richiesta del TIN/EIN, abbiamo bisogno di questo documento per verificare il numero di ID fiscale fornito',
         companyAddressVerification: 'Verifica dell’indirizzo aziendale',
         companyAddressVerificationDescription: dedent(`
-        Carica uno dei seguenti file:
-        • Bolletta recente con nome e indirizzo dell’azienda
-        • Estratto conto bancario con nome e indirizzo dell’azienda
-        • Contratto di locazione attuale con pagina firme che mostri nome e indirizzo attuale dell’azienda
-        • Documento assicurativo con nome e indirizzo dell’azienda
-        • Documento di assegnazione TIN con nome e indirizzo dell’azienda`),
+            Carica uno dei seguenti file:
+            • Bolletta recente con nome e indirizzo dell’azienda
+            • Estratto conto bancario con nome e indirizzo dell’azienda
+            • Contratto di locazione attuale con pagina firme che mostri nome e indirizzo attuale dell’azienda
+            • Documento assicurativo con nome e indirizzo dell’azienda
+            • Documento di assegnazione TIN con nome e indirizzo dell’azienda
+        `),
         userAddressVerification: 'Verifica dell’indirizzo',
         userAddressVerificationDescription: dedent(`
-        Carica uno dei seguenti file:
-        • Tessera elettorale
-        • Patente di guida
-        • Estratto conto bancario
-        • Bolletta`),
+            Carica uno dei seguenti file:
+            • Tessera elettorale
+            • Patente di guida
+            • Estratto conto bancario
+            • Bolletta
+        `),
         userDOBVerification: 'Verifica della data di nascita',
         userDOBVerificationDescription: 'Carica un documento di identità rilasciato negli Stati Uniti',
         finishViaChat: 'Completa via chat',
@@ -4326,7 +4359,6 @@ ${amount} per ${merchant} - ${date}`,
             customFieldHint: 'Aggiungi una codifica personalizzata che si applichi a tutte le spese di questo membro.',
             reports: 'Report',
             reportFields: 'Campi del report',
-            invoiceFields: 'Campi fattura',
             reportTitle: 'Titolo del report',
             reportField: 'Campo report',
             taxes: 'Tasse',
@@ -4410,7 +4442,7 @@ ${amount} per ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Amministratore';
+                        return 'Amministratore spazio di lavoro';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Revisore';
                     case CONST.POLICY.ROLE.EDITOR:
@@ -4420,7 +4452,7 @@ ${amount} per ${merchant} - ${date}`,
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'Amministrazione persone';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Amministrazione pagamenti';
+                        return 'Amministratore pagamenti';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membro';
                     default:
@@ -6015,29 +6047,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             reportFieldInitialValueRequiredError: 'Scegli un valore iniziale per il campo del resoconto',
             genericFailureMessage: 'Si è verificato un errore durante l’aggiornamento del campo del report. Riprova.',
         },
-        invoiceFields: {
-            subtitle: 'I campi della fattura possono essere utili quando vuoi includere informazioni aggiuntive.',
-            importedFromAccountingSoftware: 'I campi della fattura riportati di seguito sono importati dal tuo',
-            disableInvoiceFields: 'Disattiva i campi della fattura',
-            disableInvoiceFieldsConfirmation: 'Sei sicuro? I campi della fattura verranno disattivati nelle fatture.',
-            delete: 'Elimina campo della fattura',
-            deleteConfirmation: 'Sei sicuro di voler eliminare questo campo della fattura?',
-            findInvoiceField: 'Trova campo della fattura',
-            nameInputSubtitle: 'Scegli un nome per il campo della fattura.',
-            typeInputSubtitle: 'Scegli il tipo di campo della fattura da utilizzare.',
-            initialValueInputSubtitle: 'Inserisci un valore iniziale da mostrare nel campo della fattura.',
-            listValuesInputSubtitle: 'Questi valori appariranno nel menu a discesa del campo della fattura. I valori abilitati possono essere selezionati dai membri.',
-            listInputSubtitle: 'Questi valori appariranno nell’elenco del campo della fattura. I valori abilitati possono essere selezionati dai membri.',
-            emptyInvoiceFieldsValues: {
-                title: 'Nessun valore elenco ancora',
-                subtitle: 'Aggiungi valori personalizzati da mostrare sulle fatture.',
-            },
-            existingInvoiceFieldNameError: 'Esiste già un campo della fattura con questo nome',
-            invoiceFieldNameRequiredError: 'Inserisci un nome per il campo della fattura',
-            invoiceFieldTypeRequiredError: 'Scegli un tipo di campo della fattura',
-            invoiceFieldInitialValueRequiredError: 'Scegli un valore iniziale per il campo della fattura',
-            addField: 'Aggiungi campo',
-        },
         tags: {
             tagName: 'Nome tag',
             requiresTag: 'I membri devono etichettare tutte le spese',
@@ -6259,8 +6268,8 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 other: 'Rendi membri',
             }),
             makeAdmin: () => ({
-                one: 'Rendi amministratore',
-                other: 'Rendi amministratori',
+                one: 'Rendi amministratore dello spazio di lavoro',
+                other: 'Rendi amministratori dello spazio di lavoro',
             }),
             makeAuditor: () => ({
                 one: 'Rendi revisore',
@@ -6289,12 +6298,14 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} ha un rapporto in sospeso su cui deve intervenire. Chiedi loro di completare l’azione richiesta prima di rimuoverlə dallo spazio di lavoro.`,
             allMembers: 'Tutti i membri',
-            admins: 'Amministratori',
+            admins: 'Amministratori dello spazio di lavoro',
             approvers: 'Approvatori',
             auditors: 'Revisori',
             emptyRoleFilter: {title: 'Nessun membro corrisponde a questo filtro', subtitle: 'Invita un membro o modifica il filtro qui sopra.'},
             configureHRSync: (providerName: string) => `Configura la sincronizzazione di ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizza con ${providerName}`,
+            makeCardAdmin: () => ({one: 'Rendi amministratore carta', other: 'Rendi amministratori carta'}),
+            cardAdmins: 'Amministratori carta',
         },
         card: {
             getStartedIssuing: 'Inizia emettendo la tua prima carta virtuale o fisica.',
@@ -6710,6 +6721,10 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             }),
             enableRate: 'Abilita tariffa',
             status: 'Stato',
+            statusActive: 'Attivo',
+            statusFuture: 'Futuro',
+            statusExpired: 'Scaduto',
+            statusInactive: 'Inattivo',
             unit: 'Unit',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Per usare questa funzione devi abilitare le imposte nello spazio di lavoro. Vai su <a href="#">Altre funzionalità</a> per effettuare questa modifica.</muted-text>',
@@ -6836,12 +6851,6 @@ Vuoi davvero esportarli di nuovo?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>I campi del report sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Campi fattura',
-                description: `I campi fattura ti consentono di includere dettagli aggiuntivi a livello di fattura.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>I campi fattura sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Approfitta della sincronizzazione automatica e riduci le registrazioni manuali con l’integrazione Expensify + NetSuite. Ottieni approfondimenti finanziari dettagliati e in tempo reale grazie al supporto di segmenti nativi e personalizzati, inclusa la mappatura di progetti e clienti.`,
@@ -6943,12 +6952,6 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Le tariffe chilometriche sono disponibili con il piano Collect, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Revisore',
-                description: 'I revisori ottengono accesso in sola lettura a tutti i report per garantire completa visibilità e monitoraggio della conformità.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Gli auditor sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Livelli di approvazione multipli',
                 description:
@@ -7048,6 +7051,12 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>La fatturazione è disponibile nei piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Ruoli dei criteri di controllo',
+                description: 'Usa ruoli specializzati come Revisore e Amministratore carte per concedere ai membri l’accesso solo a ciò di cui hanno bisogno.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>I ruoli specializzati dello spazio di lavoro sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -7375,6 +7384,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 deleteRuleConfirmation: 'Sei sicuro di voler eliminare questa regola?',
                 describeRuleTitle: 'Descrivi la tua regola',
                 describeRuleSubtitle: 'Descrivi la tua regola e Concierge la creerà',
+                disclaimer: 'Gli agenti IA possono commettere errori.',
             },
         },
         planTypePage: {
@@ -8060,25 +8070,19 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} da ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `ha cambiato l’aliquota fiscale predefinita della categoria "${categoryName}" in "${newTax}" (in precedenza "${oldTax}")`,
         addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `ha aggiunto la tariffa "${rateName}" di ${rateValue}`,
         addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `ha aggiunto l’aliquota "${rateName}" di ${rateValue}, valida dal ${startDate}`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `ha aggiunto la tariffa "${rateName}" di ${rateValue}, valida fino al ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `ha aggiunto la tariffa "${rateName}" di ${rateValue}, valida dal ${startDate} al ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate
-                ? `aggiornata la data di inizio della tariffa "${rateName}" a ${newDate} (in precedenza ${oldDate})`
-                : `imposta la data di inizio della tariffa "${rateName}" su ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate
-                ? `ha aggiornato la data di fine della tariffa "${rateName}" a ${newDate} (in precedenza ${oldDate})`
-                : `imposta la data di fine della tariffa "${rateName}" al ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `ha aggiornato la data di inizio e fine della tariffa "${rateName}" in ${newStartDate} - ${newEndDate} (in precedenza ${oldStartDate} - ${oldEndDate})`
-                : `imposta data di inizio e fine della tariffa "${rateName}" su ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `rimossa la data di inizio dalla tariffa "${rateName}" (in precedenza ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `data di fine rimossa dalla tariffa "${rateName}" (precedentemente ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `ha aggiornato la tariffa chilometrica "${rateName}" per applicarla a ${newDateRange} (in precedenza ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `dal ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `fino al ${date}`,
+        customUnitRateDateRangeAllDates: () => `per tutte le date`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro non trovato.',
@@ -8519,8 +8523,11 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                     `La connessione ${feedName} è interrotta. Per ripristinare le importazioni della carta, <a href='${workspaceCompanyCardRoute}'>accedi alla tua banca</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} come ${role === 'member' ? 'a' : 'un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} come ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `ha aggiornato il ruolo di ${email} a ${newRole} (in precedenza ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
@@ -9417,6 +9424,11 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Come <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copilota</a> per ${accountOwnerEmail}, non hai l'autorizzazione per eseguire questa azione. Spiacenti!`,
+        removeCopilotAccess: 'Rimuovi il mio accesso copilota',
+        removeCopilotAccessTitle: "Rimuovere l'accesso copilota?",
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Sei sicuro di voler rimuovere il tuo accesso copilota all'account Expensify di ${delegatorName}? Questa azione non può essere annullata.`,
+        removeCopilotAccessConfirm: 'Rimuovi accesso',
         copilotAccess: 'Accesso a Copilot',
     },
     debug: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 98aae61a7580..22b0a46b97c3 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -108,7 +109,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: '複数選択',
         saveChanges: '変更を保存',
         submit: '送信',
+        markAsDone: '完了にする',
         submitted: '送信済み',
+        markedAsDoneStatus: '完了済み',
         rotate: '回転',
         zoom: 'ズーム',
         password: 'パスワード',
@@ -293,7 +296,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: '説明',
         title: 'タイトル',
         assignee: '担当者',
-        createdBy: '作成者',
         with: '〜で',
         shareCode: 'コードを共有',
         share: '共有',
@@ -314,6 +316,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: '加盟店',
         change: '変更',
         category: 'カテゴリ',
+        vendor: 'ベンダー',
         report: 'レポート',
         billable: '請求可能',
         nonBillable: '請求不可',
@@ -355,6 +358,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'チャットを検索するには',
             subtitleText2: '上のボタン、または次を使って何かを作成する',
             subtitleText3: '下のボタンを押してください。',
+            noUnreadChats: '未読のチャットはありません',
+            noTodos: 'To-do はありません',
+            caughtUp: 'すべて確認済みです。お疲れさまでした！',
+            seeAllChats: 'すべてのチャットを表示',
         },
         businessName: '会社名',
         clear: 'クリア',
@@ -843,6 +850,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `このチャットの相手は${users}です。`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `ここは<strong>${submitterDisplayName}</strong>さんが<strong>${workspaceName}</strong>に経費精算を提出する場所です。+ボタンを押すだけでOKです。`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'ここは経費を管理する場所です',
         beginningOfChatHistorySelfDM: 'ここはあなたの個人スペースです。メモ、タスク、下書き、リマインダーに活用してください。',
         beginningOfChatHistorySystemDM: 'ようこそ！設定を始めましょう。',
         chatWithAccountManager: 'ここでアカウントマネージャーとチャットする',
@@ -945,7 +953,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 subtitle: ({policyName}: {policyName: string}) => `${policyName} > 会計`,
             },
             fixPersonalCardConnection: {title: ({cardName}: {cardName?: string}) => (cardName ? `${cardName}個人カードの接続を修正` : '個人カードの連携を修正'), subtitle: 'ウォレット'},
-            validateAccount: {title: 'Expensify を引き続きご利用いただくには、アカウントを認証してください', subtitle: 'アカウント', cta: '検証する'},
+            validateAccount: {title: 'アカウントを認証してください', subtitle: 'アカウント', cta: '検証する'},
             fixFailedBilling: {title: '登録されているカードから請求できませんでした', subtitle: 'サブスクリプション'},
             unlockBankAccount: {
                 workspaceTitle: 'ビジネス用銀行口座がロックされました',
@@ -1000,6 +1008,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'すべて確認済みです',
                 f1FlagsDescription: 'すべての未処理の To-do が完了しました。',
             },
+            reviewExpenses: ({count}: {count: number}) => `${count} 件の${count === 1 ? '経費' : '経費'}を確認`,
         },
         upcomingTravel: '今後の出張',
         upcomingTravelSection: {
@@ -1335,6 +1344,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `${amount} の請求書を送信`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `${comment}用` : ''}`,
         submitted: (memo?: string) => `送信済み${memo ? `、メモ: ${memo}` : ''}`,
+        markedAsDone: (memo) => `完了としてマークしました${memo ? `（メモ：${memo}）` : ''}`,
         automaticallySubmitted: `<a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">提出の延期</a> 経由で提出されました`,
         queuedToSubmitViaDEW: 'カスタム承認ワークフローで提出待ち',
         queuedToApproveViaDEW: 'カスタム承認ワークフローで承認待ちに設定されました',
@@ -1548,6 +1558,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: '削除済み',
         transactionPending: '取引は保留中です。',
         chooseARate: 'ワークスペースの払い戻しレートをマイルまたはキロメートルごとに選択してください',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate}から${endDate}まで有効`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `${startDate}から有効`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `${endDate}まで有効`,
         unapprove: '承認を取り消す',
         unapproveReport: 'レポートの承認を取り消す',
         headsUp: 'ご注意ください！',
@@ -1648,6 +1661,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'レートのエラーを修正して、もう一度お試しください。',
         AskToExplain: `・<a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">説明<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge がこの経費を <strong>${vendorName}</strong> に一致させました`,
         duplicateNonDefaultWorkspacePerDiemError: 'ワークスペースごとに日当レートが異なる場合があるため、日当経費をワークスペース間で複製することはできません。',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? '経費を「精算対象」に指定しました' : '経費を「精算対象外」にマークしました'),
@@ -1775,6 +1789,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `管理者が経費を送信するのを待っています。`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `<strong>あなた</strong>が完了にするのを待っています。`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `<strong>${actor}</strong>が完了にするのを待っています。`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `管理者が完了にするのを待っています。`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
@@ -2207,10 +2236,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: '不審な行為を報告',
         lockAccount: 'アカウントをロック',
+        lockMyAccount: 'アカウントをロックする',
         unlockAccount: 'アカウントのロック解除',
-        compromisedDescription:
-            'アカウントにおかしな点がありますか？報告すると、すぐにアカウントがロックされ、新しい Expensify カードの取引がブロックされ、アカウントの変更もできなくなります。',
-        domainAdminsDescription: 'ドメイン管理者向け：これにより、ドメイン全体のすべての Expensify カードの利用と管理者による操作も一時停止されます。',
+        findYourSituation: 'ほとんどの問題ではアカウントをロックする必要はありません。以下からご自身の状況をお探しください。',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">カードの紛失または身に覚えのない請求</a>：カードを解約し、不明な取引について異議申し立てをするために Concierge へご連絡ください。',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">不正なアカウントアクセス</a>：以下からアカウントをロックしてください。これにより、新しい Expensify カードの利用、カードの発行依頼、およびアカウントの変更ができなくなります。ドメイン管理者の場合、ドメイン全体のカードアクティビティと管理者アクションも一時停止されます。',
+        securityTeamFollowUp: 'ロック後、セキュリティチームが<a href="mailto:risk@expensify.com">risk@expensify.com</a>からご連絡します。',
         areYouSure: 'Expensify アカウントをロックしてもよろしいですか？',
         onceLocked: 'ロックされると、解除リクエストとセキュリティ審査が完了するまでアカウントは制限されます',
         unlockTitle: 'リクエストを受け付けました',
@@ -2572,13 +2605,10 @@ ${date} の ${merchant} への ${amount}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `${members} の経費で、承認者は ${approvers} です`,
         addApprovalButton: '承認ワークフローを追加',
         editWorkflowAction: '編集',
-        addAgentAction: 'エージェントを追加',
         findWorkflow: 'ワークフローを検索',
         addApprovalTip: 'より詳細なワークフローが存在する場合を除き、このデフォルトのワークフローがすべてのメンバーに適用されます。',
         approver: '承認者',
         addApprovalsDescription: '支払いを承認する前に、追加の承認を必須にする。',
-        automateApprovalsWithAgentsTitle: '代理を使って承認を自動化する',
-        automateApprovalsWithAgentsSubtitle: '承認を自動化するには、以下のエージェントをワークフローに追加してください。',
         makeOrTrackPaymentsTitle: '支払',
         makeOrTrackPaymentsDescription: 'Expensifyでの支払いに対する承認済み支払者を追加するか、他の場所で行われた支払いを記録します。',
         customApprovalWorkflowEnabled:
@@ -2872,6 +2902,12 @@ ${date} の ${merchant} への ${amount}`,
             },
         },
     },
+    focusModeUpdateModal: {
+        title: '#focus モードへようこそ！',
+        prompt: (priorityModePageUrl: string) =>
+            `未読のチャットや対応が必要なチャットだけを表示して、状況を常に把握できるようにしましょう。いつでも<a href="${priorityModePageUrl}">設定</a>で変更できます。`,
+    },
+    inboxTabs: {all: 'すべて', todo: 'To-do リスト', unread: '未読'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `${policyName} 内`,
         generatingPDF: 'PDFを生成',
@@ -3434,11 +3470,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         year: '年',
         selectYear: '年を選択してください',
     },
-    focusModeUpdateModal: {
-        title: '#focusモードへようこそ！',
-        prompt: (priorityModePageUrl: string) =>
-            `未読のチャットや対応が必要なチャットだけを表示して、常に状況を把握しましょう。いつでも<a href="${priorityModePageUrl}">設定</a>から変更できます。`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'お探しのチャットが見つかりません。',
         getMeOutOfHere: 'ここから出して',
@@ -4096,27 +4127,30 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         verificationFailed: '確認に失敗したため、追加の書類で本人および事業の確認が必要です',
         taxIDVerification: '納税者番号の確認',
         taxIDVerificationDescription: dedent(`
-        以下のいずれかの書類をアップロードしてください：
-        • IRS TIN/EIN 割当通知書
-        • IRS TIN/EIN 申請確認書（通常「Congratulations! The EIN has been successfully assigned」と記載）
-        • 会社名と EIN が記載された IRS の免税通知書`),
+            以下のいずれかの書類をアップロードしてください：
+            • IRS TIN/EIN 割当通知書
+            • IRS TIN/EIN 申請確認書（通常「Congratulations! The EIN has been successfully assigned」と記載）
+            • 会社名と EIN が記載された IRS の免税通知書
+        `),
         nameChangeDocument: '名称変更書類',
         nameChangeDocumentDescription: 'TIN/EIN 申請後に会社名が変更された場合、提供された納税者番号を確認するためにこの書類が必要です',
         companyAddressVerification: '会社住所の確認',
         companyAddressVerificationDescription: dedent(`
-        以下のいずれかの書類をアップロードしてください：
-        • 会社名と住所が記載された最近の公共料金請求書
-        • 会社名と住所が記載された銀行取引明細書
-        • 署名ページを含む現行の賃貸契約書（会社名と現住所が記載されたもの）
-        • 会社名と住所が記載された保険証書
-        • 会社名と住所が記載された TIN 割当書類`),
+            以下のいずれかの書類をアップロードしてください：
+            • 会社名と住所が記載された最近の公共料金請求書
+            • 会社名と住所が記載された銀行取引明細書
+            • 署名ページを含む現行の賃貸契約書（会社名と現住所が記載されたもの）
+            • 会社名と住所が記載された保険証書
+            • 会社名と住所が記載された TIN 割当書類
+        `),
         userAddressVerification: '住所確認',
         userAddressVerificationDescription: dedent(`
-        以下のいずれかの書類をアップロードしてください：
-        • 有権者登録カード
-        • 運転免許証
-        • 銀行取引明細書
-        • 公共料金請求書`),
+            以下のいずれかの書類をアップロードしてください：
+            • 有権者登録カード
+            • 運転免許証
+            • 銀行取引明細書
+            • 公共料金請求書
+        `),
         userDOBVerification: '生年月日の確認',
         userDOBVerificationDescription: '米国発行の身分証明書をアップロードしてください',
         finishViaChat: 'チャットで完了',
@@ -4297,7 +4331,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             customFieldHint: 'このメンバーのすべての支出に適用されるカスタムコードを追加します。',
             reports: 'レポート',
             reportFields: 'レポート項目',
-            invoiceFields: '請求書項目',
             reportTitle: 'レポートタイトル',
             reportField: 'レポート項目',
             taxes: '税金',
@@ -4380,18 +4413,17 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理者';
+                        return 'ワークスペース管理者';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '監査人';
                     case CONST.POLICY.ROLE.EDITOR:
                         return '編集者';
-                        return '監査担当者';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return 'カード管理者';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'メンバー管理';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return '支払管理者';
+                        return '支払い管理者';
                     case CONST.POLICY.ROLE.USER:
                         return 'メンバー';
                     default:
@@ -5946,29 +5978,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             reportFieldInitialValueRequiredError: 'レポート項目の初期値を選択してください',
             genericFailureMessage: 'レポートフィールドの更新中にエラーが発生しました。もう一度お試しください。',
         },
-        invoiceFields: {
-            subtitle: '追加情報を含めたい場合、請求書フィールドが役立ちます。',
-            importedFromAccountingSoftware: '以下の請求書フィールドは、次からインポートされます',
-            disableInvoiceFields: '請求書フィールドを無効にする',
-            disableInvoiceFieldsConfirmation: 'よろしいですか？請求書フィールドは請求書で無効になります。',
-            delete: '請求書フィールドを削除',
-            deleteConfirmation: 'この請求書フィールドを削除してもよろしいですか？',
-            findInvoiceField: '請求書フィールドを検索',
-            nameInputSubtitle: '請求書フィールドの名前を選択してください。',
-            typeInputSubtitle: '使用する請求書フィールドの種類を選択してください。',
-            initialValueInputSubtitle: '請求書フィールドに表示する開始値を入力してください。',
-            listValuesInputSubtitle: 'これらの値は請求書フィールドのドロップダウンに表示されます。有効な値はメンバーが選択できます。',
-            listInputSubtitle: 'これらの値は請求書フィールドのリストに表示されます。有効な値はメンバーが選択できます。',
-            emptyInvoiceFieldsValues: {
-                title: 'リスト値はまだありません',
-                subtitle: '請求書に表示するカスタム値を追加します。',
-            },
-            existingInvoiceFieldNameError: 'この名前の請求書フィールドは既に存在します',
-            invoiceFieldNameRequiredError: '請求書フィールド名を入力してください',
-            invoiceFieldTypeRequiredError: '請求書フィールドの種類を選択してください',
-            invoiceFieldInitialValueRequiredError: '請求書フィールドの初期値を選択してください',
-            addField: 'フィールドを追加',
-        },
         tags: {
             tagName: 'タグ名',
             requiresTag: 'メンバーはすべての経費にタグを付ける必要があります',
@@ -6189,8 +6198,8 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 other: 'メンバーにする',
             }),
             makeAdmin: () => ({
-                one: '管理者にする',
-                other: '管理者にする',
+                one: 'ワークスペース管理者にする',
+                other: 'ワークスペース管理者にする',
             }),
             makeAuditor: () => ({
                 one: '監査担当者に設定',
@@ -6219,12 +6228,14 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} は、対応が必要な未処理のレポートがあります。ワークスペースから削除する前に、必要な対応を完了するよう依頼してください。`,
             allMembers: 'すべてのメンバー',
-            admins: '管理者',
+            admins: 'ワークスペース管理者',
             approvers: '承認者',
             auditors: '監査担当者',
             emptyRoleFilter: {title: 'このフィルターに一致するメンバーはいません', subtitle: 'メンバーを招待するか、上のフィルターを変更してください。'},
             configureHRSync: (providerName: string) => `${providerName} の同期を設定します。`,
             syncWithHR: (providerName: string) => `${providerName}と同期`,
+            makeCardAdmin: () => ({one: 'カード管理者にする', other: 'カード管理者に設定'}),
+            cardAdmins: 'カード管理者',
         },
         card: {
             getStartedIssuing: 'まずは最初のバーチャルカードまたは物理カードを発行しましょう。',
@@ -6639,6 +6650,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             }),
             enableRate: 'レートを有効にする',
             status: 'ステータス',
+            statusActive: 'アクティブ',
+            statusFuture: '将来',
+            statusExpired: '期限切れ',
+            statusInactive: '無効',
             unit: '単位',
             taxFeatureNotEnabledMessage:
                 '<muted-text>この機能を利用するには、ワークスペースで税金設定を有効にする必要があります。設定を変更するには、<a href="#">その他の機能</a>に移動してください。</muted-text>',
@@ -6764,12 +6779,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>レポートフィールドは、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からのControlプランでのみ利用できます</muted-text>`,
             },
-            invoiceFields: {
-                title: '請求書項目',
-                description: `請求書フィールドを使うと、請求書レベルの追加情報を請求書に含めることができます。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>請求書フィールドは、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からのControlプランでのみ利用できます</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Expensify と NetSuite の連携により、自動同期を活用して手入力を減らしましょう。プロジェクトや顧客のマッピングを含むネイティブおよびカスタムセグメントのサポートで、詳細かつリアルタイムな財務インサイトを得られます。`,
@@ -6870,12 +6879,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>距離レートはCollectプランで利用できます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からご利用になれます</muted-text>`,
             },
-            auditor: {
-                title: '監査人',
-                description: '監査担当者は、可視性とコンプライアンス監視を徹底するため、すべてのレポートを閲覧専用で確認できます。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>監査人は、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からの Control プランでのみ利用できます</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: '複数の承認レベル',
                 description: '複数承認レベルは、精算前にレポートを複数人で承認する必要がある会社向けのワークフローツールです。',
@@ -6970,6 +6973,12 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>請求書発行機能は、Collect プランと Control プランでご利用いただけます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からご利用可能です。</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'コントロールポリシーのロール',
+                description: '監査人やカード管理者などの専用ロールを使って、メンバーが必要なものにだけアクセスできるようにします。',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>特別なワークスペースロールは Control プランでのみご利用いただけます（<strong>${formattedPrice}</strong> から、${hasTeam2025Pricing ? `メンバー1人あたり月額。` : `アクティブメンバー1人あたり／月`}）。</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -7293,6 +7302,7 @@ ${reportName}
                 deleteRuleConfirmation: 'このルールを削除してもよろしいですか？',
                 describeRuleTitle: 'ルールの内容を記入してください',
                 describeRuleSubtitle: 'ルールの内容を入力すると、Concierge が自動作成します',
+                disclaimer: 'AI エージェントは間違える場合があります。',
             },
         },
         planTypePage: {
@@ -7964,21 +7974,19 @@ ${reportName}
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${cards} からの ${content}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `「${categoryName}」カテゴリのデフォルト税率を「${newTax}」に変更しました（以前は「${oldTax}」）`,
         addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `「${rateName}」レート（${rateValue}）を追加しました`,
         addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `${startDate}から有効な「${rateName}」レート（${rateValue}）を追加しました`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `「${rateName}」レート（${rateValue}）を${endDate}まで有効として追加しました`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `「${rateName}」レート（${rateValue}）を追加しました。有効期間：${startDate}〜${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `「${rateName}」レートの開始日を${newDate}に更新しました（以前は${oldDate}）` : `「${rateName}」レートの開始日を${newDate}に設定する`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `「${rateName}」レートの終了日を${newDate}（以前は${oldDate}）に更新しました` : `「${rateName}」レートの終了日を${newDate}に設定します`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `「${rateName}」レートの開始日と終了日を${newStartDate}〜${newEndDate}に更新しました（以前は${oldStartDate}〜${oldEndDate}）`
-                : `「${rateName}」レートの開始日と終了日を${newStartDate}〜${newEndDate}に設定しました`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `「${rateName}」レートの開始日を削除しました（以前の開始日：${oldDate}）`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `「${rateName}」レートの終了日を削除しました（以前は ${oldDate}）`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `距離レート「${rateName}」を更新し、${newDateRange} に適用しました（以前は ${oldDateRange}）`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `${date} から`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `${date}まで`,
+        customUnitRateDateRangeAllDates: () => `すべての日付に対して`,
     },
     roomMembersPage: {
         memberNotFound: 'メンバーが見つかりません。',
@@ -8408,8 +8416,11 @@ ${reportName}
                     `${feedName} との接続が切断されています。カードの取引明細の取込を再開するには、<a href='${workspaceCompanyCardRoute}'>銀行にログイン</a>してください。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${role === 'member' ? 'a' : '1つの'} ${role} として ${email} を追加しました`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? '1つの' : 'a';
+                    return didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を ${article} ${translatedRole} として追加しました`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `${email} のロールを ${currentRole} から ${newRole} に更新しました`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
@@ -9293,6 +9304,11 @@ ${reportName}
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `${accountOwnerEmail} の<a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">コパイロット</a>として、この操作を行う権限がありません。申し訳ありません。`,
+        removeCopilotAccess: '自分のコパイロットアクセスを削除',
+        removeCopilotAccessTitle: 'コパイロットアクセスを削除しますか？',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `${delegatorName}のExpensifyアカウントへのコパイロットアクセスを削除してもよろしいですか？この操作は元に戻せません。`,
+        removeCopilotAccessConfirm: 'アクセスを削除',
         copilotAccess: 'Copilot へのアクセス',
     },
     debug: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index ba3d4b5b121c..b6b836726f01 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -108,7 +109,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Meerdere selecteren',
         saveChanges: 'Wijzigingen opslaan',
         submit: 'Verzenden',
+        markAsDone: 'Markeren als voltooid',
         submitted: 'Ingediend',
+        markedAsDoneStatus: 'Als voltooid gemarkeerd',
         rotate: 'Draaien',
         zoom: 'Zoom',
         password: 'Wachtwoord',
@@ -293,7 +296,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Beschrijving',
         title: 'Titel',
         assignee: 'Toegewezene',
-        createdBy: 'Gemaakt door',
         with: 'met',
         shareCode: 'Code delen',
         share: 'Delen',
@@ -314,6 +316,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Handelaar',
         change: 'Wijzigen',
         category: 'Categorie',
+        vendor: 'Leverancier',
         report: 'Rapport',
         billable: 'Factureerbaar',
         nonBillable: 'Niet-factureerbaar',
@@ -355,6 +358,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Zoek een chat met de',
             subtitleText2: 'knop hierboven, of maak iets met de',
             subtitleText3: 'knop hieronder.',
+            noUnreadChats: 'Geen ongelezen chats',
+            noTodos: 'Geen taken',
+            caughtUp: 'Je bent helemaal bij. Goed gedaan!',
+            seeAllChats: 'Alle chats bekijken',
         },
         businessName: 'Bedrijfsnaam',
         clear: 'Wissen',
@@ -852,6 +859,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Deze chat is met ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `Dit is waar <strong>${submitterDisplayName}</strong> declaraties indient bij <strong>${workspaceName}</strong>. Gebruik gewoon de +-knop.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Hier houd je je uitgaven bij',
         beginningOfChatHistorySelfDM: 'Dit is je persoonlijke ruimte. Gebruik het voor notities, taken, concepten en herinneringen.',
         beginningOfChatHistorySystemDM: 'Welkom! Laten we je instellen.',
         chatWithAccountManager: 'Chat hier met je accountmanager',
@@ -957,7 +965,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Verbinding van persoonlijke kaart ${cardName} herstellen` : 'Verbinding persoonlijke kaart herstellen'),
                 subtitle: 'Portemonnee',
             },
-            validateAccount: {title: 'Valideer je account om Expensify te blijven gebruiken', subtitle: 'Account', cta: 'Valideren'},
+            validateAccount: {title: 'Valideer je account', subtitle: 'Account', cta: 'Valideren'},
             fixFailedBilling: {title: 'We konden je kaart in ons bestand niet belasten', subtitle: 'Abonnement'},
             unlockBankAccount: {
                 workspaceTitle: 'Je zakelijke bankrekening is geblokkeerd',
@@ -1012,6 +1020,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Helemaal bij',
                 f1FlagsDescription: "Je hebt alle openstaande to-do's afgerond.",
             },
+            reviewExpenses: ({count}: {count: number}) => `Beoordeel ${count} ${count === 1 ? 'uitgave' : 'uitgaven'}`,
         },
         upcomingTravel: 'Aankomende reizen',
         upcomingTravelSection: {
@@ -1347,6 +1356,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Verzend factuur van ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `voor ${comment}` : ''}`,
         submitted: (memo?: string) => `ingediend${memo ? `, met de omschrijving ${memo}` : ''}`,
+        markedAsDone: (memo) => `gemarkeerd als voltooid${memo ? `, met als omschrijving ${memo}` : ''}`,
         automaticallySubmitted: `ingediend via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">uitgestelde indieningen</a>`,
         queuedToSubmitViaDEW: 'in wachtrij om via aangepast goedkeuringsproces in te dienen',
         queuedToApproveViaDEW: 'in de wachtrij gezet voor goedkeuring via aangepaste goedkeuringsworkflow',
@@ -1560,6 +1570,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'verwijderd',
         transactionPending: 'Transactie in behandeling.',
         chooseARate: 'Selecteer een workspace-vergoeding per mijl of kilometer',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} tot ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Geldig vanaf ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Geldig tot ${endDate}`,
         unapprove: 'Intrekken goedkeuring',
         unapproveReport: 'Goedkeuring rapport intrekken',
         headsUp: 'Let op!',
@@ -1660,6 +1673,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Los de tarieffout op en probeer het opnieuw.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Uitleggen<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge heeft deze uitgave gekoppeld aan <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError: 'Je kunt dagvergoedingen niet dupliceren tussen werkruimtes, omdat de tarieven per werkruimte kunnen verschillen.',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'markeerde de uitgave als „terugbetaalbaar”' : 'heeft de uitgave als ‘niet-vergoedbaar’ gemarkeerd'),
@@ -1787,6 +1801,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Wachten tot een beheerder de onkosten indient.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Er wordt gewacht tot <strong>jij</strong> dit als voltooid markeert.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Wachten tot <strong>${actor}</strong> dit als voltooid markeert.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Wachten tot een beheerder dit als voltooid markeert.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
@@ -2221,10 +2250,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Verdachte activiteit melden',
         lockAccount: 'Account vergrendelen',
+        lockMyAccount: 'Account vergrendelen',
         unlockAccount: 'Account ontgrendelen',
-        compromisedDescription:
-            'Val je iets op aan je account? Als je dit meldt, wordt je account onmiddellijk vergrendeld, worden nieuwe Expensify Kaart-transacties geblokkeerd en worden wijzigingen aan je account voorkomen.',
-        domainAdminsDescription: 'Voor domeinbeheerders: dit pauzeert ook alle Expensify Kaart-activiteit en beheerdersacties in je domein(en).',
+        findYourSituation: 'Voor de meeste problemen hoef je je account niet te blokkeren. Zoek hieronder jouw situatie:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Kaart kwijt of onbekende kosten</a>: Annuleer je kaart en neem contact op met Concierge om onbekende transacties te betwisten.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Onbevoegde accounttoegang</a>: Vergrendel hieronder je account. Dit blokkeert nieuwe Expensify Kaart-transacties, kaartbestellingen en accountwijzigingen. Als je domeinbeheerder bent, pauzeert dit ook alle domeinbrede kaartactiviteiten en beheerdersacties.',
+        securityTeamFollowUp: 'Ons beveiligingsteam neemt na het blokkeren contact met je op vanaf <a href="mailto:risk@expensify.com">risk@expensify.com</a>.',
         areYouSure: 'Weet je zeker dat je je Expensify-account wilt vergrendelen?',
         onceLocked: 'Zodra deze wordt vergrendeld, wordt je account beperkt in afwachting van een deblokkeringsverzoek en een beveiligingscontrole',
         unlockTitle: 'We hebben je verzoek ontvangen',
@@ -2592,13 +2625,10 @@ ${amount} voor ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `de uitgaven van ${members}, en de goedkeurder is ${approvers}`,
         addApprovalButton: 'Goedkeuringsworkflow toevoegen',
         editWorkflowAction: 'Bewerken',
-        addAgentAction: 'Agent toevoegen',
         findWorkflow: 'Workflow zoeken',
         addApprovalTip: 'Deze standaardworkflow is van toepassing op alle leden, tenzij er een specifiekere workflow bestaat.',
         approver: 'Fiatteur',
         addApprovalsDescription: 'Extra goedkeuring vereisen voordat je een betaling autoriseert.',
-        automateApprovalsWithAgentsTitle: 'Automatiseer goedkeuringen met agents',
-        automateApprovalsWithAgentsSubtitle: 'Voeg hieronder een agent toe aan de workflow om goedkeuringen te automatiseren.',
         makeOrTrackPaymentsTitle: 'Betalingen',
         makeOrTrackPaymentsDescription: 'Voeg een gemachtigde betaler toe voor betalingen die in Expensify worden gedaan of volg betalingen die elders zijn gedaan.',
         customApprovalWorkflowEnabled:
@@ -2894,6 +2924,12 @@ ${amount} voor ${merchant} - ${date}`,
             },
         },
     },
+    focusModeUpdateModal: {
+        title: 'Welkom in #focus-modus!',
+        prompt: (priorityModePageUrl: string) =>
+            `Blijf op de hoogte door alleen ongelezen chats of chats te zien die je aandacht nodig hebben. Geen zorgen, je kunt dit op elk moment wijzigen in de <a href="${priorityModePageUrl}">instellingen</a>.`,
+    },
+    inboxTabs: {all: 'Alles', todo: 'Te doen', unread: 'Ongelezen'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
         generatingPDF: 'PDF genereren',
@@ -3456,11 +3492,6 @@ ${amount} voor ${merchant} - ${date}`,
         year: 'Jaar',
         selectYear: 'Selecteer een jaar',
     },
-    focusModeUpdateModal: {
-        title: 'Welkom bij de #focus-modus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Houd het overzicht door alleen ongelezen chats of chats die je aandacht nodig hebben te zien. Geen zorgen, je kunt dit op elk moment wijzigen in de <a href="${priorityModePageUrl}">instellingen</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'De chat die je zoekt, kan niet worden gevonden.',
         getMeOutOfHere: 'Haal me hier weg',
@@ -4120,27 +4151,30 @@ ${amount} voor ${merchant} - ${date}`,
         verificationFailed: 'De verificatie is mislukt, daarom hebben we extra documenten nodig om jou en je bedrijf te verifiëren',
         taxIDVerification: 'Belastingnummerverificatie',
         taxIDVerificationDescription: dedent(`
-        Upload een van de volgende bestanden:
-        • IRS TIN/EIN-toewijzingsbrief
-        • IRS TIN/EIN-aanvraagbevestiging (bevat meestal "Congratulations! The EIN has been successfully assigned")
-        • IRS-belastingvrijstellingsbrief met bedrijfsnaam en EIN`),
+            Upload een van de volgende bestanden:
+            • IRS TIN/EIN-toewijzingsbrief
+            • IRS TIN/EIN-aanvraagbevestiging (bevat meestal "Congratulations! The EIN has been successfully assigned")
+            • IRS-belastingvrijstellingsbrief met bedrijfsnaam en EIN
+        `),
         nameChangeDocument: 'Document naamswijziging',
         nameChangeDocumentDescription: 'Als de naam van je bedrijf is gewijzigd sinds de TIN/EIN-aanvraag, hebben we dit document nodig om het opgegeven belastingnummer te verifiëren',
         companyAddressVerification: 'Verificatie van bedrijfsadres',
         companyAddressVerificationDescription: dedent(`
-        Upload een van de volgende bestanden:
-        • Recente energierekening met bedrijfsnaam en adres
-        • Bankafschrift met bedrijfsnaam en adres
-        • Huidige huur- of leaseovereenkomst inclusief ondertekeningspagina met bedrijfsnaam en huidig adres
-        • Verzekeringsverklaring met bedrijfsnaam en adres
-        • TIN-toewijzingsdocument met bedrijfsnaam en adres`),
+            Upload een van de volgende bestanden:
+            • Recente energierekening met bedrijfsnaam en adres
+            • Bankafschrift met bedrijfsnaam en adres
+            • Huidige huur- of leaseovereenkomst inclusief ondertekeningspagina met bedrijfsnaam en huidig adres
+            • Verzekeringsverklaring met bedrijfsnaam en adres
+            • TIN-toewijzingsdocument met bedrijfsnaam en adres
+        `),
         userAddressVerification: 'Adresverificatie',
         userAddressVerificationDescription: dedent(`
-        Upload een van de volgende bestanden:
-        • Kiezersregistratiekaart
-        • Rijbewijs
-        • Bankafschrift
-        • Energierekening`),
+            Upload een van de volgende bestanden:
+            • Kiezersregistratiekaart
+            • Rijbewijs
+            • Bankafschrift
+            • Energierekening
+        `),
         userDOBVerification: 'Verificatie van geboortedatum',
         userDOBVerificationDescription: 'Upload een in de VS uitgegeven identiteitsbewijs',
         finishViaChat: 'Afronden via chat',
@@ -4321,7 +4355,6 @@ ${amount} voor ${merchant} - ${date}`,
             customFieldHint: 'Voeg aangepaste codering toe die van toepassing is op alle uitgaven van dit lid.',
             reports: 'Rapporten',
             reportFields: 'Rapportvelden',
-            invoiceFields: 'Factuurvelden',
             reportTitle: 'Rapporttitel',
             reportField: 'Rapportveld',
             taxes: 'Belastingen',
@@ -4405,7 +4438,7 @@ ${amount} voor ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Beheer';
+                        return 'Werkruimtebeheerder';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.EDITOR:
@@ -4413,7 +4446,7 @@ ${amount} voor ${merchant} - ${date}`,
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return 'Kaartbeheer';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Mensenbeheer';
+                        return 'Personenbeheer';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Beheerder betalingen';
                     case CONST.POLICY.ROLE.USER:
@@ -5993,29 +6026,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             reportFieldInitialValueRequiredError: 'Kies een beginwaarde voor een rapportveld',
             genericFailureMessage: 'Er is een fout opgetreden bij het bijwerken van het rapportveld. Probeer het opnieuw.',
         },
-        invoiceFields: {
-            subtitle: 'Factuurvelden kunnen handig zijn als je extra informatie wilt toevoegen.',
-            importedFromAccountingSoftware: 'De onderstaande factuurvelden zijn geïmporteerd uit je',
-            disableInvoiceFields: 'Factuurvelden uitschakelen',
-            disableInvoiceFieldsConfirmation: 'Weet je het zeker? Factuurvelden worden uitgeschakeld op facturen.',
-            delete: 'Factuurveld verwijderen',
-            deleteConfirmation: 'Weet je zeker dat je dit factuurveld wilt verwijderen?',
-            findInvoiceField: 'Factuurveld zoeken',
-            nameInputSubtitle: 'Kies een naam voor het factuurveld.',
-            typeInputSubtitle: 'Kies welk type factuurveld je wilt gebruiken.',
-            initialValueInputSubtitle: 'Voer een beginwaarde in om in het factuurveld weer te geven.',
-            listValuesInputSubtitle: 'Deze waarden verschijnen in de vervolgkeuzelijst van je factuurveld. Ingeschakelde waarden kunnen door leden worden geselecteerd.',
-            listInputSubtitle: 'Deze waarden verschijnen in je factuurveldenlijst. Ingeschakelde waarden kunnen door leden worden geselecteerd.',
-            emptyInvoiceFieldsValues: {
-                title: 'Nog geen lijstwaarden',
-                subtitle: 'Voeg aangepaste waarden toe om op facturen te tonen.',
-            },
-            existingInvoiceFieldNameError: 'Er bestaat al een factuurveld met deze naam',
-            invoiceFieldNameRequiredError: 'Voer een naam voor een factuurveld in',
-            invoiceFieldTypeRequiredError: 'Kies een veldtype voor de factuur',
-            invoiceFieldInitialValueRequiredError: 'Kies een beginwaarde voor een factuurveld',
-            addField: 'Veld toevoegen',
-        },
         tags: {
             tagName: 'Tagnaam',
             requiresTag: 'Leden moeten alle uitgaven taggen',
@@ -6237,8 +6247,8 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 other: 'Leden maken',
             }),
             makeAdmin: () => ({
-                one: 'Admin maken',
-                other: 'Beheerders maken',
+                one: 'Workspace-beheerder maken',
+                other: 'Workspace-beheerders maken',
             }),
             makeAuditor: () => ({
                 one: 'Auditeur maken',
@@ -6267,12 +6277,14 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} heeft een openstaand rapport in verwerking waarop actie moet worden ondernomen. Vraag hen dit vereiste actiepunt af te ronden voordat je hen uit de workspace verwijdert.`,
             allMembers: 'Alle leden',
-            admins: 'Beheerders',
+            admins: 'Workspace-beheerders',
             approvers: 'Fiatteurs',
             auditors: 'Accountants',
             emptyRoleFilter: {title: 'Geen leden komen overeen met dit filter', subtitle: 'Nodig een lid uit of wijzig het filter hierboven.'},
             configureHRSync: (providerName: string) => `Stel ${providerName}-synchronisatie in.`,
             syncWithHR: (providerName: string) => `Synchroniseren met ${providerName}`,
+            makeCardAdmin: () => ({one: 'Kaartbeheerder maken', other: 'Kaartbeheerders maken'}),
+            cardAdmins: 'Kaartbeheerders',
         },
         card: {
             getStartedIssuing: 'Begin met het uitgeven van je eerste virtuele of fysieke kaart.',
@@ -6689,6 +6701,10 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             }),
             enableRate: 'Tarief inschakelen',
             status: 'Status',
+            statusActive: 'Actief',
+            statusFuture: 'Toekomstig',
+            statusExpired: 'Verlopen',
+            statusInactive: 'Inactief',
             unit: 'Eenheid',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Belastingen moeten in de workspace zijn ingeschakeld om deze functie te gebruiken. Ga naar <a href="#">Meer functies</a> om dat te wijzigen.</muted-text>',
@@ -6815,12 +6831,6 @@ Weet je zeker dat je ze opnieuw wilt exporteren?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Rapportvelden zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Factuurvelden',
-                description: `Met factuurvelden kun je extra gegevens op factuurniveau toevoegen aan facturen.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Factuurvelden zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Profiteer van automatische synchronisatie en verminder handmatige invoer met de Expensify + NetSuite-integratie. Krijg diepgaande realtime financiële inzichten met ondersteuning voor native en aangepaste segmenten, inclusief project- en klanttoewijzing.`,
@@ -6921,12 +6931,6 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Afstandstarieven zijn beschikbaar in het Collect-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditor',
-                description: 'Auditors krijgen alleen-lezen-toegang tot alle rapporten voor volledige transparantie en nalevingsbewaking.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Auditors zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Meerdere goedkeuringsniveaus',
                 description:
@@ -7024,6 +7028,12 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Facturatie is beschikbaar in de Collect- en Control-abonnementen, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Beleidsrollen controleren',
+                description: 'Gebruik gespecialiseerde rollen zoals Auditor en Kaartbeheerder om leden alleen toegang te geven tot wat ze nodig hebben.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Gespecialiseerde werkruimterollen zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actief lid per maand.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -7349,6 +7359,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 deleteRuleConfirmation: 'Weet je zeker dat je deze regel wilt verwijderen?',
                 describeRuleTitle: 'Beschrijf je regel',
                 describeRuleSubtitle: 'Beschrijf je regel en Concierge maakt hem voor je',
+                disclaimer: 'AI-agents kunnen fouten maken.',
             },
         },
         planTypePage: {
@@ -8027,21 +8038,19 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} van ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `heeft het standaardbelastingtarief van de categorie "${categoryName}" gewijzigd naar "${newTax}" (voorheen "${oldTax}")`,
         addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `heeft tarief „${rateName}” van ${rateValue} toegevoegd`,
         addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `tarief "${rateName}" van ${rateValue} toegevoegd, geldig vanaf ${startDate}`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `heeft tarief „${rateName}” van ${rateValue} toegevoegd, geldig tot ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `heeft tarief "${rateName}" van ${rateValue} toegevoegd, geldig van ${startDate} - ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `startdatum van tarief "${rateName}" bijgewerkt naar ${newDate} (voorheen ${oldDate})` : `startdatum van tarief "${rateName}" instellen op ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `einddatum van tarief "${rateName}" bijgewerkt naar ${newDate} (voorheen ${oldDate})` : `einddatum van tarief "${rateName}" instellen op ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `start- en einddatum van tarief "${rateName}" bijgewerkt naar ${newStartDate} - ${newEndDate} (voorheen ${oldStartDate} - ${oldEndDate})`
-                : `start- en einddatum van tarief "${rateName}" ingesteld op ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `startdatum verwijderd van tarief "${rateName}" (voorheen ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `einddatum verwijderd van tarief "${rateName}" (voorheen ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `heeft het kilometertarief "${rateName}" bijgewerkt zodat het geldt van ${newDateRange} (voorheen ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `vanaf ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `tot ${date}`,
+        customUnitRateDateRangeAllDates: () => `voor alle data`,
     },
     roomMembersPage: {
         memberNotFound: 'Lid niet gevonden.',
@@ -8482,8 +8491,11 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                     `De verbinding met ${feedName} is verbroken. <a href='${workspaceCompanyCardRoute}'>Log in bij je bank</a> om kaartimports te herstellen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${role === 'member' ? 'een' : 'een'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'een' : 'een';
+                    return didJoinPolicy ? `${email} is lid geworden via de uitnodigingslink voor de workspace` : `${email} toegevoegd als ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `heeft de rol van ${email} bijgewerkt naar ${newRole} (voorheen ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
@@ -9379,6 +9391,11 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Als <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copiloot</a> voor ${accountOwnerEmail} heb je geen toestemming om deze actie uit te voeren. Sorry!`,
+        removeCopilotAccess: 'Mijn copilot-toegang verwijderen',
+        removeCopilotAccessTitle: 'Copilot-toegang verwijderen?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Weet je zeker dat je je copilot-toegang tot het Expensify-account van ${delegatorName} wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.`,
+        removeCopilotAccessConfirm: 'Toegang verwijderen',
         copilotAccess: 'Copilot-toegang',
     },
     debug: {
diff --git a/src/languages/params.ts b/src/languages/params.ts
index 41610783b027..b9c0884faab4 100644
--- a/src/languages/params.ts
+++ b/src/languages/params.ts
@@ -102,6 +102,8 @@ type SyncStageNameConnectionsParams = {stage: PolicyConnectionSyncStage};
 
 type DelegateRoleParams = {role: DelegateRole};
 
+type RemoveCopilotAccessConfirmationParams = {delegatorName: string};
+
 type RemovedFromApprovalWorkflowParams = {
     submittersNames: string[];
 };
@@ -135,6 +137,7 @@ export type {
     InvalidValueParams,
     RemovedFromApprovalWorkflowParams,
     DelegateRoleParams,
+    RemoveCopilotAccessConfirmationParams,
     SyncStageNameConnectionsParams,
     IntacctMappingTitleParams,
     ExportIntegrationSelectedParams,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 29f9591d54bf..9a6d8b988c7b 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -108,7 +109,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Wielokrotny wybór',
         saveChanges: 'Zapisz zmiany',
         submit: 'Wyślij',
+        markAsDone: 'Oznacz jako wykonane',
         submitted: 'Przesłano',
+        markedAsDoneStatus: 'Oznaczone jako ukończone',
         rotate: 'Obróć',
         zoom: 'Powiększenie',
         password: 'Hasło',
@@ -293,7 +296,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Opis',
         title: 'Tytuł',
         assignee: 'Osoba przypisana',
-        createdBy: 'Utworzone przez',
         with: 'z',
         shareCode: 'Udostępnij kod',
         share: 'Udostępnij',
@@ -314,6 +316,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Sprzedawca',
         change: 'Zmień',
         category: 'Kategoria',
+        vendor: 'Dostawca',
         report: 'Raport',
         billable: 'Fakturowalne',
         nonBillable: 'Nierozliczalne',
@@ -355,6 +358,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Znajdź czat za pomocą',
             subtitleText2: 'przycisk powyżej lub utwórz coś za pomocą',
             subtitleText3: 'przycisk poniżej.',
+            noUnreadChats: 'Brak nieprzeczytanych czatów',
+            noTodos: 'Brak zadań',
+            caughtUp: 'Ze wszystkim już się uporałeś. Dobra robota!',
+            seeAllChats: 'Zobacz wszystkie czaty',
         },
         businessName: 'Nazwa firmy',
         clear: 'Wyczyść',
@@ -853,6 +860,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Ten czat jest z ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `Tutaj <strong>${submitterDisplayName}</strong> będzie przesyłać wydatki do <strong>${workspaceName}</strong>. Po prostu użyj przycisku +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Tutaj będziesz śledzić wydatki',
         beginningOfChatHistorySelfDM: 'To Twoja osobista przestrzeń. Używaj jej na notatki, zadania, szkice i przypomnienia.',
         beginningOfChatHistorySystemDM: 'Witamy! Zacznijmy konfigurację.',
         chatWithAccountManager: 'Porozmawiaj tutaj z opiekunem konta',
@@ -959,7 +967,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Napraw połączenie z prywatną kartą ${cardName}` : 'Napraw połączenie karty prywatnej'),
                 subtitle: 'Portfel',
             },
-            validateAccount: {title: 'Zweryfikuj swoje konto, aby dalej korzystać z Expensify', subtitle: 'Konto', cta: 'Zatwierdź'},
+            validateAccount: {title: 'Zweryfikuj swoje konto', subtitle: 'Konto', cta: 'Zatwierdź'},
             fixFailedBilling: {title: 'Nie mogliśmy obciążyć zapisanej karty', subtitle: 'Subskrypcja'},
             unlockBankAccount: {
                 workspaceTitle: 'Twoje firmowe konto bankowe zostało zablokowane',
@@ -1014,6 +1022,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Wszystko nadrobione',
                 f1FlagsDescription: 'Ukończyłeś wszystkie zaległe zadania.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Przejrzyj ${count} ${count === 1 ? 'wydatek' : 'wydatki'}`,
         },
         upcomingTravel: 'Nadchodząca podróż',
         upcomingTravelSection: {
@@ -1347,6 +1356,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Wyślij fakturę na ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `za ${comment}` : ''}`,
         submitted: (memo?: string) => `przesłano${memo ? `, wpisując ${memo}` : ''}`,
+        markedAsDone: (memo) => `oznaczono jako zakończone${memo ? `, z adnotacją: ${memo}` : ''}`,
         automaticallySubmitted: `przesłano przez <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">opóźnianie wysyłania</a>`,
         queuedToSubmitViaDEW: 'w kolejce do przesłania przez niestandardowy proces zatwierdzania',
         queuedToApproveViaDEW: 'oczekuje na zatwierdzenie w niestandardowym procesie akceptacji',
@@ -1559,6 +1569,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'usunięto',
         transactionPending: 'Transakcja w toku.',
         chooseARate: 'Wybierz stawkę zwrotu kosztów za milę lub kilometr dla przestrzeni roboczej',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} do ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Ważne od ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Ważne do ${endDate}`,
         unapprove: 'Cofnij zatwierdzenie',
         unapproveReport: 'Cofnij zatwierdzenie raportu',
         headsUp: 'Uwaga!',
@@ -1659,6 +1672,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Napraw błąd stawki i spróbuj ponownie.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Wyjaśnij<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge dopasował ten wydatek do <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError:
             'Nie możesz duplikować wydatków z tytułu diet między przestrzeniami roboczymi, ponieważ stawki mogą się różnić między poszczególnymi przestrzeniami.',
         rulesModifiedFields: {
@@ -1788,6 +1802,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Oczekiwanie, aż administrator złoży wydatki.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Czekamy, aż <strong>Ty</strong> oznaczysz to jako wykonane.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Oczekiwanie, aż <strong>${actor}</strong> oznaczy to jako wykonane.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Oczekiwanie, aż administrator oznaczy to jako wykonane.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
@@ -2221,10 +2250,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Zgłoś podejrzaną aktywność',
         lockAccount: 'Zablokuj konto',
+        lockMyAccount: 'Zablokuj moje konto',
         unlockAccount: 'Odblokuj konto',
-        compromisedDescription:
-            'Zauważyłeś coś niepokojącego na swoim koncie? Zgłoszenie tego natychmiast zablokuje twoje konto, wstrzyma nowe transakcje Kartą Expensify i uniemożliwi wprowadzanie jakichkolwiek zmian na koncie.',
-        domainAdminsDescription: 'Dla administratorów domen: to również wstrzymuje całą aktywność Kart Expensify i działania administracyjne w twoich domenach.',
+        findYourSituation: 'Większość problemów nie wymaga blokowania konta! Znajdź swoją sytuację poniżej:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Zgubiona karta lub nieznane obciążenia</a>: Anuluj swoją kartę i skontaktuj się z Concierge, żeby zakwestionować nieznane transakcje.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Nieautoryzowany dostęp do konta</a>: Zablokuj swoje konto poniżej. To zablokuje nowe transakcje Kartą Expensify, zamówienia kart i zmiany na koncie. Jeśli jesteś administratorem domeny, to wstrzyma też całą aktywność kart i działania administratorów w obrębie domeny.',
+        securityTeamFollowUp: 'Nasz zespół ds. bezpieczeństwa skontaktuje się z tobą z adresu <a href="mailto:risk@expensify.com">risk@expensify.com</a> po zablokowaniu.',
         areYouSure: 'Czy na pewno chcesz zablokować swoje konto Expensify?',
         onceLocked: 'Po zablokowaniu Twoje konto będzie ograniczone do czasu złożenia prośby o odblokowanie i przeprowadzenia kontroli bezpieczeństwa',
         unlockTitle: 'Otrzymaliśmy Twoją prośbę',
@@ -2588,13 +2621,10 @@ ${amount} dla ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `wydatki od ${members}, a zatwierdzającym jest ${approvers}`,
         addApprovalButton: 'Dodaj proces akceptacji',
         editWorkflowAction: 'Edytuj',
-        addAgentAction: 'Dodaj agenta',
         findWorkflow: 'Znajdź przepływ pracy',
         addApprovalTip: 'Domyślny proces pracy ma zastosowanie do wszystkich członków, chyba że istnieje bardziej szczegółowy proces pracy.',
         approver: 'Osoba zatwierdzająca',
         addApprovalsDescription: 'Wymagaj dodatkowej akceptacji przed autoryzacją płatności.',
-        automateApprovalsWithAgentsTitle: 'Automatyzuj zatwierdzanie z agentami',
-        automateApprovalsWithAgentsSubtitle: 'Dodaj agenta poniżej do przepływu pracy, aby zautomatyzować zatwierdzanie.',
         makeOrTrackPaymentsTitle: 'Płatności',
         makeOrTrackPaymentsDescription: 'Dodaj upoważnionego płatnika dla płatności dokonywanych w Expensify lub śledź płatności wykonywane gdzie indziej.',
         customApprovalWorkflowEnabled:
@@ -2888,6 +2918,12 @@ ${amount} dla ${merchant} - ${date}`,
             },
         },
     },
+    focusModeUpdateModal: {
+        title: 'Witaj w trybie #focus!',
+        prompt: (priorityModePageUrl: string) =>
+            `Bądź na bieżąco, widząc tylko nieprzeczytane czaty lub czaty wymagające twojej uwagi. Spokojnie, możesz to zmienić w dowolnym momencie w <a href="${priorityModePageUrl}">ustawieniach</a>.`,
+    },
+    inboxTabs: {all: 'Wszystko', todo: 'Zadania do wykonania', unread: 'Nieprzeczytane'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `w ${policyName}`,
         generatingPDF: 'Wygeneruj PDF',
@@ -3447,11 +3483,6 @@ ${amount} dla ${merchant} - ${date}`,
         year: 'Rok',
         selectYear: 'Wybierz rok',
     },
-    focusModeUpdateModal: {
-        title: 'Witamy w trybie #focus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Miej wszystko pod kontrolą, wyświetlając tylko nieprzeczytane czaty lub czaty wymagające Twojej uwagi. Nie martw się, możesz to zmienić w dowolnym momencie w <a href="${priorityModePageUrl}">ustawieniach</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'Nie można znaleźć czatu, którego szukasz.',
         getMeOutOfHere: 'Wyprowadź mnie stąd',
@@ -4112,27 +4143,30 @@ ${amount} dla ${merchant} - ${date}`,
         verificationFailed: 'Weryfikacja nie powiodła się, dlatego potrzebujemy dodatkowych dokumentów do potwierdzenia Twojej tożsamości i firmy',
         taxIDVerification: 'Weryfikacja numeru podatkowego',
         taxIDVerificationDescription: dedent(`
-        Prześlij jeden z poniższych plików:
-        • List przydziału TIN/EIN z IRS
-        • Potwierdzenie wniosku TIN/EIN z IRS (zwykle zawiera „Congratulations! The EIN has been successfully assigned”)
-        • Pismo o zwolnieniu podatkowym z IRS zawierające nazwę firmy i EIN`),
+            Prześlij jeden z poniższych plików:
+            • List przydziału TIN/EIN z IRS
+            • Potwierdzenie wniosku TIN/EIN z IRS (zwykle zawiera „Congratulations! The EIN has been successfully assigned”)
+            • Pismo o zwolnieniu podatkowym z IRS zawierające nazwę firmy i EIN
+        `),
         nameChangeDocument: 'Dokument zmiany nazwy',
         nameChangeDocumentDescription: 'Jeśli nazwa firmy zmieniła się od momentu złożenia wniosku o TIN/EIN, dokument ten jest wymagany do weryfikacji podanego numeru podatkowego',
         companyAddressVerification: 'Weryfikacja adresu firmy',
         companyAddressVerificationDescription: dedent(`
-        Prześlij jeden z poniższych plików:
-        • Aktualny rachunek za media z nazwą i adresem firmy
-        • Wyciąg bankowy z nazwą i adresem firmy
-        • Aktualna umowa najmu z podpisaną stroną zawierającą nazwę i adres firmy
-        • Dokument ubezpieczeniowy z nazwą i adresem firmy
-        • Dokument przydziału TIN z nazwą i adresem firmy`),
+            Prześlij jeden z poniższych plików:
+            • Aktualny rachunek za media z nazwą i adresem firmy
+            • Wyciąg bankowy z nazwą i adresem firmy
+            • Aktualna umowa najmu z podpisaną stroną zawierającą nazwę i adres firmy
+            • Dokument ubezpieczeniowy z nazwą i adresem firmy
+            • Dokument przydziału TIN z nazwą i adresem firmy
+        `),
         userAddressVerification: 'Weryfikacja adresu',
         userAddressVerificationDescription: dedent(`
-        Prześlij jeden z poniższych plików:
-        • Karta rejestracji wyborcy
-        • Prawo jazdy
-        • Wyciąg bankowy
-        • Rachunek za media`),
+            Prześlij jeden z poniższych plików:
+            • Karta rejestracji wyborcy
+            • Prawo jazdy
+            • Wyciąg bankowy
+            • Rachunek za media
+        `),
         userDOBVerification: 'Weryfikacja daty urodzenia',
         userDOBVerificationDescription: 'Prześlij dokument tożsamości wydany w USA',
         finishViaChat: 'Zakończ przez czat',
@@ -4313,7 +4347,6 @@ ${amount} dla ${merchant} - ${date}`,
             customFieldHint: 'Dodaj niestandardowe kodowanie, które będzie stosowane do wszystkich wydatków tego członka.',
             reports: 'Raporty',
             reportFields: 'Pola raportu',
-            invoiceFields: 'Pola faktury',
             reportTitle: 'Tytuł raportu',
             reportField: 'Pole raportu',
             taxes: 'Podatki',
@@ -4397,7 +4430,7 @@ ${amount} dla ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrator';
+                        return 'Administrator przestrzeni roboczej';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Audytor';
                     case CONST.POLICY.ROLE.EDITOR:
@@ -5987,29 +6020,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             reportFieldInitialValueRequiredError: 'Wybierz początkową wartość pola raportu',
             genericFailureMessage: 'Wystąpił błąd podczas aktualizowania pola raportu. Spróbuj ponownie.',
         },
-        invoiceFields: {
-            subtitle: 'Pola faktury mogą być pomocne, gdy chcesz dodać dodatkowe informacje.',
-            importedFromAccountingSoftware: 'Poniższe pola faktury są importowane z Twojego',
-            disableInvoiceFields: 'Wyłącz pola faktury',
-            disableInvoiceFieldsConfirmation: 'Czy na pewno? Pola faktury zostaną wyłączone na fakturach.',
-            delete: 'Usuń pole faktury',
-            deleteConfirmation: 'Czy na pewno chcesz usunąć to pole faktury?',
-            findInvoiceField: 'Znajdź pole faktury',
-            nameInputSubtitle: 'Wybierz nazwę pola faktury.',
-            typeInputSubtitle: 'Wybierz typ pola faktury, którego chcesz użyć.',
-            initialValueInputSubtitle: 'Wprowadź wartość początkową, która ma być wyświetlana w polu faktury.',
-            listValuesInputSubtitle: 'Te wartości pojawią się na liście rozwijanej pola faktury. Członkowie mogą wybierać włączone wartości.',
-            listInputSubtitle: 'Te wartości pojawią się na liście pola faktury. Członkowie mogą wybierać włączone wartości.',
-            emptyInvoiceFieldsValues: {
-                title: 'Brak wartości listy',
-                subtitle: 'Dodaj niestandardowe wartości, które mają pojawiać się na fakturach.',
-            },
-            existingInvoiceFieldNameError: 'Pole faktury o tej nazwie już istnieje',
-            invoiceFieldNameRequiredError: 'Wprowadź nazwę pola faktury',
-            invoiceFieldTypeRequiredError: 'Wybierz typ pola faktury',
-            invoiceFieldInitialValueRequiredError: 'Wybierz początkową wartość pola faktury',
-            addField: 'Dodaj pole',
-        },
         tags: {
             tagName: 'Nazwa tagu',
             requiresTag: 'Członkowie muszą otagować wszystkie wydatki',
@@ -6232,8 +6242,8 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 other: 'Utwórz członków',
             }),
             makeAdmin: () => ({
-                one: 'Ustaw jako administratora',
-                other: 'Ustaw jako administratorów',
+                one: 'Ustaw jako administratora przestrzeni roboczej',
+                other: 'Ustaw jako administratorów przestrzeni roboczej',
             }),
             makeAuditor: () => ({
                 one: 'Ustaw jako audytora',
@@ -6262,12 +6272,14 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} ma nierozliczony raport w trakcie przetwarzania, który wymaga działania. Poproś tę osobę o wykonanie wymaganej czynności przed jej usunięciem z przestrzeni roboczej.`,
             allMembers: 'Wszyscy członkowie',
-            admins: 'Administratorzy',
+            admins: 'Administratorzy przestrzeni roboczej',
             approvers: 'Osoby zatwierdzające',
             auditors: 'Audytorzy',
             emptyRoleFilter: {title: 'Żadni członkowie nie pasują do tego filtra', subtitle: 'Zaproś członka lub zmień filtr powyżej.'},
             configureHRSync: (providerName: string) => `Skonfiguruj synchronizację ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchronizuj z ${providerName}`,
+            makeCardAdmin: () => ({one: 'Ustaw jako administratora karty', other: 'Ustaw administratorów kart'}),
+            cardAdmins: 'Administratorzy kart',
         },
         card: {
             getStartedIssuing: 'Zacznij od wydania swojej pierwszej wirtualnej lub fizycznej karty.',
@@ -6682,6 +6694,10 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             }),
             enableRate: 'Włącz stawkę',
             status: 'Status',
+            statusActive: 'Aktywna',
+            statusFuture: 'Przyszła',
+            statusExpired: 'Wygasła',
+            statusInactive: 'Nieaktywna',
             unit: 'Jednostka',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Aby korzystać z tej funkcji, włącz podatki w przestrzeni roboczej. Przejdź do sekcji <a href="#">Więcej funkcji</a>, aby to zmienić.</muted-text>',
@@ -6808,12 +6824,6 @@ Czy na pewno chcesz wyeksportować je ponownie?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Pola raportu są dostępne tylko w planie Control, od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Pola faktury',
-                description: `Pola faktury pozwalają dodać dodatkowe szczegóły na poziomie faktury.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Pola faktury są dostępne tylko w planie Control, od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Korzystaj z automatycznej synchronizacji i ograniczaj ręczne wprowadzanie danych dzięki integracji Expensify + NetSuite. Uzyskaj dogłębny, aktualny w czasie rzeczywistym wgląd w finanse dzięki obsłudze natywnych i niestandardowych segmentów, w tym mapowaniu projektów i klientów.`,
@@ -6915,12 +6925,6 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Stawki za przejazdy są dostępne w planie Collect, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Audytor',
-                description: 'Biegli rewidentci otrzymują dostęp tylko do odczytu do wszystkich raportów, aby zapewnić pełną widoczność i monitorowanie zgodności.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Audytorzy są dostępni tylko w planie Control, zaczynającym się od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Wiele poziomów zatwierdzania',
                 description:
@@ -7020,6 +7024,12 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Fakturowanie jest dostępne w planach Collect i Control, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Role zasad kontroli',
+                description: 'Użyj wyspecjalizowanych ról, takich jak Audytor i Administrator kart, żeby dać członkom dostęp tylko do tego, czego potrzebują.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Specjalistyczne role w przestrzeni roboczej są dostępne tylko w planie Control, od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka miesięcznie.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -7342,6 +7352,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 deleteRuleConfirmation: 'Na pewno chcesz usunąć tę regułę?',
                 describeRuleTitle: 'Opisz swoją regułę',
                 describeRuleSubtitle: 'Opisz swoją regułę, a Concierge ją utworzy',
+                disclaimer: 'Agenci AI mogą popełniać błędy.',
             },
         },
         planTypePage: {
@@ -8019,22 +8030,20 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} z ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `zmienił(a) domyślną stawkę podatku dla kategorii „${categoryName}” na „${newTax}” (wcześniej „${oldTax}”)`,
         addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `dodano stawkę „${rateName}” w wysokości ${rateValue}`,
         addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) =>
             `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą od ${startDate}`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą do ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą od ${startDate} do ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `zaktualizowano datę rozpoczęcia stawki „${rateName}” na ${newDate} (wcześniej ${oldDate})` : `ustaw datę rozpoczęcia stawki „${rateName}” na ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `zaktualizowano datę końcową stawki „${rateName}” na ${newDate} (wcześniej ${oldDate})` : `ustaw datę zakończenia stawki „${rateName}” na ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `zaktualizowano datę początkową i końcową stawki „${rateName}” na ${newStartDate} – ${newEndDate} (wcześniej ${oldStartDate} – ${oldEndDate})`
-                : `ustaw początkową i końcową datę stawki „${rateName}” na ${newStartDate} – ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `usunięto datę początkową ze stawki „${rateName}” (wcześniej ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `usunięto datę zakończenia ze stawki „${rateName}” (wcześniej ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `zaktualizowano stawkę za dystans „${rateName}”, aby obowiązywała ${newDateRange} (wcześniej ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `od ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `do ${date}`,
+        customUnitRateDateRangeAllDates: () => `dla wszystkich dat`,
     },
     roomMembersPage: {
         memberNotFound: 'Nie znaleziono członka.',
@@ -8474,8 +8483,11 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                     `Połączenie ${feedName} jest przerwane. Aby przywrócić importy kart, <a href='${workspaceCompanyCardRoute}'>zaloguj się do swojego banku</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} dołączył(a) przez link z zaproszeniem do przestrzeni roboczej` : `dodano ${email} jako ${role === 'member' ? 'a' : 'jeden'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'a';
+                    return didJoinPolicy ? `${email} dołączył za pomocą linku z zaproszeniem do przestrzeni roboczej` : `dodano ${email} jako ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `zaktualizowano rolę użytkownika ${email} na ${newRole} (wcześniej ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
@@ -9364,6 +9376,11 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Jako <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">kopilot</a> dla ${accountOwnerEmail} nie masz uprawnień do wykonania tej akcji. Przepraszamy!`,
+        removeCopilotAccess: 'Usuń mój dostęp kopilota',
+        removeCopilotAccessTitle: 'Usunąć dostęp kopilota?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Czy na pewno chcesz usunąć swój dostęp kopilota do konta Expensify użytkownika ${delegatorName}? Tej czynności nie można cofnąć.`,
+        removeCopilotAccessConfirm: 'Usuń dostęp',
         copilotAccess: 'Dostęp do Copilota',
     },
     debug: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index aa19d8aceaf8..0e1b4717bb76 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -108,7 +109,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Seleção múltipla',
         saveChanges: 'Salvar alterações',
         submit: 'Enviar',
+        markAsDone: 'Marcar como concluído',
         submitted: 'Enviado',
+        markedAsDoneStatus: 'Marcado como concluído',
         rotate: 'Girar',
         zoom: 'Zoom',
         password: 'Senha',
@@ -293,7 +296,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Descrição',
         title: 'Título',
         assignee: 'Responsável',
-        createdBy: 'Criado por',
         with: 'com',
         shareCode: 'Compartilhar código',
         share: 'Compartilhar',
@@ -314,6 +316,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Estabelecimento',
         change: 'Alterar',
         category: 'Categoria',
+        vendor: 'Fornecedor',
         report: 'Relatório',
         billable: 'Faturável',
         nonBillable: 'Não faturável',
@@ -355,6 +358,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Encontre um chat usando o',
             subtitleText2: 'botão acima ou crie algo usando o',
             subtitleText3: 'botão abaixo.',
+            noUnreadChats: 'Nenhum chat não lido',
+            noTodos: 'Nenhuma tarefa pendente',
+            caughtUp: 'Você está em dia. Muito bem!',
+            seeAllChats: 'Ver todas as conversas',
         },
         businessName: 'Nome da empresa',
         clear: 'Limpar',
@@ -852,6 +859,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Este chat é com ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `É aqui que <strong>${submitterDisplayName}</strong> enviará despesas para <strong>${workspaceName}</strong>. Basta usar o botão +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'É aqui que você vai acompanhar as despesas',
         beginningOfChatHistorySelfDM: 'Este é o seu espaço pessoal. Use-o para anotações, tarefas, rascunhos e lembretes.',
         beginningOfChatHistorySystemDM: 'Bem-vindo(a)! Vamos fazer a sua configuração.',
         chatWithAccountManager: 'Converse com seu gerente de conta aqui',
@@ -957,7 +965,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Corrigir conexão do cartão pessoal ${cardName}` : 'Corrigir conexão do cartão pessoal'),
                 subtitle: 'Carteira',
             },
-            validateAccount: {title: 'Valide sua conta para continuar usando o Expensify', subtitle: 'Conta', cta: 'Validar'},
+            validateAccount: {title: 'Valide sua conta', subtitle: 'Conta', cta: 'Validar'},
             fixFailedBilling: {title: 'Não foi possível cobrar o cartão cadastrado', subtitle: 'Assinatura'},
             unlockBankAccount: {
                 workspaceTitle: 'Sua conta bancária comercial foi bloqueada',
@@ -1012,6 +1020,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Tudo em dia',
                 f1FlagsDescription: 'Você concluiu todas as tarefas pendentes.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Revisar ${count} ${count === 1 ? 'despesa' : 'despesas'}`,
         },
         upcomingTravel: 'Próximas viagens',
         upcomingTravelSection: {
@@ -1347,6 +1356,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Enviar fatura de ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `para ${comment}` : ''}`,
         submitted: (memo?: string) => `enviado${memo ? `, dizendo ${memo}` : ''}`,
+        markedAsDone: (memo) => `marcado como concluído${memo ? `, dizendo ${memo}` : ''}`,
         automaticallySubmitted: `enviado via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">atrasar envios</a>`,
         queuedToSubmitViaDEW: 'na fila para enviar via fluxo de aprovação personalizado',
         queuedToApproveViaDEW: 'na fila para aprovar via fluxo de aprovação personalizado',
@@ -1558,6 +1568,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'removido',
         transactionPending: 'Transação pendente.',
         chooseARate: 'Selecione uma taxa de reembolso do espaço de trabalho por milha ou quilômetro',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} a ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Válido a partir de ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Válido até ${endDate}`,
         unapprove: 'Reprovar',
         unapproveReport: 'Rejeitar relatório',
         headsUp: 'Atenção!',
@@ -1658,6 +1671,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Corrija o erro de taxa e tente novamente.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explicar<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge associou esta despesa ao fornecedor <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError: 'Você não pode duplicar despesas de diárias entre espaços de trabalho porque as tarifas podem variar entre eles.',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'marcou a despesa como "reembolsável"' : 'marcou a despesa como “não reembolsável”'),
@@ -1785,6 +1799,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Aguardando um administrador enviar as despesas.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Aguardando <strong>você</strong> marcar como concluído.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Aguardando <strong>${actor}</strong> marcar como concluído.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Aguardando um administrador marcar como concluído.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
@@ -2218,10 +2247,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Denunciar atividade suspeita',
         lockAccount: 'Bloquear conta',
+        lockMyAccount: 'Bloquear minha conta',
         unlockAccount: 'Desbloquear conta',
-        compromisedDescription:
-            'Percebeu algo estranho na sua conta? Ao denunciar, sua conta será imediatamente bloqueada, novas transações com o Cartão Expensify serão impedidas e qualquer alteração na conta será bloqueada.',
-        domainAdminsDescription: 'Para admins de domínio: isso também pausa todas as atividades do Cartão Expensify e ações de administração em todo(s) o(s) seu(s) domínio(s).',
+        findYourSituation: 'A maioria dos problemas não exige bloquear sua conta! Encontre sua situação abaixo:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Cartão perdido ou cobranças desconhecidas</a>: Cancele seu cartão e contate o Concierge para contestar transações desconhecidas.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Acesso não autorizado à conta</a>: Bloqueie sua conta abaixo. Isso bloqueia novas transações com o Cartão Expensify, pedidos de cartão e alterações na conta. Se você for admin de domínio, isso também pausa toda a atividade de cartões em todo o domínio e as ações de admin.',
+        securityTeamFollowUp: 'Nossa equipe de segurança vai entrar em contato a partir de <a href="mailto:risk@expensify.com">risk@expensify.com</a> após o bloqueio.',
         areYouSure: 'Tem certeza de que deseja bloquear sua conta Expensify?',
         onceLocked: 'Depois de bloqueada, sua conta ficará restrita até que seja feita uma solicitação de desbloqueio e uma revisão de segurança',
         unlockTitle: 'Recebemos sua solicitação',
@@ -2586,13 +2619,10 @@ ${amount} para ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `despesas de ${members}, e o aprovador é ${approvers}`,
         addApprovalButton: 'Adicionar fluxo de aprovação',
         editWorkflowAction: 'Editar',
-        addAgentAction: 'Adicionar agente',
         findWorkflow: 'Buscar fluxo de trabalho',
         addApprovalTip: 'Este fluxo de trabalho padrão se aplica a todos os membros, a menos que exista um fluxo de trabalho mais específico.',
         approver: 'Aprovador',
         addApprovalsDescription: 'Exigir aprovação adicional antes de autorizar um pagamento.',
-        automateApprovalsWithAgentsTitle: 'Automatize aprovações com agentes',
-        automateApprovalsWithAgentsSubtitle: 'Adicione o agente abaixo ao fluxo de trabalho para automatizar as aprovações.',
         makeOrTrackPaymentsTitle: 'Pagamentos',
         makeOrTrackPaymentsDescription: 'Adicione um pagador autorizado para pagamentos feitos no Expensify ou acompanhe pagamentos feitos em outros lugares.',
         customApprovalWorkflowEnabled:
@@ -2888,6 +2918,12 @@ ${amount} para ${merchant} - ${date}`,
             },
         },
     },
+    focusModeUpdateModal: {
+        title: 'Bem-vindo ao modo #focus!',
+        prompt: (priorityModePageUrl: string) =>
+            `Fique no controle vendo apenas chats não lidos ou que precisam da sua atenção. Não se preocupe, você pode mudar isso a qualquer momento em <a href="${priorityModePageUrl}">configurações</a>.`,
+    },
+    inboxTabs: {all: 'Todos', todo: 'Pendências', unread: 'Não lidas'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `em ${policyName}`,
         generatingPDF: 'Gerar PDF',
@@ -3448,11 +3484,6 @@ ${amount} para ${merchant} - ${date}`,
         year: 'Ano',
         selectYear: 'Selecione um ano',
     },
-    focusModeUpdateModal: {
-        title: 'Bem-vindo ao modo #focus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Mantenha tudo sob controle vendo apenas os chats não lidos ou que precisam da sua atenção. Não se preocupe, você pode alterar isso a qualquer momento em <a href="${priorityModePageUrl}">configurações</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'O chat que você está procurando não foi encontrado.',
         getMeOutOfHere: 'Me tire daqui',
@@ -4112,27 +4143,30 @@ ${amount} para ${merchant} - ${date}`,
         verificationFailed: 'A verificação falhou, então precisaremos de documentos adicionais para verificar você e sua empresa',
         taxIDVerification: 'Verificação de ID fiscal',
         taxIDVerificationDescription: dedent(`
-        Envie um dos seguintes arquivos:
-        • Carta de atribuição de TIN/EIN do IRS
-        • Confirmação de solicitação de TIN/EIN do IRS (normalmente contém "Congratulations! The EIN has been successfully assigned")
-        • Carta de isenção fiscal do IRS com o nome da empresa e o EIN`),
+            Envie um dos seguintes arquivos:
+            • Carta de atribuição de TIN/EIN do IRS
+            • Confirmação de solicitação de TIN/EIN do IRS (normalmente contém "Congratulations! The EIN has been successfully assigned")
+            • Carta de isenção fiscal do IRS com o nome da empresa e o EIN
+        `),
         nameChangeDocument: 'Documento de alteração de nome',
         nameChangeDocumentDescription: 'Se o nome da sua empresa mudou desde a solicitação do TIN/EIN, precisamos deste documento para verificar o número de identificação fiscal informado',
         companyAddressVerification: 'Verificação de endereço da empresa',
         companyAddressVerificationDescription: dedent(`
-        Envie um dos seguintes arquivos:
-        • Conta recente de serviços públicos com nome e endereço da empresa
-        • Extrato bancário com nome e endereço da empresa
-        • Contrato de locação atual incluindo a página de assinatura com nome e endereço atual da empresa
-        • Apólice ou declaração de seguro com nome e endereço da empresa
-        • Documento de atribuição de TIN com nome e endereço da empresa`),
+            Envie um dos seguintes arquivos:
+            • Conta recente de serviços públicos com nome e endereço da empresa
+            • Extrato bancário com nome e endereço da empresa
+            • Contrato de locação atual incluindo a página de assinatura com nome e endereço atual da empresa
+            • Apólice ou declaração de seguro com nome e endereço da empresa
+            • Documento de atribuição de TIN com nome e endereço da empresa
+        `),
         userAddressVerification: 'Verificação de endereço',
         userAddressVerificationDescription: dedent(`
-        Envie um dos seguintes arquivos:
-        • Título de eleitor
-        • Carteira de motorista
-        • Extrato bancário
-        • Conta de serviços públicos`),
+            Envie um dos seguintes arquivos:
+            • Título de eleitor
+            • Carteira de motorista
+            • Extrato bancário
+            • Conta de serviços públicos
+        `),
         userDOBVerification: 'Verificação de data de nascimento',
         userDOBVerificationDescription: 'Envie um documento de identidade emitido nos EUA',
         finishViaChat: 'Finalizar pelo chat',
@@ -4316,7 +4350,6 @@ ${amount} para ${merchant} - ${date}`,
             reportFields: 'Campos do relatório',
             reportTitle: 'Título do relatório',
             reportField: 'Campo de relatório',
-            invoiceFields: 'Campos de fatura',
             taxes: 'Impostos',
             bills: 'Contas',
             invoices: 'Faturas',
@@ -4398,17 +4431,17 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Admin. do workspace';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.EDITOR:
                         return 'Editor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Admin. do Cartão';
+                        return 'Admin. de Cartão';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Administração de pessoas';
+                        return 'Administração de Pessoas';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Admin de pagamentos';
+                        return 'Admin de Pagamentos';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membro';
                     default:
@@ -5992,29 +6025,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             reportFieldInitialValueRequiredError: 'Escolha um valor inicial para o campo de relatório',
             genericFailureMessage: 'Ocorreu um erro ao atualizar o campo do relatório. Tente novamente.',
         },
-        invoiceFields: {
-            subtitle: 'Os campos da fatura podem ser úteis quando você quiser incluir informações extras.',
-            importedFromAccountingSoftware: 'Os campos da fatura abaixo são importados do seu',
-            disableInvoiceFields: 'Desativar campos da fatura',
-            disableInvoiceFieldsConfirmation: 'Tem certeza? Os campos da fatura serão desativados nas faturas.',
-            delete: 'Excluir campo da fatura',
-            deleteConfirmation: 'Tem certeza de que deseja excluir este campo da fatura?',
-            findInvoiceField: 'Encontrar campo da fatura',
-            nameInputSubtitle: 'Escolha um nome para o campo da fatura.',
-            typeInputSubtitle: 'Escolha o tipo de campo da fatura que deseja usar.',
-            initialValueInputSubtitle: 'Insira um valor inicial para mostrar no campo da fatura.',
-            listValuesInputSubtitle: 'Esses valores aparecerão no menu suspenso do campo da fatura. Valores ativados podem ser selecionados pelos membros.',
-            listInputSubtitle: 'Esses valores aparecerão na lista do campo da fatura. Valores ativados podem ser selecionados pelos membros.',
-            emptyInvoiceFieldsValues: {
-                title: 'Ainda não há valores de lista',
-                subtitle: 'Adicione valores personalizados para aparecerem nas faturas.',
-            },
-            existingInvoiceFieldNameError: 'Já existe um campo da fatura com este nome',
-            invoiceFieldNameRequiredError: 'Insira um nome para o campo da fatura',
-            invoiceFieldTypeRequiredError: 'Escolha um tipo de campo da fatura',
-            invoiceFieldInitialValueRequiredError: 'Escolha um valor inicial para o campo da fatura',
-            addField: 'Adicionar campo',
-        },
         tags: {
             tagName: 'Nome da tag',
             requiresTag: 'Membros devem marcar todas as despesas',
@@ -6236,8 +6246,8 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 other: 'Tornar membros',
             }),
             makeAdmin: () => ({
-                one: 'Tornar admin',
-                other: 'Tornar admins',
+                one: 'Tornar admin do workspace',
+                other: 'Tornar admins do workspace',
             }),
             makeAuditor: () => ({
                 one: 'Tornar auditor',
@@ -6266,12 +6276,14 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} tem um relatório pendente de processamento que requer ação. Peça para que concluam a ação necessária antes de removê-los do workspace.`,
             allMembers: 'Todos os membros',
-            admins: 'Administradores',
+            admins: 'Admins do workspace',
             approvers: 'Aprovadores',
             auditors: 'Auditores',
             emptyRoleFilter: {title: 'Nenhum membro corresponde a este filtro', subtitle: 'Convide um membro ou altere o filtro acima.'},
             configureHRSync: (providerName: string) => `Configurar a sincronização do ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar com ${providerName}`,
+            makeCardAdmin: () => ({one: 'Tornar admin do cartão', other: 'Tornar administradores do cartão'}),
+            cardAdmins: 'Administradores de cartões',
         },
         card: {
             getStartedIssuing: 'Comece emitindo seu primeiro cartão virtual ou físico.',
@@ -6687,6 +6699,10 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             }),
             enableRate: 'Ativar tarifa',
             status: 'Status',
+            statusActive: 'Ativo',
+            statusFuture: 'Futuro',
+            statusExpired: 'Expirado',
+            statusInactive: 'Inativo',
             unit: 'Unidade',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Os impostos precisam estar ativados no workspace para usar este recurso. Vá até <a href="#">Mais recursos</a> para fazer essa alteração.</muted-text>',
@@ -6813,12 +6829,6 @@ Tem certeza de que deseja exportá-los novamente?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Os campos de relatório estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Campos de fatura',
-                description: `Os campos da fatura permitem incluir detalhes extras no nível da fatura.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Os campos da fatura estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Aproveite a sincronização automática e reduza lançamentos manuais com a integração Expensify + NetSuite. Obtenha insights financeiros profundos e em tempo real com suporte a segmentos nativos e personalizados, incluindo mapeamento de projetos e clientes.`,
@@ -6919,12 +6929,6 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Tarifas por distância estão disponíveis no plano Collect, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditor',
-                description: 'Auditores têm acesso somente leitura a todos os relatórios para total visibilidade e monitoramento de conformidade.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Auditores estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Múltiplos níveis de aprovação',
                 description:
@@ -7022,6 +7026,12 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>O faturamento está disponível nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Funções da política de controle',
+                description: 'Use funções especializadas como Auditor e Administrador de Cartão para conceder aos membros acesso apenas ao que precisam.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Funções especializadas no espaço de trabalho estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -7348,6 +7358,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 deleteRuleConfirmation: 'Tem certeza de que quer excluir esta regra?',
                 describeRuleTitle: 'Descreva sua regra',
                 describeRuleSubtitle: 'Descreva sua regra e a Concierge vai criá-la',
+                disclaimer: 'Os agentes de IA podem cometer erros.',
             },
         },
         planTypePage: {
@@ -8021,22 +8032,20 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} de ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `alterou a alíquota de imposto padrão da categoria "${categoryName}" para "${newTax}" (antes "${oldTax}")`,
         addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `adicionou a taxa "${rateName}" de ${rateValue}`,
         addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) =>
             `adicionou a taxa "${rateName}" de ${rateValue}, válida a partir de ${startDate}`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `adicionou a taxa "${rateName}" de ${rateValue}, válida até ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `adicionou a tarifa "${rateName}" de ${rateValue}, válida de ${startDate} a ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `atualizou a data de início da tarifa "${rateName}" para ${newDate} (antes ${oldDate})` : `definir data de início da tarifa "${rateName}" para ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `atualizou a data de término da tarifa "${rateName}" para ${newDate} (antes ${oldDate})` : `definir data de término da tarifa "${rateName}" para ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `atualizou a data de início e término da tarifa "${rateName}" para ${newStartDate} - ${newEndDate} (antes ${oldStartDate} - ${oldEndDate})`
-                : `define a data de início e de término da tarifa "${rateName}" para ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `removeu a data de início da tarifa "${rateName}" (antes ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `removeu a data de término da tarifa "${rateName}" (anteriormente ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `atualizou a taxa de distância "${rateName}" para se aplicar a ${newDateRange} (anteriormente ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `de ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `até ${date}`,
+        customUnitRateDateRangeAllDates: () => `para todas as datas`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro não encontrado.',
@@ -8477,8 +8486,11 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                     `A conexão de ${feedName} está interrompida. Para restaurar as importações do cartão, <a href='${workspaceCompanyCardRoute}'>faça login no seu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${role === 'member' ? 'a' : 'um'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'um' : 'um';
+                    return didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `atualizou a função de ${email} para ${newRole} (anteriormente ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
@@ -9372,6 +9384,11 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Como <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copiloto</a> de ${accountOwnerEmail}, você não tem permissão para realizar esta ação. Desculpe!`,
+        removeCopilotAccess: 'Remover meu acesso de copiloto',
+        removeCopilotAccessTitle: 'Remover acesso de copiloto?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Tem certeza de que deseja remover seu acesso de copiloto à conta Expensify de ${delegatorName}? Esta ação não pode ser desfeita.`,
+        removeCopilotAccessConfirm: 'Remover acesso',
         copilotAccess: 'Acesso ao Copilot',
     },
     debug: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 9bb7121b54b8..5d9c083b3282 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -108,7 +109,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: '多选',
         saveChanges: '保存更改',
         submit: '提交',
+        markAsDone: '标记为完成',
         submitted: '已提交',
+        markedAsDoneStatus: '已标记为完成',
         rotate: '旋转',
         zoom: '缩放',
         password: '密码',
@@ -293,7 +296,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: '描述',
         title: '标题',
         assignee: '受托人',
-        createdBy: '创建者',
         with: '与',
         shareCode: '共享代码',
         share: '分享',
@@ -314,6 +316,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: '商户',
         change: '更改',
         category: '类别',
+        vendor: '供应商',
         report: '报表',
         billable: '可计费',
         nonBillable: '不可计费',
@@ -355,6 +358,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: '使用以下方式查找聊天',
             subtitleText2: '上方的按钮，或使用以下内容创建',
             subtitleText3: '下方按钮。',
+            noUnreadChats: '没有未读聊天',
+            noTodos: '没有待办事项',
+            caughtUp: '你已经全部处理完了。干得好！',
+            seeAllChats: '查看所有聊天',
         },
         businessName: '公司名称',
         clear: '清除',
@@ -831,6 +838,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `此聊天对象为 ${users}。`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `这是 <strong>${submitterDisplayName}</strong> 向 <strong>${workspaceName}</strong> 提交报销的地方。只需使用“+”按钮即可。`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: '在这里跟踪你的报销费用',
         beginningOfChatHistorySelfDM: '这是你的个人空间。可在此记录笔记、任务、草稿和提醒事项。',
         beginningOfChatHistorySystemDM: '欢迎！让我们帮你完成设置。',
         chatWithAccountManager: '在这里与您的客户经理聊天',
@@ -928,7 +936,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 defaultSubtitle: '工作区',
                 subtitle: ({policyName}: {policyName: string}) => `${policyName} > 会计`,
             },
-            validateAccount: {title: '验证您的账户以继续使用 Expensify', subtitle: '账户', cta: '验证'},
+            validateAccount: {title: '验证您的账户', subtitle: '账户', cta: '验证'},
             fixFailedBilling: {title: '我们无法向您档案中的银行卡收费', subtitle: '订阅'},
             unlockBankAccount: {
                 workspaceTitle: '您的企业银行账户已被锁定',
@@ -983,6 +991,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: '全部完成',
                 f1FlagsDescription: '你已完成所有未完成的待办事项。',
             },
+            reviewExpenses: ({count}: {count: number}) => `审核 ${count} ${count === 1 ? '费用' : '费用'}`,
         },
         upcomingTravel: '即将出行',
         upcomingTravelSection: {
@@ -1306,6 +1315,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `发送 ${amount} 发票`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `用于 ${comment}` : ''}`,
         submitted: (memo?: string) => `已提交${memo ? `，备注为 ${memo}` : ''}`,
+        markedAsDone: (memo) => `标记为已完成${memo ? `，说明：${memo}` : ''}`,
         automaticallySubmitted: `通过<a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">延迟提交</a>提交`,
         queuedToSubmitViaDEW: '已排队，待通过自定义审批流程提交',
         queuedToApproveViaDEW: '已排队，等待通过自定义审批流程批准',
@@ -1515,6 +1525,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: '已移除',
         transactionPending: '交易处理中。',
         chooseARate: '选择工作区每英里或每公里的报销费率',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} 至 ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `有效期自 ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `有效期至 ${endDate}`,
         unapprove: '取消批准',
         unapproveReport: '取消批准报销单',
         headsUp: '注意！',
@@ -1613,6 +1626,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: '修复费率错误后请重试。',
         AskToExplain: `。<a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">说明<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge 已将此支出匹配到<strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError: '您无法在不同工作区之间复制每日津贴报销，因为各工作区的补贴标准可能不同。',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? '将该报销单标记为“可报销”' : '将该报销单标记为“不可报销”'),
@@ -1736,6 +1750,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `正在等待管理员提交报销。`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `正在等待<strong>你</strong>标记为完成。`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `正在等待<strong>${actor}</strong>标记为完成。`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `正在等待管理员标记为完成。`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
@@ -2166,9 +2195,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: '举报可疑活动',
         lockAccount: '锁定账户',
+        lockMyAccount: '锁定我的账户',
         unlockAccount: '解锁账户',
-        compromisedDescription: '发现账户有异常？提交报告后将立即锁定账户、阻止新的 Expensify 卡交易，并禁止任何账户更改。',
-        domainAdminsDescription: '针对域管理员：这也会暂停您所有域中的所有 Expensify 卡活动和管理员操作。',
+        findYourSituation: '大多数问题都不需要锁定你的账户！请在以下列表中找到与你相符的情况：',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">卡片遗失或出现不明扣款</a>：请挂失您的卡片，并联系 Concierge 申诉未知交易。',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">未经授权的账号访问</a>：请在下方锁定你的账号。这将阻止新的 Expensify 卡交易、卡片申请和账号更改。如果你是域管理员，这也会暂停整个域的所有卡片活动和管理员操作。',
+        securityTeamFollowUp: '锁定后，我们的安全团队将通过 <a href="mailto:risk@expensify.com">risk@expensify.com</a> 与您后续联系。',
         areYouSure: '你确定要锁定你的 Expensify 账户吗？',
         onceLocked: '一旦被锁定，您的账户将受到限制，直至提交解锁请求并完成安全审查',
         unlockTitle: '我们已收到您的请求',
@@ -2521,13 +2555,10 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `来自${members}的报销，审批人是${approvers}`,
         addApprovalButton: '添加审批工作流',
         editWorkflowAction: '编辑',
-        addAgentAction: '添加代理',
         findWorkflow: '查找工作流',
         addApprovalTip: '除非存在更具体的工作流程，否则此默认工作流程适用于所有成员。',
         approver: '审批人',
         addApprovalsDescription: '在付款前需要额外审批。',
-        automateApprovalsWithAgentsTitle: '使用代理自动化审批',
-        automateApprovalsWithAgentsSubtitle: '在下方添加代理到工作流程中以自动化审批。',
         makeOrTrackPaymentsTitle: '付款',
         makeOrTrackPaymentsDescription: '为在 Expensify 中进行的付款添加授权付款人，或跟踪在其他地方进行的付款。',
         customApprovalWorkflowEnabled:
@@ -2815,6 +2846,11 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             },
         },
     },
+    focusModeUpdateModal: {
+        title: '欢迎使用 #focus 模式！',
+        prompt: (priorityModePageUrl: string) => `通过只查看未读聊天或需要你关注的聊天，随时掌握最新进展。别担心，你可以随时在<a href="${priorityModePageUrl}">设置</a>中更改此项。`,
+    },
+    inboxTabs: {all: '全部', todo: '待办事项', unread: '未读'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `在 ${policyName} 中`,
         generatingPDF: '生成 PDF',
@@ -3372,10 +3408,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         year: '年份',
         selectYear: '请选择年份',
     },
-    focusModeUpdateModal: {
-        title: '欢迎进入 #focus 模式！',
-        prompt: (priorityModePageUrl: string) => `通过仅查看未读聊天或需要你关注的聊天来随时掌握进展。别担心，你可以随时在<a href="${priorityModePageUrl}">设置</a>中更改此项。`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: '找不到您要查找的聊天。',
         getMeOutOfHere: '带我离开这里',
@@ -4024,27 +4056,30 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         verificationFailed: '验证失败，因此我们需要额外的文件来验证你及你的企业',
         taxIDVerification: '税务识别号验证',
         taxIDVerificationDescription: dedent(`
-        请上传以下任一文件：
-        • IRS TIN/EIN 分配函
-        • IRS TIN/EIN 申请确认函（通常包含“Congratulations! The EIN has been successfully assigned”）
-        • 显示公司名称和 EIN 的 IRS 免税函`),
+            请上传以下任一文件：
+            • IRS TIN/EIN 分配函
+            • IRS TIN/EIN 申请确认函（通常包含“Congratulations! The EIN has been successfully assigned”）
+            • 显示公司名称和 EIN 的 IRS 免税函
+        `),
         nameChangeDocument: '名称变更文件',
         nameChangeDocumentDescription: '如果你的公司名称在申请 TIN/EIN 后发生更改，我们需要此文件来验证你提供的税务识别号',
         companyAddressVerification: '公司地址验证',
         companyAddressVerificationDescription: dedent(`
-        请上传以下任一文件：
-        • 显示公司名称和地址的近期水电账单
-        • 显示公司名称和地址的银行对账单
-        • 包含签字页的有效租赁协议，显示公司名称和当前地址
-        • 显示公司名称和地址的保险声明
-        • 显示公司名称和地址的 TIN 分配文件`),
+            请上传以下任一文件：
+            • 显示公司名称和地址的近期水电账单
+            • 显示公司名称和地址的银行对账单
+            • 包含签字页的有效租赁协议，显示公司名称和当前地址
+            • 显示公司名称和地址的保险声明
+            • 显示公司名称和地址的 TIN 分配文件
+        `),
         userAddressVerification: '地址验证',
         userAddressVerificationDescription: dedent(`
-        请上传以下任一文件：
-        • 选民登记卡
-        • 驾驶证
-        • 银行对账单
-        • 水电账单`),
+            请上传以下任一文件：
+            • 选民登记卡
+            • 驾驶证
+            • 银行对账单
+            • 水电账单
+        `),
         userDOBVerification: '出生日期验证',
         userDOBVerificationDescription: '请上传美国签发的身份证件',
         finishViaChat: '通过聊天完成',
@@ -4221,7 +4256,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             customFieldHint: '为该成员的所有支出添加适用的自定义编码。',
             reports: '报表',
             reportFields: '报表字段',
-            invoiceFields: '发票字段',
             reportTitle: '报表标题',
             reportField: '报表字段',
             taxes: '税费',
@@ -4304,15 +4338,15 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理员';
+                        return '工作区管理员';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '审计员';
                     case CONST.POLICY.ROLE.EDITOR:
-                        return '编辑';
+                        return '编辑器';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return '卡片管理员';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return '人员管理';
+                        return '人员管理员';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return '付款管理员';
                     case CONST.POLICY.ROLE.USER:
@@ -5837,29 +5871,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             reportFieldInitialValueRequiredError: '请选择报表字段的初始值',
             genericFailureMessage: '更新报表字段时出错。请重试。',
         },
-        invoiceFields: {
-            subtitle: '当你想添加更多信息时，发票字段会很有帮助。',
-            importedFromAccountingSoftware: '以下发票字段是从你的',
-            disableInvoiceFields: '禁用发票字段',
-            disableInvoiceFieldsConfirmation: '确定吗？发票字段将在发票中被禁用。',
-            delete: '删除发票字段',
-            deleteConfirmation: '确定要删除此发票字段吗？',
-            findInvoiceField: '查找发票字段',
-            nameInputSubtitle: '为发票字段选择一个名称。',
-            typeInputSubtitle: '选择要使用的发票字段类型。',
-            initialValueInputSubtitle: '输入要在发票字段中显示的起始值。',
-            listValuesInputSubtitle: '这些值将显示在你的发票字段下拉菜单中。成员可以选择已启用的值。',
-            listInputSubtitle: '这些值将显示在你的发票字段列表中。成员可以选择已启用的值。',
-            emptyInvoiceFieldsValues: {
-                title: '还没有列表值',
-                subtitle: '添加要显示在发票上的自定义值。',
-            },
-            existingInvoiceFieldNameError: '已存在同名发票字段',
-            invoiceFieldNameRequiredError: '请输入发票字段名称',
-            invoiceFieldTypeRequiredError: '请选择发票字段类型',
-            invoiceFieldInitialValueRequiredError: '请选择发票字段的初始值',
-            addField: '添加字段',
-        },
         tags: {
             tagName: '标签名称',
             requiresTag: '成员必须为所有报销添加标签',
@@ -6080,8 +6091,8 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 other: '设为成员',
             }),
             makeAdmin: () => ({
-                one: '设为管理员',
-                other: '设为管理员',
+                one: '设为工作区管理员',
+                other: '设为工作区管理员',
             }),
             makeAuditor: () => ({
                 one: '设为审计员',
@@ -6106,12 +6117,14 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 `如果您将 ${memberName} 从此工作区中移除，我们会将其技术联系人替换为工作区所有者 ${workspaceOwner}。`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) => `${memberName} 还有一份待处理报告需要处理。请在将其从工作区中移除之前，先让 TA 完成所需操作。`,
             allMembers: '所有成员',
-            admins: '管理员',
+            admins: '工作区管理员',
             approvers: '审批人',
             auditors: '审计员',
             emptyRoleFilter: {title: '没有成员符合此筛选条件', subtitle: '邀请成员或更改上方的筛选条件。'},
             configureHRSync: (providerName: string) => `配置 ${providerName} 同步。`,
             syncWithHR: (providerName: string) => `与 ${providerName} 同步`,
+            makeCardAdmin: () => ({one: '设为卡片管理员', other: '设为卡管理员'}),
+            cardAdmins: '卡片管理员',
         },
         card: {
             getStartedIssuing: '从发放您的第一张虚拟卡或实体卡开始使用。',
@@ -6522,6 +6535,10 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             }),
             enableRate: '启用费率',
             status: '状态',
+            statusActive: '活跃',
+            statusFuture: '未来',
+            statusExpired: '已过期',
+            statusInactive: '未启用',
             unit: '单位',
             taxFeatureNotEnabledMessage: '<muted-text>必须在工作区中启用税费才能使用此功能。前往<a href="#">更多功能</a>进行更改。</muted-text>',
             deleteDistanceRate: '删除距离费率',
@@ -6640,12 +6657,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>报表字段仅在 Control 方案中提供，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
-            invoiceFields: {
-                title: '发票字段',
-                description: `发票字段可用于在发票上包含额外的发票级别详情。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>发票字段仅在 Control 方案中提供，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `通过 Expensify + NetSuite 集成实现自动同步，减少手动录入。借助对原生和自定义维度的支持（包括项目和客户映射），获取深入的实时财务洞察。`,
@@ -6745,12 +6756,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>里程费率适用于 Collect 方案，起始价格为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
-            auditor: {
-                title: '审计员',
-                description: '审计员将获得所有报表的只读访问权限，以实现全面可见性和合规监控。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>审核员仅适用于 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: '多级审批',
                 description: '多级审批是一个工作流程工具，适用于在报销前需要多个人批准报销单的公司。',
@@ -6844,6 +6849,12 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>开票功能适用于 Collect 和 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: '控制策略角色',
+                description: '使用审计员、卡片管理员等专门角色，只授予成员完成工作所需的访问权限。',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>专用工作区角色仅在 Control 方案中提供，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -7159,6 +7170,7 @@ ${reportName}
                 deleteRuleConfirmation: '确定要删除此规则吗？',
                 describeRuleTitle: '描述你的规则',
                 describeRuleSubtitle: '描述你的规则，我们会由 Concierge 为你创建',
+                disclaimer: 'AI 智能体可能会犯错。',
             },
         },
         planTypePage: {
@@ -7812,21 +7824,18 @@ ${reportName}
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `来自 ${cards} 的 ${content}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `将“${categoryName}”类别的默认税率更改为“${newTax}”（之前为“${oldTax}”）`,
         addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `已添加“${rateName}”汇率，数值为 ${rateValue}`,
         addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `已添加“${rateName}”费率 ${rateValue}，自 ${startDate} 起生效`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `已添加“${rateName}”费率 ${rateValue}，有效期至 ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `已添加“${rateName}”费率 ${rateValue}，有效期为 ${startDate} - ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `将“${rateName}”费率的开始日期更新为 ${newDate}（之前为 ${oldDate}）` : `将“${rateName}”费率的开始日期设置为 ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `已将“${rateName}”费率的结束日期更新为 ${newDate}（之前为 ${oldDate}）` : `将“${rateName}”费率的结束日期设置为 ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `已将“${rateName}”费率的起止日期更新为 ${newStartDate} - ${newEndDate}（此前为 ${oldStartDate} - ${oldEndDate}）`
-                : `将“${rateName}”费率的开始和结束日期设为 ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `已从“${rateName}”费率中移除开始日期（原为 ${oldDate}）`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `已从“${rateName}”费率中移除结束日期（之前为 ${oldDate}）`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) => `已将距离费率“${rateName}”更新为适用于 ${newDateRange}（此前为 ${oldDateRange}）`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `自 ${date} 起`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `直到 ${date}`,
+        customUnitRateDateRangeAllDates: () => `适用于所有日期`,
     },
     roomMembersPage: {
         memberNotFound: '未找到成员。',
@@ -8247,8 +8256,11 @@ ${reportName}
                     `${feedName} 连接已中断。要恢复银行卡导入，请<a href='${workspaceCompanyCardRoute}'>登录您的银行账户</a>。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${role === 'member' ? '一个' : '一个'} 的 ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? '一个' : 'a';
+                    return didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `已将 ${email} 的角色更新为 ${newRole}（先前为 ${currentRole}）`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
@@ -9121,6 +9133,10 @@ ${reportName}
             作为副驾驶，你无权访问此页面。抱歉！
         `),
         notAllowedMessage: (accountOwnerEmail: string) => `作为${accountOwnerEmail}的<a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">副驾驶</a>，你没有权限执行此操作。抱歉！`,
+        removeCopilotAccess: '移除我的副驾驶访问权限',
+        removeCopilotAccessTitle: '移除副驾驶访问权限？',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) => `您确定要移除对${delegatorName}的 Expensify 账户的副驾驶访问权限吗？此操作无法撤销。`,
+        removeCopilotAccessConfirm: '移除访问权限',
         copilotAccess: 'Copilot 访问',
     },
     debug: {
diff --git a/src/libs/API/parameters/CreateWorkspaceInvoiceFieldListValueParams.ts b/src/libs/API/parameters/CreateWorkspaceInvoiceFieldListValueParams.ts
deleted file mode 100644
index fa22805f4e71..000000000000
--- a/src/libs/API/parameters/CreateWorkspaceInvoiceFieldListValueParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type CreateWorkspaceInvoiceFieldListValueParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default CreateWorkspaceInvoiceFieldListValueParams;
diff --git a/src/libs/API/parameters/CreateWorkspaceInvoiceFieldParams.ts b/src/libs/API/parameters/CreateWorkspaceInvoiceFieldParams.ts
deleted file mode 100644
index 5cce12e49273..000000000000
--- a/src/libs/API/parameters/CreateWorkspaceInvoiceFieldParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type CreateWorkspaceInvoiceFieldParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default CreateWorkspaceInvoiceFieldParams;
diff --git a/src/libs/API/parameters/DeletePolicyInvoiceField.ts b/src/libs/API/parameters/DeletePolicyInvoiceField.ts
deleted file mode 100644
index 5b3c37fb1e07..000000000000
--- a/src/libs/API/parameters/DeletePolicyInvoiceField.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type DeletePolicyInvoiceField = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default DeletePolicyInvoiceField;
diff --git a/src/libs/API/parameters/EnablePolicyInvoiceFieldsParams.ts b/src/libs/API/parameters/EnablePolicyInvoiceFieldsParams.ts
deleted file mode 100644
index 5afc5c912d90..000000000000
--- a/src/libs/API/parameters/EnablePolicyInvoiceFieldsParams.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-type EnablePolicyInvoiceFieldsParams = {
-    policyID: string;
-    enabled: boolean;
-};
-
-export default EnablePolicyInvoiceFieldsParams;
diff --git a/src/libs/API/parameters/EnableWorkspaceInvoiceFieldListValueParams.ts b/src/libs/API/parameters/EnableWorkspaceInvoiceFieldListValueParams.ts
deleted file mode 100644
index a52405efad54..000000000000
--- a/src/libs/API/parameters/EnableWorkspaceInvoiceFieldListValueParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type EnableWorkspaceInvoiceFieldListValueParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default EnableWorkspaceInvoiceFieldListValueParams;
diff --git a/src/libs/API/parameters/RemoveDelegatorParams.ts b/src/libs/API/parameters/RemoveDelegatorParams.ts
new file mode 100644
index 000000000000..81e6f0441dd3
--- /dev/null
+++ b/src/libs/API/parameters/RemoveDelegatorParams.ts
@@ -0,0 +1,5 @@
+type RemoveDelegatorParams = {
+    delegatorEmail: string;
+};
+
+export default RemoveDelegatorParams;
diff --git a/src/libs/API/parameters/RemoveWorkspaceInvoiceFieldListValueParams.ts b/src/libs/API/parameters/RemoveWorkspaceInvoiceFieldListValueParams.ts
deleted file mode 100644
index c793b4bdf10a..000000000000
--- a/src/libs/API/parameters/RemoveWorkspaceInvoiceFieldListValueParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type RemoveWorkspaceInvoiceFieldListValueParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default RemoveWorkspaceInvoiceFieldListValueParams;
diff --git a/src/libs/API/parameters/UpdateWorkspaceInvoiceFieldInitialValueParams.ts b/src/libs/API/parameters/UpdateWorkspaceInvoiceFieldInitialValueParams.ts
deleted file mode 100644
index eeb3cd5106aa..000000000000
--- a/src/libs/API/parameters/UpdateWorkspaceInvoiceFieldInitialValueParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type UpdateWorkspaceInvoiceFieldInitialValueParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default UpdateWorkspaceInvoiceFieldInitialValueParams;
diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts
index ea8c05a42cde..d56b78063826 100644
--- a/src/libs/API/parameters/index.ts
+++ b/src/libs/API/parameters/index.ts
@@ -259,7 +259,6 @@ export type {default as SetPolicyTravelSettingsParams} from './SetPolicyTravelSe
 export type {default as EnablePolicyTagsParams} from './EnablePolicyTagsParams';
 export type {default as SetPolicyTagsEnabled} from './SetPolicyTagsEnabled';
 export type {default as EnablePolicyWorkflowsParams} from './EnablePolicyWorkflowsParams';
-export type {default as EnablePolicyInvoiceFieldsParams} from './EnablePolicyInvoiceFieldsParams';
 export type {default as EnablePolicyReportFieldsParams} from './EnablePolicyReportFieldsParams';
 export type {default as EnablePolicyExpensifyCardsParams} from './EnablePolicyExpensifyCardsParams';
 export type {default as UpdateGustoApprovalModeParams} from './UpdateGustoApprovalModeParams';
@@ -338,21 +337,15 @@ export type {default as DowngradeToTeamParams} from './DowngradeToTeamParams';
 export type {default as RejectMoneyRequestInBulkParams} from './RejectMoneyRequestInBulkParams';
 export type {default as ApproveMoneyRequestOnSearchParams} from './ApproveMoneyRequestOnSearchParams';
 export type {default as UpdateNetSuiteSubsidiaryParams} from './UpdateNetSuiteSubsidiaryParams';
-export type {default as DeletePolicyInvoiceField} from './DeletePolicyInvoiceField';
 export type {default as DeletePolicyReportField} from './DeletePolicyReportField';
 export type {default as ConnectPolicyToNetSuiteParams} from './ConnectPolicyToNetSuiteParams';
 export type {default as CreateWorkspaceReportFieldParams} from './CreateWorkspaceReportFieldParams';
-export type {default as CreateWorkspaceInvoiceFieldParams} from './CreateWorkspaceInvoiceFieldParams';
 export type {default as UpdateWorkspaceReportFieldInitialValueParams} from './UpdateWorkspaceReportFieldInitialValueParams';
-export type {default as UpdateWorkspaceInvoiceFieldInitialValueParams} from './UpdateWorkspaceInvoiceFieldInitialValueParams';
 export type {default as EnableWorkspaceReportFieldListValueParams} from './EnableWorkspaceReportFieldListValueParams';
-export type {default as EnableWorkspaceInvoiceFieldListValueParams} from './EnableWorkspaceInvoiceFieldListValueParams';
 export type {default as EnablePolicyInvoicingParams} from './EnablePolicyInvoicingParams';
 export type {default as EnablePolicyTimeTrackingParams} from './EnablePolicyTimeTrackingParams';
 export type {default as CreateWorkspaceReportFieldListValueParams} from './CreateWorkspaceReportFieldListValueParams';
-export type {default as CreateWorkspaceInvoiceFieldListValueParams} from './CreateWorkspaceInvoiceFieldListValueParams';
 export type {default as RemoveWorkspaceReportFieldListValueParams} from './RemoveWorkspaceReportFieldListValueParams';
-export type {default as RemoveWorkspaceInvoiceFieldListValueParams} from './RemoveWorkspaceInvoiceFieldListValueParams';
 export type {default as OpenPolicyExpensifyCardsPageParams} from './OpenPolicyExpensifyCardsPageParams';
 export type {default as OpenPolicyTravelPageParams} from './OpenPolicyTravelPageParams';
 export type {default as OpenPolicyEditCardLimitTypePageParams} from './OpenPolicyEditCardLimitTypePageParams';
@@ -411,6 +404,7 @@ export type {default as SetCardReconciliationBankAccountParams} from './SetCardR
 export type {default as CardDeactivateParams} from './CardDeactivateParams';
 export type {default as UpdateExpensifyCardLimitTypeParams} from './UpdateExpensifyCardLimitTypeParams';
 export type {default as RemoveDelegateParams} from './RemoveDelegateParams';
+export type {default as RemoveDelegatorParams} from './RemoveDelegatorParams';
 export type {default as SetPolicyTagApproverParams} from './SetPolicyTagApproverParams';
 export type {default as SaveSearchParams} from './SaveSearch';
 export type {default as DeleteSavedSearchParams} from './DeleteSavedSearch';
diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts
index 0bdcd9ff6228..973435cea37a 100644
--- a/src/libs/API/types.ts
+++ b/src/libs/API/types.ts
@@ -193,7 +193,6 @@ const WRITE_COMMANDS = {
     UPDATE_POLICY_CATEGORY_GL_CODE: 'UpdatePolicyCategoryGLCode',
     DELETE_WORKSPACE_CATEGORIES: 'DeleteWorkspaceCategories',
     DELETE_POLICY_REPORT_FIELD: 'DeletePolicyReportField',
-    DELETE_POLICY_INVOICE_FIELD: 'DeletePolicyInvoiceField',
     SET_POLICY_TAGS_REQUIRED: 'SetPolicyTagsRequired',
     SET_POLICY_TAG_LISTS_REQUIRED: 'SetPolicyTagListsRequired',
     SET_POLICY_REQUIRES_TAG: 'SetPolicyRequiresTag',
@@ -271,7 +270,6 @@ const WRITE_COMMANDS = {
     ENABLE_POLICY_TAXES: 'EnablePolicyTaxes',
     ENABLE_POLICY_WORKFLOWS: 'EnablePolicyWorkflows',
     ENABLE_POLICY_REPORT_FIELDS: 'EnablePolicyReportFields',
-    ENABLE_POLICY_INVOICE_FIELDS: 'EnablePolicyInvoiceFields',
     ENABLE_POLICY_EXPENSIFY_CARDS: 'EnablePolicyExpensifyCards',
     TOGGLE_POLICY_PER_DIEM: 'TogglePolicyPerDiem',
     ENABLE_POLICY_COMPANY_CARDS: 'EnablePolicyCompanyCards',
@@ -411,14 +409,9 @@ const WRITE_COMMANDS = {
     OPEN_SIDE_PANEL: 'OpenSidePanel',
     CLOSE_SIDE_PANEL: 'CloseSidePanel',
     UPDATE_NETSUITE_SUBSIDIARY: 'UpdateNetSuiteSubsidiary',
-    CREATE_WORKSPACE_INVOICE_FIELD: 'CreatePolicyInvoiceField',
-    CREATE_WORKSPACE_INVOICE_FIELD_LIST_VALUE: 'CreatePolicyInvoiceFieldOption',
     CREATE_WORKSPACE_REPORT_FIELD: 'CreatePolicyReportField',
-    UPDATE_WORKSPACE_INVOICE_FIELD_INITIAL_VALUE: 'SetPolicyInvoiceFieldDefault',
     UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE: 'SetPolicyReportFieldDefault',
-    ENABLE_WORKSPACE_INVOICE_FIELD_LIST_VALUE: 'EnablePolicyInvoiceFieldOption',
     ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'EnablePolicyReportFieldOption',
-    REMOVE_WORKSPACE_INVOICE_FIELD_LIST_VALUE: 'RemovePolicyInvoiceFieldOption',
     CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'CreatePolicyReportFieldOption',
     REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'RemovePolicyReportFieldOption',
     UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION: 'UpdateNetSuiteSyncTaxConfiguration',
@@ -527,6 +520,7 @@ const WRITE_COMMANDS = {
     QUEUE_EXPENSIFY_CARD_FOR_BILLING: 'Domain_QueueExpensifyCardForBilling',
     ADD_DELEGATE: 'AddDelegate',
     REMOVE_DELEGATE: 'RemoveDelegate',
+    REMOVE_DELEGATOR: 'RemoveDelegator',
     UPDATE_DELEGATE_ROLE: 'UpdateDelegateRole',
     TOGGLE_CARD_CONTINUOUS_RECONCILIATION: 'ToggleCardContinuousReconciliation',
     TOGGLE_CARD_CASHBACK_TO_BILL: 'ToggleCardCashbackToBill',
@@ -821,7 +815,6 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_PAYROLL_CODE]: Parameters.UpdatePolicyCategoryPayrollCodeParams;
     [WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_GL_CODE]: Parameters.UpdatePolicyCategoryGLCodeParams;
     [WRITE_COMMANDS.DELETE_POLICY_REPORT_FIELD]: Parameters.DeletePolicyReportField;
-    [WRITE_COMMANDS.DELETE_POLICY_INVOICE_FIELD]: Parameters.DeletePolicyInvoiceField;
     [WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG]: Parameters.SetPolicyRequiresTag;
     [WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED]: Parameters.SetPolicyTagsRequired;
     [WRITE_COMMANDS.SET_POLICY_TAG_LISTS_REQUIRED]: Parameters.SetPolicyTagListsRequired;
@@ -918,7 +911,6 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.ENABLE_POLICY_TAXES]: Parameters.EnablePolicyTaxesParams;
     [WRITE_COMMANDS.ENABLE_POLICY_WORKFLOWS]: Parameters.EnablePolicyWorkflowsParams;
     [WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS]: Parameters.EnablePolicyReportFieldsParams;
-    [WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS]: Parameters.EnablePolicyInvoiceFieldsParams;
     [WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS]: Parameters.EnablePolicyExpensifyCardsParams;
     [WRITE_COMMANDS.TOGGLE_POLICY_PER_DIEM]: Parameters.TogglePolicyPerDiemParams;
     [WRITE_COMMANDS.ENABLE_POLICY_COMPANY_CARDS]: Parameters.EnablePolicyCompanyCardsParams;
@@ -1119,6 +1111,11 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS]: Parameters.UpdateFinancialForceGenericTypeParams<'exportStatus', FinancialForceReportExportStatus>;
     [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_AUTO_SYNC]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
     [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_PARENT_TAG_MAPPING]: Parameters.UpdateFinancialForceGenericTypeParams<'parentTagMapping', ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING>>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_COMPANY]: Parameters.UpdateFinancialForceGenericTypeParams<'companyID', string>;
     [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
     [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
 
@@ -1131,15 +1128,10 @@ type WriteCommandParameters = {
 
     // Workspace report field parameters
     [WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD]: Parameters.CreateWorkspaceReportFieldParams;
-    [WRITE_COMMANDS.CREATE_WORKSPACE_INVOICE_FIELD]: Parameters.CreateWorkspaceInvoiceFieldParams;
     [WRITE_COMMANDS.UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE]: Parameters.UpdateWorkspaceReportFieldInitialValueParams;
-    [WRITE_COMMANDS.UPDATE_WORKSPACE_INVOICE_FIELD_INITIAL_VALUE]: Parameters.UpdateWorkspaceInvoiceFieldInitialValueParams;
     [WRITE_COMMANDS.ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.EnableWorkspaceReportFieldListValueParams;
-    [WRITE_COMMANDS.ENABLE_WORKSPACE_INVOICE_FIELD_LIST_VALUE]: Parameters.EnableWorkspaceInvoiceFieldListValueParams;
     [WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.CreateWorkspaceReportFieldListValueParams;
-    [WRITE_COMMANDS.CREATE_WORKSPACE_INVOICE_FIELD_LIST_VALUE]: Parameters.CreateWorkspaceInvoiceFieldListValueParams;
     [WRITE_COMMANDS.REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.RemoveWorkspaceReportFieldListValueParams;
-    [WRITE_COMMANDS.REMOVE_WORKSPACE_INVOICE_FIELD_LIST_VALUE]: Parameters.RemoveWorkspaceInvoiceFieldListValueParams;
 
     [WRITE_COMMANDS.UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>;
     [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_TAX_SOLUTION_ID]: Parameters.UpdateNetSuiteGenericTypeParams<'taxSolutionID', string>;
@@ -1213,6 +1205,7 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.ADD_DELEGATE]: Parameters.AddDelegateParams;
     [WRITE_COMMANDS.UPDATE_DELEGATE_ROLE]: Parameters.UpdateDelegateRoleParams;
     [WRITE_COMMANDS.REMOVE_DELEGATE]: Parameters.RemoveDelegateParams;
+    [WRITE_COMMANDS.REMOVE_DELEGATOR]: Parameters.RemoveDelegatorParams;
     [WRITE_COMMANDS.TOGGLE_CARD_CONTINUOUS_RECONCILIATION]: Parameters.ToggleCardContinuousReconciliationParams;
     [WRITE_COMMANDS.TOGGLE_CARD_CASHBACK_TO_BILL]: Parameters.ToggleCardCashbackToBillParams;
     [WRITE_COMMANDS.SET_CARD_RECONCILIATION_BANK_ACCOUNT]: Parameters.SetCardReconciliationBankAccountParams;
@@ -1369,7 +1362,6 @@ const READ_COMMANDS = {
     OPEN_POLICY_TAGS_PAGE: 'OpenPolicyTagsPage',
     OPEN_POLICY_TAXES_PAGE: 'OpenPolicyTaxesPage',
     OPEN_POLICY_REPORT_FIELDS_PAGE: 'OpenPolicyReportFieldsPage',
-    OPEN_POLICY_INVOICES_PAGE: 'OpenPolicyInvoicesPage',
     OPEN_POLICY_RULES_PAGE: 'OpenPolicyRulesPage',
     OPEN_POLICY_EXPENSIFY_CARDS_PAGE: 'OpenPolicyExpensifyCardsPage',
     OPEN_POLICY_TRAVEL_PAGE: 'OpenPolicyTravelPage',
@@ -1474,7 +1466,6 @@ type ReadCommandParameters = {
     [READ_COMMANDS.OPEN_POLICY_TAGS_PAGE]: Parameters.OpenPolicyTagsPageParams;
     [READ_COMMANDS.OPEN_POLICY_TAXES_PAGE]: Parameters.OpenPolicyTaxesPageParams;
     [READ_COMMANDS.OPEN_POLICY_REPORT_FIELDS_PAGE]: Parameters.OpenPolicyReportFieldsPageParams;
-    [READ_COMMANDS.OPEN_POLICY_INVOICES_PAGE]: Parameters.OpenPolicyReportFieldsPageParams;
     [READ_COMMANDS.OPEN_POLICY_RULES_PAGE]: Parameters.OpenPolicyRulesPageParams;
     [READ_COMMANDS.OPEN_WORKSPACE_INVITE_PAGE]: Parameters.OpenWorkspaceInvitePageParams;
     [READ_COMMANDS.OPEN_DRAFT_WORKSPACE_REQUEST]: Parameters.OpenDraftWorkspaceRequestParams;
diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts
index fb1d4e173eb0..a0288d2847c6 100644
--- a/src/libs/DistanceRequestUtils.ts
+++ b/src/libs/DistanceRequestUtils.ts
@@ -1,3 +1,4 @@
+import {format, parseISO} from 'date-fns';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import Onyx from 'react-native-onyx';
 import type {CurrencyListActionsContextType} from '@components/CurrencyListContextProvider';
@@ -635,6 +636,29 @@ function prepareTextForDisplay(text: string): string {
     return text.replaceAll(/[^0-9., ]/g, '').replace(/^0+(?=\d)/, '');
 }
 
+function getRateDateLabel(rate: MileageRate, translate: LocaleContextProps['translate']): string {
+    const dateFormat = CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT;
+
+    try {
+        if (rate.startDate && rate.endDate) {
+            return translate('iou.rateValidDateRange', {
+                startDate: format(parseISO(rate.startDate), dateFormat),
+                endDate: format(parseISO(rate.endDate), dateFormat),
+            });
+        }
+        if (rate.startDate) {
+            return translate('iou.rateValidFrom', {startDate: format(parseISO(rate.startDate), dateFormat)});
+        }
+        if (rate.endDate) {
+            return translate('iou.rateValidUntil', {endDate: format(parseISO(rate.endDate), dateFormat)});
+        }
+    } catch {
+        return '';
+    }
+
+    return '';
+}
+
 export default {
     getDefaultMileageRate,
     getDistanceMerchant,
@@ -659,6 +683,7 @@ export default {
     prepareTextForDisplay,
     isRateEligibleForDate,
     getBestEligibleRate,
+    getRateDateLabel,
 };
 
 export type {MileageRate};
diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts
index 61d0b20ebf17..ee7ac77b3720 100644
--- a/src/libs/ModifiedExpenseMessage.ts
+++ b/src/libs/ModifiedExpenseMessage.ts
@@ -15,7 +15,7 @@ import {formatList} from './Localize';
 import Log from './Log';
 import Parser from './Parser';
 import {getPersonalDetailByEmail} from './PersonalDetailsUtils';
-import {getCleanedTagName, getCommaSeparatedTagNameWithSanitizedColons, getSortedTagKeys, isPolicyAdmin} from './PolicyUtils';
+import {getCleanedTagName, getCommaSeparatedTagNameWithSanitizedColons, getQBOVendorByID, getSortedTagKeys, isPolicyAdmin} from './PolicyUtils';
 import {getOriginalMessage, isModifiedExpenseAction} from './ReportActionsUtils';
 // This cycle import is safe because ReportNameUtils was extracted from ReportUtils to separate report name computation logic.
 // The functions imported here are pure utility functions that don't create initialization-time dependencies.
@@ -448,6 +448,36 @@ function getForReportAction({
         buildMessageFragmentForValue(translate, newReimbursable, oldReimbursable, translate('iou.expense'), true, setFragments, removalFragments, changeFragments);
     }
 
+    // Onyx applies updates with `shouldRemoveNestedNulls: true`, so when we build an optimistic
+    // MODIFIED_EXPENSE for a vendor "set" (no prior, `oldVendor: null`) or "remove" (no new,
+    // `vendor: null`), the null-valued key is stripped on merge and only one of the two keys
+    // survives in storage. Treat either key's presence as a vendor modification — requiring both
+    // would let "add" and "remove" cases fall through to the generic "changed the expense"
+    // fallback.
+    const hasModifiedVendor = isReportActionOriginalMessageAnObject && ('oldVendor' in reportActionOriginalMessage || 'vendor' in reportActionOriginalMessage);
+    if (hasModifiedVendor) {
+        // Vendor is stored on the action as `{externalID, isManuallySet}` (or absent/null). Resolve
+        // the display name from the policy's QBO vendor list; if the vendor has since been removed
+        // from QBO the name is unrecoverable, so fall back to the externalID so the fragment still
+        // identifies which vendor was set rather than rendering `set vendor ""`.
+        const resolveVendorName = (entry: typeof reportActionOriginalMessage.vendor): string => {
+            if (!entry?.externalID) {
+                return '';
+            }
+            return getQBOVendorByID(policy, entry.externalID)?.name ?? entry.externalID;
+        };
+        buildMessageFragmentForValue(
+            translate,
+            resolveVendorName(reportActionOriginalMessage?.vendor),
+            resolveVendorName(reportActionOriginalMessage?.oldVendor),
+            translate('common.vendor'),
+            true,
+            setFragments,
+            removalFragments,
+            changeFragments,
+        );
+    }
+
     const hasModifiedAttendees = isReportActionOriginalMessageAnObject && 'oldAttendees' in reportActionOriginalMessage && 'newAttendees' in reportActionOriginalMessage;
     if (hasModifiedAttendees) {
         const [oldAttendees, attendees] = getFormattedAttendees(reportActionOriginalMessage.newAttendees, reportActionOriginalMessage.oldAttendees);
diff --git a/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx b/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx
index f953488083a9..7eb752147fe0 100644
--- a/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx
+++ b/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx
@@ -19,7 +19,6 @@ import {getReportIDFromLink} from '@libs/ReportUtils';
 import * as SessionUtils from '@libs/SessionUtils';
 import {endSpan, getSpan, startSpan} from '@libs/telemetry/activeSpans';
 import {getSearchParamFromUrl} from '@libs/Url';
-import {openAgentsPage} from '@userActions/Agent';
 import * as App from '@userActions/App';
 import * as Download from '@userActions/Download';
 import {clearStaleExportDownloads} from '@userActions/Export';
@@ -132,11 +131,6 @@ function AuthScreensInitHandler() {
             App.reconnectApp(initialLastUpdateIDAppliedToClient);
         }
 
-        // Hydrate the user's custom-agent prompts so AgentZeroStatusProvider can recognize
-        // custom-agent chats opened directly from a deep link or right after sign-in, without
-        // requiring a prior visit to Settings > Agents.
-        openAgentsPage();
-
         App.setUpPoliciesAndNavigate(
             session,
             introSelected,
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 6a86b048a5dc..668a25069717 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -174,10 +174,11 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
     [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepConfirmation').default,
     [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION_VERIFY_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/MoneyRequestStepConfirmationVerifyAccountPage').default,
     [SCREENS.MONEY_REQUEST.STEP_AMOUNT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepAmount').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepTaxAmountPage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepTaxRatePage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepCategoryPage').default,
+    [SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepTaxAmountPage').default,
+    [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepTaxRatePage').default,
+    [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepCategory').default,
     [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepCategoryCreate').default,
+    [SCREENS.MONEY_REQUEST.STEP_VENDOR]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepVendor').default,
     [SCREENS.MONEY_REQUEST.STEP_DATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDate').default,
     [SCREENS.MONEY_REQUEST.STEP_DESCRIPTION]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDescription').default,
     [SCREENS.MONEY_REQUEST.STEP_DISTANCE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDistance').default,
@@ -200,9 +201,9 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
     [SCREENS.IOU_SEND.ADD_DEBIT_CARD]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/AddDebitCardPage').default,
     [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: () => require<ReactComponentModule>('../../../../pages/EnablePayments/Pay/EnablePaymentsPage').default,
     [SCREENS.MONEY_REQUEST.STATE_SELECTOR]: () => require<ReactComponentModule>('../../../../pages/settings/Profile/PersonalDetails/StateSelectionPage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepAttendeesPage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepAccountantPage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepUpgradePage').default,
+    [SCREENS.MONEY_REQUEST.STEP_ATTENDEES]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepAttendees').default,
+    [SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepAccountant').default,
+    [SCREENS.MONEY_REQUEST.STEP_UPGRADE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepUpgrade').default,
     [SCREENS.MONEY_REQUEST.STEP_DESTINATION]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDestination').default,
     [SCREENS.MONEY_REQUEST.STEP_TIME]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepTime').default,
     [SCREENS.MONEY_REQUEST.STEP_SUBRATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepSubrate').default,
@@ -575,7 +576,6 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
         require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage').default,
-    [SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT]: withAgentAccessDenied(() => require<ReactComponentModule>('../../../../pages/settings/Agents/AddAgentPage').default),
     [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_INVITE_MESSAGE]: () => require<ReactComponentModule>('../../../../pages/workspace/DynamicWorkspaceInviteMessagePage').default,
     [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_INVITE_MESSAGE_ROLE]: () => require<ReactComponentModule>('../../../../pages/workspace/DynamicWorkspaceInviteMessageRolePage').default,
     [SCREENS.WORKSPACE.INVITE_MESSAGE_APPROVER]: () => require<ReactComponentModule>('../../../../pages/workspace/WorkspaceInviteMessageApproverPage').default,
@@ -912,6 +912,9 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_EXPORT_DATE]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/export/CertiniaExportDatePage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_DEFAULT_VENDOR]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/export/CertiniaDefaultVendorPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_ADVANCED]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/advanced/CertiniaAdvancedPage').default,
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_REPORT_EXPORT_STATUS]: () =>
+        require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/export/CertiniaReportExportStatusPage').default,
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_COMPANY_SELECTOR]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/CertiniaCompanySelectorPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/reconciliation/CardReconciliationPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION_SAGE_INTACCT_AUTO_SYNC]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/accounting/reconciliation/CardReconciliationSageIntacctAutoSyncPage').default,
@@ -999,16 +1002,10 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.WORKSPACE.REPORT_FIELDS_VALUE_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/reports/ReportFieldsValueSettingsPage').default,
     [SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/reports/ReportFieldsInitialValuePage').default,
     [SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/reports/ReportFieldsEditValuePage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/CreateInvoiceFieldsPage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsSettingsPage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsListValuesPage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsAddListValuePage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsValueSettingsPage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsInitialValuePage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsEditValuePage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_IMPORT]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/import/CertiniaImportPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_DIMENSION_MAPPING]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/import/CertiniaDimensionMappingPage').default,
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_TAGS_MAPPING]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/import/CertiniaTagsMappingPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_IMPORT]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/intacct/import/SageIntacctImportPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_TOGGLE_MAPPING]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage').default,
diff --git a/src/libs/Navigation/helpers/navigateToWorkspacesPage.ts b/src/libs/Navigation/helpers/navigateToWorkspacesPage.ts
index 852f69b32c01..331e5e4f8cc1 100644
--- a/src/libs/Navigation/helpers/navigateToWorkspacesPage.ts
+++ b/src/libs/Navigation/helpers/navigateToWorkspacesPage.ts
@@ -3,7 +3,6 @@ import {findFocusedRoute, StackActions, TabActions} from '@react-navigation/nati
 import interceptAnonymousUser from '@libs/interceptAnonymousUser';
 import Navigation from '@libs/Navigation/Navigation';
 import navigationRef from '@libs/Navigation/navigationRef';
-// eslint-disable-next-line no-restricted-imports -- TransitionTracker is needed here to sequence the tab jump after the popToTop transition completes, so WorkspaceInitialPage appears before the tab becomes visible.
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import {isPendingDeletePolicy, shouldShowPolicy as shouldShowPolicyUtil} from '@libs/PolicyUtils';
 import NAVIGATORS from '@src/NAVIGATORS';
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
index d826e3285910..a4963bdf1ee4 100755
--- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
@@ -35,7 +35,6 @@ const WORKSPACE_TO_RHP: Partial<Record<keyof WorkspaceSplitNavigatorParamList, s
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER,
-        SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT,
         SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY,
         SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET,
         SCREENS.WORKSPACE.WORKFLOWS_PAYER,
@@ -193,6 +192,9 @@ const WORKSPACE_TO_RHP: Partial<Record<keyof WorkspaceSplitNavigatorParamList, s
         SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_EXPORT_DATE,
         SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_DEFAULT_VENDOR,
         SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_ADVANCED,
+        SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_TAGS_MAPPING,
+        SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_REPORT_EXPORT_STATUS,
+        SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_COMPANY_SELECTOR,
     ],
     [SCREENS.WORKSPACE.TAXES]: [
         SCREENS.WORKSPACE.TAXES_SETTINGS,
@@ -297,18 +299,7 @@ const WORKSPACE_TO_RHP: Partial<Record<keyof WorkspaceSplitNavigatorParamList, s
         SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE,
         SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE,
     ],
-    [SCREENS.WORKSPACE.INVOICES]: [
-        SCREENS.WORKSPACE.INVOICES_COMPANY_NAME,
-        SCREENS.WORKSPACE.INVOICES_COMPANY_WEBSITE,
-        SCREENS.WORKSPACE.INVOICES_VERIFY_ACCOUNT,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE,
-    ],
+    [SCREENS.WORKSPACE.INVOICES]: [SCREENS.WORKSPACE.INVOICES_COMPANY_NAME, SCREENS.WORKSPACE.INVOICES_COMPANY_WEBSITE, SCREENS.WORKSPACE.INVOICES_VERIFY_ACCOUNT],
     [SCREENS.WORKSPACE.COMPANY_CARDS]: [
         SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_COMPANY_CARDS_ADD_NEW,
         SCREENS.WORKSPACE.COMPANY_CARDS_IMPORT_SPREADSHEET,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 5709ca05c881..470bfeec483e 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -803,6 +803,9 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_EXPORT_DATE]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_EXPORT_DATE.path,
                         [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_DEFAULT_VENDOR]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_DEFAULT_VENDOR.path,
                         [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_ADVANCED]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_ADVANCED.path,
+                        [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_TAGS_MAPPING]: {path: ROUTES.POLICY_ACCOUNTING_CERTINIA_TAGS_MAPPING.route},
+                        [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_REPORT_EXPORT_STATUS]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_REPORT_EXPORT_STATUS.path,
+                        [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_COMPANY_SELECTOR]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_COMPANY_SELECTOR.path,
                         [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION]: {path: ROUTES.WORKSPACE_ACCOUNTING_CARD_RECONCILIATION.route},
                         [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION_SAGE_INTACCT_AUTO_SYNC]: {
                             path: ROUTES.POLICY_ACCOUNTING_CARD_RECONCILIATION_SAGE_INTACCT_AUTO_SYNC.route,
@@ -833,27 +836,6 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                             path: ROUTES.WORKSPACE_INVOICES_VERIFY_ACCOUNT.route,
                             exact: true,
                         },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_CREATE.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_LIST_VALUES.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_ADD_VALUE.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_VALUE_SETTINGS.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_VALUE.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_SETTINGS.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_INITIAL_VALUE.route,
-                        },
                         [SCREENS.WORKSPACE.COMPANY_CARDS_SELECT_FEED]: {
                             path: ROUTES.WORKSPACE_COMPANY_CARDS_SELECT_FEED.route,
                         },
@@ -1008,9 +990,6 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: {
                             path: ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.route,
                         },
-                        [SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT]: {
-                            path: ROUTES.WORKSPACE_WORKFLOWS_ADD_AGENT.route,
-                        },
                         [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_INVITE_MESSAGE]: DYNAMIC_ROUTES.WORKSPACE_INVITE_MESSAGE.path,
                         [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_INVITE_MESSAGE_ROLE]: DYNAMIC_ROUTES.WORKSPACE_INVITE_MESSAGE_ROLE.path,
                         [SCREENS.WORKSPACE.INVITE_MESSAGE_APPROVER]: {
@@ -1772,8 +1751,9 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.MONEY_REQUEST.STEP_REPORT]: ROUTES.MONEY_REQUEST_STEP_REPORT.route,
                         [SCREENS.MONEY_REQUEST.STEP_COMPANY_INFO]: ROUTES.MONEY_REQUEST_STEP_COMPANY_INFO.route,
                         [SCREENS.MONEY_REQUEST.STEP_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_AMOUNT.route,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY]: DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.path,
+                        [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: ROUTES.MONEY_REQUEST_STEP_CATEGORY.route,
                         [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: ROUTES.MONEY_REQUEST_STEP_CATEGORY_CREATE.route,
+                        [SCREENS.MONEY_REQUEST.STEP_VENDOR]: ROUTES.MONEY_REQUEST_STEP_VENDOR.route,
                         [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION]: ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.route,
                         [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION_VERIFY_ACCOUNT]: ROUTES.MONEY_REQUEST_STEP_CONFIRMATION_VERIFY_ACCOUNT.route,
                         [SCREENS.MONEY_REQUEST.STEP_DATE]: ROUTES.MONEY_REQUEST_STEP_DATE.route,
@@ -1792,15 +1772,15 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.MONEY_REQUEST.RECEIPT_VIEW]: ROUTES.MONEY_REQUEST_RECEIPT_VIEW.route,
                         [SCREENS.MONEY_REQUEST.STEP_TAG]: ROUTES.MONEY_REQUEST_STEP_TAG.route,
                         [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: ROUTES.MONEY_REQUEST_STEP_WAYPOINT.route,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT]: DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.path,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE]: DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_RATE.path,
+                        [SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.route,
+                        [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: ROUTES.MONEY_REQUEST_STEP_TAX_RATE.route,
                         [SCREENS.MONEY_REQUEST.STATE_SELECTOR]: {
                             path: ROUTES.MONEY_REQUEST_STATE_SELECTOR.route,
                             exact: true,
                         },
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES]: DYNAMIC_ROUTES.MONEY_REQUEST_ATTENDEE.path,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT]: DYNAMIC_ROUTES.MONEY_REQUEST_ACCOUNTANT.path,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE]: DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.path,
+                        [SCREENS.MONEY_REQUEST.STEP_ATTENDEES]: ROUTES.MONEY_REQUEST_ATTENDEE.route,
+                        [SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT]: ROUTES.MONEY_REQUEST_ACCOUNTANT.route,
+                        [SCREENS.MONEY_REQUEST.STEP_UPGRADE]: ROUTES.MONEY_REQUEST_UPGRADE.route,
                         [SCREENS.MONEY_REQUEST.STEP_DESTINATION]: ROUTES.MONEY_REQUEST_STEP_DESTINATION.route,
                         [SCREENS.MONEY_REQUEST.STEP_TIME]: ROUTES.MONEY_REQUEST_STEP_TIME.route,
                         [SCREENS.MONEY_REQUEST.STEP_SUBRATE]: ROUTES.MONEY_REQUEST_STEP_SUBRATE.route,
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index f74a385b909c..6bd1d14f56dd 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -247,7 +247,6 @@ type SettingsNavigatorParamList = {
     [SCREENS.SETTINGS.ADD_BANK_ACCOUNT_SELECT_COUNTRY_VERIFY_ACCOUNT]: undefined;
     [SCREENS.SETTINGS.AGENTS.ADD]: {
         policyID?: string;
-        workflowApproverEmail?: string;
     };
     [SCREENS.SETTINGS.AGENTS.ADD_AVATAR]: undefined;
     [SCREENS.SETTINGS.AGENTS.EDIT]: {
@@ -644,59 +643,31 @@ type SettingsNavigatorParamList = {
     [SCREENS.WORKSPACE.REPORT_FIELDS_CREATE]: {
         policyID: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE]: {
-        policyID: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_LIST_VALUES]: {
         policyID: string;
         reportFieldID?: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES]: {
-        policyID: string;
-        reportFieldID?: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_ADD_VALUE]: {
         policyID: string;
         reportFieldID?: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE]: {
-        policyID: string;
-        reportFieldID?: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_VALUE_SETTINGS]: {
         policyID: string;
         valueIndex: number;
         reportFieldID?: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS]: {
-        policyID: string;
-        valueIndex: number;
-        reportFieldID?: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE]: {
         policyID: string;
         valueIndex: number;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE]: {
-        policyID: string;
-        valueIndex: number;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_SETTINGS]: {
         policyID: string;
         reportFieldID: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS]: {
-        policyID: string;
-        reportFieldID: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE]: {
         policyID: string;
         reportFieldID: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE]: {
-        policyID: string;
-        reportFieldID: string;
-    };
     [SCREENS.WORKSPACE.MEMBER_DETAILS]: {
         policyID: string;
         accountID: string;
@@ -1203,6 +1174,15 @@ type SettingsNavigatorParamList = {
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_ADVANCED]: {
         policyID: string;
     };
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_TAGS_MAPPING]: {
+        policyID: string;
+    };
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_REPORT_EXPORT_STATUS]: {
+        policyID: string;
+    };
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_COMPANY_SELECTOR]: {
+        policyID: string;
+    };
     [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION]: {
         policyID: string;
         connection: ValueOf<typeof CONST.POLICY.CONNECTIONS.ROUTE>;
@@ -1932,12 +1912,21 @@ type MoneyRequestNavigatorParamList = {
         backTo: Routes;
         reportActionID: string;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY]: {
+    [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
+        reportActionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
+    };
+    [SCREENS.MONEY_REQUEST.STEP_VENDOR]: {
+        action: IOUAction;
+        iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
+        transactionID: string;
         reportActionID?: string;
+        reportID: string;
     };
     [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: {
         action: IOUAction;
@@ -1948,11 +1937,13 @@ type MoneyRequestNavigatorParamList = {
         // eslint-disable-next-line no-restricted-syntax -- backTo is needed to track where editing was initiated from (search/view or r/:reportID)
         backTo?: Routes;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT]: {
+    [SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
     };
     [SCREENS.MONEY_REQUEST.STEP_TAG]: {
         action: IOUAction;
@@ -1964,11 +1955,13 @@ type MoneyRequestNavigatorParamList = {
         reportActionID: string;
         orderWeight: string;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE]: {
+    [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
     };
     [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: {
         iouType: IOUType;
@@ -2154,23 +2147,29 @@ type MoneyRequestNavigatorParamList = {
         /** ID of the expense report being rejected */
         reportID: string;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES]: {
+    [SCREENS.MONEY_REQUEST.STEP_ATTENDEES]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT]: {
+    [SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE]: {
+    [SCREENS.MONEY_REQUEST.STEP_UPGRADE]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
         upgradePath?: ValueOf<typeof CONST.UPGRADE_PATHS>;
         shouldSubmitExpense?: boolean;
     };
@@ -2775,23 +2774,6 @@ type WorkspaceSplitNavigatorParamList = {
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EDIT]: {
         policyID: string;
         firstApproverEmail: string;
-
-        /**
-         * Optional email of a person/agent to seed as approver[0] when the editor mounts. Used by
-         * the inline Add Agent flow on the Workflows page so the freshly-created agent can be
-         * dropped into the workflow without coordinating cross-page state.
-         */
-        seedApproverEmail?: string;
-
-        /**
-         * Optional optimistic accountID of an agent that was just created locally but does not
-         * have a server-assigned email yet. The Edit Approvers screen reads the personal
-         * details by accountID and seeds the workflow with whatever is there (display name,
-         * avatar, optimistic pendingAction). When the CREATE_AGENT response arrives the
-         * personal detail is upgraded with the real login, which then becomes the approver
-         * email for the workflow save.
-         */
-        seedApproverAccountID?: string;
     };
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM]: {
         policyID: string;
@@ -2814,10 +2796,6 @@ type WorkspaceSplitNavigatorParamList = {
         policyID: string;
         approverIndex: number;
     };
-    [SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT]: {
-        policyID: string;
-        workflowApproverEmail?: string;
-    };
     [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: {
         policyID: string;
     };
diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts
index 4ea6e9f2e761..9c4a1b366bf7 100644
--- a/src/libs/Network/SequentialQueue.ts
+++ b/src/libs/Network/SequentialQueue.ts
@@ -44,13 +44,28 @@ type RequestError = Error & {
     status?: string;
 };
 
-let resolveIsReadyPromise: ((args?: unknown[]) => void) | undefined;
-let isReadyPromise = new Promise((resolve) => {
-    resolveIsReadyPromise = resolve;
-});
+let resolveIsReadyPromise: (() => void) | undefined;
+let isReadyPromise: Promise<void> = Promise.resolve();
+let isReadyPromisePending = false;
 
-// Resolve the isReadyPromise immediately so that the queue starts working as soon as the page loads
-resolveIsReadyPromise?.();
+/**
+ * Marks isReadyPromise as pending so any READ that consults waitForIdle() parks behind us.
+ * Idempotent: if already pending, no-op (avoids orphaning subscribers from prior pushes).
+ * Called from push()'s sync prelude before the first await, so READs on the next sync line
+ * see the pending promise.
+ */
+function setIsReadyPromisePending() {
+    if (isReadyPromisePending) {
+        return;
+    }
+    isReadyPromise = new Promise<void>((resolve) => {
+        resolveIsReadyPromise = () => {
+            isReadyPromisePending = false;
+            resolve();
+        };
+    });
+    isReadyPromisePending = true;
+}
 
 let isSequentialQueueRunning = false;
 let currentRequestPromise: Promise<void> | null = null;
@@ -322,6 +337,10 @@ function flush(shouldResetPromise = true) {
 
     if (persistedRequestsLength === 0 && !currentOngoingRequest && !hasOnyxUpdates) {
         Log.info('[SequentialQueue] Unable to flush. No requests or queued Onyx updates to process.');
+        // push() may have marked isReadyPromise pending in its sync prelude (e.g. a conflict
+        // resolver deleted the only request without pushing a replacement). Resolve here so READs
+        // parked on waitForIdle() don't hang until unrelated queue activity releases them.
+        resolveIsReadyPromise?.();
         return;
     }
 
@@ -338,6 +357,10 @@ function flush(shouldResetPromise = true) {
             persistedRequestsLength,
             hasOngoingRequest: !!currentOngoingRequest,
         });
+        // push() may have marked isReadyPromise pending in its sync prelude. Followers never
+        // process the queue, so resolve here — otherwise READs parked on waitForIdle() would
+        // hang forever on this tab after any write.
+        resolveIsReadyPromise?.();
         return;
     }
 
@@ -350,10 +373,9 @@ function flush(shouldResetPromise = true) {
     isSequentialQueueRunning = true;
 
     if (shouldResetPromise) {
-        // Reset the isReadyPromise so that the queue will be flushed as soon as the request is finished
-        isReadyPromise = new Promise((resolve) => {
-            resolveIsReadyPromise = resolve;
-        });
+        // Mark isReadyPromise as pending so READs (waitForIdle) park behind us.
+        // Idempotent — safe if push() already marked it pending in its sync prelude.
+        setIsReadyPromisePending();
     }
 
     // Ensure persistedRequests are read from storage before proceeding with the queue
@@ -520,7 +542,7 @@ async function handleConflictActions<TKey extends OnyxKey>(conflictAction: Confl
     }
 }
 
-function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void> {
+async function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void> {
     const currentRequests = getAllPersistedRequests();
     Log.info('[SequentialQueue] push() called', false, {
         command: newRequest.command,
@@ -530,19 +552,10 @@ function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void
         isSequentialQueueRunning,
     });
 
-    // Save the request to the persisted queue. The in-memory update inside save()
-    // happens synchronously, so flush() below will see the new request immediately.
-    // The returned promise resolves when disk persistence completes.
     let persistencePromise: Promise<void>;
 
     if (newRequest.checkAndFixConflictingRequest) {
-        const requests = currentRequests;
-        Log.info('[SequentialQueue] Checking for conflicts', false, {
-            command: newRequest.command,
-            existingRequestsCount: requests.length,
-        });
-
-        const {conflictAction} = newRequest.checkAndFixConflictingRequest(requests as Array<OnyxRequest<TKey>>);
+        const {conflictAction} = newRequest.checkAndFixConflictingRequest(currentRequests as Array<OnyxRequest<TKey>>);
         Log.info('[SequentialQueue] Conflict action determined', false, {
             command: newRequest.command,
             conflictType: conflictAction.type,
@@ -553,41 +566,56 @@ function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void
         delete newRequest.checkAndFixConflictingRequest;
         persistencePromise = handleConflictActions(conflictAction, newRequest);
     } else {
-        Log.info('[SequentialQueue] No conflict action. Adding request to Persisted Requests', false, {
-            command: newRequest.command,
-        });
-        // Add request to Persisted Requests so that it can be retried if it fails
         persistencePromise = savePersistedRequest(newRequest);
     }
 
-    // If we are offline we don't need to trigger the queue to empty as it will happen when we come back online
     if (isOfflineNetwork()) {
         Log.info('[SequentialQueue] Request persisted but not flushing — we are offline', false, {
             command: newRequest.command,
             queueLength: getAllPersistedRequests().length,
         });
-        return persistencePromise;
+        await persistencePromise;
+        return;
+    }
+
+    // Mark the ready-promise pending sync (before the first await) so any READ that fires on
+    // the next synchronous line via waitForIdle() correctly parks behind this write.
+    setIsReadyPromisePending();
+
+    // Block until the Onyx disk commit lands so flush() → XHR cannot race the disk write —
+    // a process kill in that window would lose the request on next launch.
+    try {
+        await persistencePromise;
+    } catch {
+        // Backstop: persistence alerts+swallows on failure, so this shouldn't reject. If it ever does,
+        // flush anyway (the request is already in the in-memory queue) rather than stranding isReadyPromise.
+        Log.info('[SequentialQueue] Persist rejected — flushing anyway', false, {command: newRequest.command});
+    }
+
+    // The network may have flipped offline while we awaited the disk write. flush() would
+    // early-return on its offline check without resolving isReadyPromise, leaving READs parked
+    // on waitForIdle() until an unrelated reconnect drains the queue. Resolve here so READs
+    // proceed — consistent with flush() resolving isReadyPromise when offline.
+    if (isOfflineNetwork()) {
+        Log.info('[SequentialQueue] Went offline during persist — resolving isReadyPromise without flushing', false, {
+            command: newRequest.command,
+        });
+        resolveIsReadyPromise?.();
+        return;
     }
 
-    // If the queue is running this request will run once it has finished processing the current batch
     if (isSequentialQueueRunning) {
         Log.info('[SequentialQueue] Queue is running. Will flush when the current request is finished.', false, {
             command: newRequest.command,
         });
-        isReadyPromise.then(() => {
-            Log.info('[SequentialQueue] isReadyPromise resolved, flushing queue', false, {
-                command: newRequest.command,
-            });
-            flush(true);
-        });
-        return persistencePromise;
+        isReadyPromise.then(() => flush(false));
+        return;
     }
 
     Log.info('[SequentialQueue] Queue is not running. Flushing the queue.', false, {
         command: newRequest.command,
     });
-    flush(true);
-    return persistencePromise;
+    flush(false);
 }
 
 function getCurrentRequest(): Promise<void> {
@@ -612,10 +640,9 @@ function resetQueue(): void {
     isSequentialQueueRunning = false;
     currentRequestPromise = null;
     isQueuePaused = false;
-    isReadyPromise = new Promise((resolve) => {
-        resolveIsReadyPromise = resolve;
-    });
-    resolveIsReadyPromise?.();
+    isReadyPromise = Promise.resolve();
+    isReadyPromisePending = false;
+    resolveIsReadyPromise = undefined;
 }
 
 export {
diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts
index 4da56fc3b94c..c703d442ddca 100644
--- a/src/libs/NextStepUtils.ts
+++ b/src/libs/NextStepUtils.ts
@@ -1,15 +1,18 @@
 import {addMonths, format, isPast, setDate} from 'date-fns';
 import {Str} from 'expensify-common';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
+import Onyx from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import type {LocaleContextProps} from '@components/LocaleContextProvider';
 import CONST from '@src/CONST';
-import type {Policy, Report, ReportNextStepDeprecated, Transaction, TransactionViolations} from '@src/types/onyx';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {IntroSelected, Policy, Report, ReportNextStepDeprecated, Transaction, TransactionViolations} from '@src/types/onyx';
 import type {ReportNextStep} from '@src/types/onyx/Report';
 import type {Message} from '@src/types/onyx/ReportNextStepDeprecated';
 import type DeepValueOf from '@src/types/utils/DeepValueOf';
 import EmailUtils from './EmailUtils';
 import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from './LocalePhoneNumber';
+import isTrackOnboardingChoice from './OnboardingUtils';
 import {getLoginsByAccountIDs, getPersonalDetailsByIDs} from './PersonalDetailsUtils';
 import {getApprovalWorkflow, getCorrectedAutoReportingFrequency, getReimburserAccountID} from './PolicyUtils';
 import {
@@ -22,9 +25,19 @@ import {
     isOpenExpenseReport,
     isPayer,
     shouldBlockSubmitDueToPreventSelfApproval,
+    shouldShowMarkAsDone,
 } from './ReportUtils';
 import {hasSubmissionBlockingViolations} from './TransactionUtils';
 
+let introSelected: OnyxEntry<IntroSelected>;
+// eslint-disable-next-line rulesdir/no-onyx-connect -- NextStepUtils is a pure utility called from action files that cannot use hooks
+Onyx.connect({
+    key: ONYXKEYS.NVP_INTRO_SELECTED,
+    callback: (value) => {
+        introSelected = value;
+    },
+});
+
 type BuildNextStepNewParams = {
     report: OnyxEntry<Report>;
     policy?: OnyxEntry<Policy>;
@@ -139,7 +152,9 @@ function buildOptimisticNextStep(params: BuildNextStepNewParams): ReportNextStep
             }
             if (isReopen) {
                 nextStep = {
-                    messageKey: CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT,
+                    messageKey: shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy})
+                        ? CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE
+                        : CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT,
                     icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
                     actorAccountID: ownerAccountID,
                 };
@@ -200,7 +215,13 @@ function buildOptimisticNextStep(params: BuildNextStepNewParams): ReportNextStep
             // Manual submission
             if (hasTransactions && !policy?.harvesting?.enabled) {
                 nextStep = {
-                    messageKey: CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT,
+                    messageKey: shouldShowMarkAsDone({
+                        isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice),
+                        report,
+                        policy,
+                    })
+                        ? CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE
+                        : CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT,
                     icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
                     actorAccountID: ownerAccountID,
                 };
@@ -537,13 +558,90 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
     switch (predictedNextStatus) {
         // Generates an optimistic nextStep once a report has been opened
         case CONST.REPORT.STATUS_NUM.OPEN:
-            if (isRejectedReport) {
+            {
+                const shouldShowMarkAsDoneCopy = shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy});
+
+                if (isRejectedReport) {
+                    optimisticNextStep = {
+                        type,
+                        icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
+                        message: [
+                            {
+                                text: 'This report was rejected. Waiting on ',
+                            },
+                            {
+                                text: `${ownerDisplayName}`,
+                                type: 'strong',
+                                clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
+                            },
+                            {
+                                text: ' to fix the issues and manually resubmit.',
+                            },
+                        ],
+                    };
+                    break;
+                }
+                if ((isASAPSubmitBetaEnabled && hasViolations && isInstantSubmitEnabled) || shouldFixViolations) {
+                    optimisticNextStep = {
+                        type,
+                        icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
+                        message: [
+                            {
+                                text: 'Waiting for ',
+                            },
+                            {
+                                text: `${ownerDisplayName}`,
+                                type: 'strong',
+                                clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
+                            },
+                            {
+                                text: ' to ',
+                            },
+                            {
+                                text: 'fix the issues',
+                            },
+                        ],
+                    };
+                    break;
+                }
+                if (isReopen) {
+                    optimisticNextStep = {
+                        type,
+                        icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
+                        message: [
+                            {
+                                text: 'Waiting for ',
+                            },
+                            {
+                                text: `${ownerDisplayName}`,
+                                type: 'strong',
+                                clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
+                            },
+                            {
+                                text: ' to ',
+                            },
+                            {
+                                text: shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit',
+                            },
+                            {
+                                text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
+                            },
+                        ],
+                    };
+                    break;
+                }
+
+                // Self review
+                let actionText = 'add';
+                if (hasTransactions) {
+                    actionText = shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit';
+                }
                 optimisticNextStep = {
                     type,
                     icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
                     message: [
                         {
-                            text: 'This report was rejected. Waiting on ',
+                            text: 'Waiting for ',
                         },
                         {
                             text: `${ownerDisplayName}`,
@@ -551,17 +649,20 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                             clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
                         },
                         {
-                            text: ' to fix the issues and manually resubmit.',
+                            text: ' to ',
+                        },
+                        {
+                            text: actionText,
+                        },
+                        {
+                            text: hasTransactions && shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
                         },
                     ],
                 };
-                break;
-            }
-            if ((isASAPSubmitBetaEnabled && hasViolations && isInstantSubmitEnabled) || shouldFixViolations) {
-                optimisticNextStep = {
-                    type,
-                    icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
-                    message: [
+
+                // Scheduled submit enabled
+                if (policy?.harvesting?.enabled && hasTransactions) {
+                    optimisticNextStep.message = [
                         {
                             text: 'Waiting for ',
                         },
@@ -571,20 +672,51 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                             clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
                         },
                         {
-                            text: ' to ',
+                            text: `'s`,
+                            type: 'strong',
                         },
                         {
-                            text: 'fix the issues',
+                            text: ' %expenses to automatically submit',
                         },
-                    ],
-                };
-                break;
-            }
-            if (isReopen) {
-                optimisticNextStep = {
-                    type,
-                    icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
-                    message: [
+                    ];
+                    let harvestingSuffix = '';
+
+                    if (autoReportingFrequency) {
+                        const currentDate = new Date();
+                        let autoSubmissionDate = '';
+                        let monthlyText = '';
+
+                        if (policy?.autoReportingOffset === CONST.POLICY.AUTO_REPORTING_OFFSET.LAST_DAY_OF_MONTH) {
+                            monthlyText = 'on the last day of the month';
+                        } else if (policy?.autoReportingOffset === CONST.POLICY.AUTO_REPORTING_OFFSET.LAST_BUSINESS_DAY_OF_MONTH) {
+                            monthlyText = 'on the last business day of the month';
+                        } else if (policy?.autoReportingOffset !== undefined) {
+                            autoSubmissionDate = format(setDate(currentDate, policy?.autoReportingOffset), CONST.DATE.ORDINAL_DAY_OF_MONTH);
+                        }
+
+                        const harvestingSuffixes: Record<DeepValueOf<typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES>, string> = {
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE]: 'later today',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.WEEKLY]: 'on Sunday',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.SEMI_MONTHLY]: 'on the 1st and 16th of each month',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MONTHLY]: autoSubmissionDate ? `on the ${autoSubmissionDate} of each month` : monthlyText,
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.TRIP]: 'at the end of their trip',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT]: '',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL]: '',
+                        };
+
+                        if (harvestingSuffixes[autoReportingFrequency]) {
+                            harvestingSuffix = `${harvestingSuffixes[autoReportingFrequency]}`;
+                        }
+                    }
+
+                    optimisticNextStep.message.push({
+                        text: ` ${harvestingSuffix}`,
+                    });
+                }
+
+                // Manual submission
+                if (hasTransactions && !policy?.harvesting?.enabled) {
+                    optimisticNextStep.message = [
                         {
                             text: 'Waiting for ',
                         },
@@ -597,118 +729,14 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                             text: ' to ',
                         },
                         {
-                            text: 'submit',
+                            text: shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit',
                         },
                         {
-                            text: ' %expenses.',
+                            text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
                         },
-                    ],
-                };
-                break;
-            }
-
-            // Self review
-            optimisticNextStep = {
-                type,
-                icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
-                message: [
-                    {
-                        text: 'Waiting for ',
-                    },
-                    {
-                        text: `${ownerDisplayName}`,
-                        type: 'strong',
-                        clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
-                    },
-                    {
-                        text: ' to ',
-                    },
-                    {
-                        text: hasTransactions ? 'submit' : 'add',
-                    },
-                    {
-                        text: ' %expenses.',
-                    },
-                ],
-            };
-
-            // Scheduled submit enabled
-            if (policy?.harvesting?.enabled && hasTransactions) {
-                optimisticNextStep.message = [
-                    {
-                        text: 'Waiting for ',
-                    },
-                    {
-                        text: `${ownerDisplayName}`,
-                        type: 'strong',
-                        clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
-                    },
-                    {
-                        text: `'s`,
-                        type: 'strong',
-                    },
-                    {
-                        text: ' %expenses to automatically submit',
-                    },
-                ];
-                let harvestingSuffix = '';
-
-                if (autoReportingFrequency) {
-                    const currentDate = new Date();
-                    let autoSubmissionDate = '';
-                    let monthlyText = '';
-
-                    if (policy?.autoReportingOffset === CONST.POLICY.AUTO_REPORTING_OFFSET.LAST_DAY_OF_MONTH) {
-                        monthlyText = 'on the last day of the month';
-                    } else if (policy?.autoReportingOffset === CONST.POLICY.AUTO_REPORTING_OFFSET.LAST_BUSINESS_DAY_OF_MONTH) {
-                        monthlyText = 'on the last business day of the month';
-                    } else if (policy?.autoReportingOffset !== undefined) {
-                        autoSubmissionDate = format(setDate(currentDate, policy?.autoReportingOffset), CONST.DATE.ORDINAL_DAY_OF_MONTH);
-                    }
-
-                    const harvestingSuffixes: Record<DeepValueOf<typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES>, string> = {
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE]: 'later today',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.WEEKLY]: 'on Sunday',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.SEMI_MONTHLY]: 'on the 1st and 16th of each month',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MONTHLY]: autoSubmissionDate ? `on the ${autoSubmissionDate} of each month` : monthlyText,
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.TRIP]: 'at the end of their trip',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT]: '',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL]: '',
-                    };
-
-                    if (harvestingSuffixes[autoReportingFrequency]) {
-                        harvestingSuffix = `${harvestingSuffixes[autoReportingFrequency]}`;
-                    }
+                    ];
                 }
-
-                optimisticNextStep.message.push({
-                    text: ` ${harvestingSuffix}`,
-                });
             }
-
-            // Manual submission
-            if (hasTransactions && !policy?.harvesting?.enabled) {
-                optimisticNextStep.message = [
-                    {
-                        text: 'Waiting for ',
-                    },
-                    {
-                        text: `${ownerDisplayName}`,
-                        type: 'strong',
-                        clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
-                    },
-                    {
-                        text: ' to ',
-                    },
-                    {
-                        text: 'submit',
-                    },
-                    {
-                        text: ' %expenses.',
-                    },
-                ];
-            }
-
             break;
 
         // Generates an optimistic nextStep once a report has been submitted
diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index 6d54b65707e8..e5ff8b4c4941 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -40,6 +40,7 @@ import {
     getAssignedCompanyCardMessage,
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
+    getCategoryTaxRateMessage,
     getChangedApproverActionMessage,
     getCombinedReportActions,
     getCurrencyDefaultTaxUpdateMessage,
@@ -162,6 +163,7 @@ import {
     isSelfDM as reportUtilsIsSelfDM,
     isTaskReport as reportUtilsIsTaskReport,
     shouldReportBeInOptionList,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import StringUtils from '@libs/StringUtils';
 import {getTaskCreatedMessage, getTaskReportActionMessage} from '@libs/TaskUtils';
@@ -659,6 +661,7 @@ function getLastMessageTextForReport({
     reportAttributesDerived,
     policyTags,
     currentUserLogin,
+    isTrackIntentUser = false,
     // eslint-disable-next-line @typescript-eslint/no-deprecated
     sortedActions = deprecatedAllSortedReportActions,
 }: {
@@ -678,6 +681,7 @@ function getLastMessageTextForReport({
     currentUserLogin?: string;
     // TODO: conciergeReportID will be required eventually. Refactor issue: https://github.com/Expensify/App/issues/66411
     conciergeReportID?: string;
+    isTrackIntentUser?: boolean;
     // TODO: Remove optional (?) once all callers pass sortedActions. Refactor issue: https://github.com/Expensify/App/issues/66381
     sortedActions?: Record<string, ReportAction[]>;
 }): string {
@@ -822,7 +826,13 @@ function getLastMessageTextForReport({
         } else if (hasPendingDEWSubmit(reportMetadata, isDEWPolicy) && isPendingAdd) {
             lastMessageTextFromReport = translate('iou.queuedToSubmitViaDEW');
         } else {
-            lastMessageTextFromReport = translate('iou.submitted', getOriginalMessage(lastReportAction)?.message);
+            lastMessageTextFromReport = shouldShowMarkAsDone({
+                report,
+                isTrackIntentUser,
+                policy,
+            })
+                ? translate('iou.markedAsDone', getOriginalMessage(lastReportAction)?.message)
+                : translate('iou.submitted', getOriginalMessage(lastReportAction)?.message);
         }
     } else if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.APPROVED)) {
         const {automaticAction} = getOriginalMessage(lastReportAction) ?? {};
@@ -932,6 +942,9 @@ function getLastMessageTextForReport({
     if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT)) {
         lastMessageTextFromReport = getAutoReimbursementMessage(translate, lastReportAction);
     }
+    if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE)) {
+        lastMessageTextFromReport = getCategoryTaxRateMessage(translate, lastReportAction);
+    }
     if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MCC_GROUP_CATEGORY)) {
         lastMessageTextFromReport = getMccGroupCategoryMessage(translate, lastReportAction);
     }
@@ -2591,20 +2604,22 @@ function getValidOptions(
             recentReportOptions = recentReportOptions.filter((report) => !report.reportID || !reportIDsToExclude.has(report.reportID));
         }
     } else if (recentAttendees && recentAttendees?.length > 0) {
-        recentAttendees.filter((attendee) => {
-            const login = attendee.login ?? attendee.displayName;
-            if (login) {
-                loginsToExcludeFromSuggestions[login] = true;
-                return true;
-            }
-
-            return false;
-        });
         recentReportOptions = filterReports(recentAttendees as SearchOptionData[], searchTerms) as Array<SearchOption<Report>>;
 
-        if (maxRecentReportElements) {
+        // Only cap the recent attendees when there's no active search. During a search we surface every match, since
+        // all recent attendees are excluded from "Contacts" and capped-off matches would otherwise vanish from the list.
+        if (maxRecentReportElements && searchTerms.length === 0) {
             recentReportOptions = recentReportOptions.slice(0, maxRecentReportElements);
         }
+
+        // Build the exclusion set from the recent attendees actually shown (after filtering and the cap) so that
+        // attendees that aren't displayed in "Recent" remain available in "Contacts".
+        for (const option of recentReportOptions) {
+            const login = option.login ?? option.displayName;
+            if (login) {
+                loginsToExcludeFromSuggestions[login] = true;
+            }
+        }
     }
 
     // Get valid personal details and check if we can find the current user:
diff --git a/src/libs/PolicyDistanceRatesUtils.ts b/src/libs/PolicyDistanceRatesUtils.ts
index 28fc53021206..abab94dfa2eb 100644
--- a/src/libs/PolicyDistanceRatesUtils.ts
+++ b/src/libs/PolicyDistanceRatesUtils.ts
@@ -171,4 +171,23 @@ function buildOnyxDataForPolicyDistanceRateUpdates(
     return {optimisticData, successData, failureData};
 }
 
-export {validateRateValue, getOptimisticRateName, validateTaxClaimableValue, validateCreateDistanceRateForm, buildOnyxDataForPolicyDistanceRateUpdates};
+function getRateStatus(rate: Rate): string {
+    if (!rate.enabled) {
+        return CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE;
+    }
+
+    const today = new Date();
+    const now = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
+
+    if (rate.startDate && rate.startDate > now) {
+        return CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE;
+    }
+
+    if (rate.endDate && rate.endDate < now) {
+        return CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED;
+    }
+
+    return CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE;
+}
+
+export {validateRateValue, getOptimisticRateName, validateTaxClaimableValue, validateCreateDistanceRateForm, buildOnyxDataForPolicyDistanceRateUpdates, getRateStatus};
diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts
index b33a652e48cd..17e30fe841f1 100644
--- a/src/libs/PolicyUtils.ts
+++ b/src/libs/PolicyUtils.ts
@@ -331,7 +331,13 @@ function getEligibleBankAccountShareRecipients(policies: OnyxCollection<Policy>
         for (const admin of getAdminEmployees(policy)) {
             const email = admin?.email;
             // Check if the email is for the active user or an existing user in the sharees array or admins list to avoid extra iterations
-            if (!email || email === currentUserLogin || adminMap.has(email) || shareesSet.has(email)) {
+            if (
+                !email ||
+                email === currentUserLogin ||
+                adminMap.has(email) ||
+                shareesSet.has(email) ||
+                (isExpensifyTeam(email) && shouldFilterExpensifyTeam(policy.owner, currentUserLogin))
+            ) {
                 continue;
             }
             const personalDetails = getPersonalDetailByEmail(email);
@@ -371,7 +377,7 @@ function hasEligibleActiveAdminFromWorkspaces(policies: OnyxCollection<Policy> |
         const admins = getAdminEmployees(policy);
         for (const admin of admins) {
             const email = admin?.email;
-            if (!email || email === currentUserLogin || alreadySharedSharees.has(email)) {
+            if (!email || email === currentUserLogin || alreadySharedSharees.has(email) || (isExpensifyTeam(email) && shouldFilterExpensifyTeam(policy.owner, currentUserLogin))) {
                 continue;
             }
 
@@ -562,6 +568,7 @@ function shouldShowPolicy(policy: OnyxEntry<Policy>, shouldShowPendingDeletePoli
 
 /**
  * Checks if a specific user is a member of the policy.
+ * Note that employeeList can be blank when the policy is not the user's default/active policy
  */
 function isPolicyMember(policy: OnyxEntry<Policy>, userLogin: string | undefined): boolean {
     return !!policy && !!userLogin && (!!policy.employeeList?.[userLogin] || policy.owner === userLogin);
@@ -1089,6 +1096,16 @@ function isPendingDeletePolicy(policy: OnyxEntry<Policy>): boolean {
     return policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
 }
 
+/**
+ * Returns true only for paid plans (Collect/Control). Use this only for billing/paid-only concerns:
+ * subscriptions, payments and reimbursement, company cards, Expensify Card, Travel, Invoices, and
+ * "do I own a paid workspace" checks.
+ *
+ * For workspace feature gating (violations, report fields, workspace chat, report creation,
+ * expense-workspace usability) use `isGroupPolicy` instead, otherwise free group plans like Submit
+ * (submit2026) are wrongly excluded. The report-based counterparts are `ReportUtils.isPaidGroupPolicy`
+ * (paid-only) and `ReportUtils.isReportInGroupPolicy` (group).
+ */
 function isPaidGroupPolicy(policy: OnyxInputOrEntry<Policy>): boolean {
     return policy?.type === CONST.POLICY.TYPE.TEAM || policy?.type === CONST.POLICY.TYPE.CORPORATE;
 }
@@ -1128,11 +1145,15 @@ function canEditWorkspaceSettings(policy: OnyxInputOrEntry<Policy>, login?: stri
 }
 
 /**
- * Returns true for any group workspace: paid (Team/Corporate) or Submit.
+ * Returns true for any group workspace: paid (Collect/Control) or Submit.
+ *
+ * Prefer this over `isPaidGroupPolicy` whenever the check is about workspace features rather than
+ * billing (violations, report fields, workspace chat, report creation, expense-workspace usability),
+ * so free group plans like Submit (submit2026) are not excluded. It is a strict superset of
+ * `isPaidGroupPolicy`, so switching a feature check to it never changes Collect/Control/Personal
+ * behavior. Use `isPaidGroupPolicy` only when the concern is genuinely billing/paid-only.
  *
- * Note: not to be confused with `ReportUtils.isGroupPolicy(policyType: string)`,
- * which excludes Submit. Use this helper when Submit workspaces should be treated
- * like paid workspaces (e.g. access gating for shared workspace pages).
+ * For report-based call sites, use `ReportUtils.isReportInGroupPolicy(report)`, which delegates here.
  */
 function isGroupPolicy(policy: OnyxInputOrEntry<Policy>): boolean {
     return isPaidGroupPolicy(policy) || isSubmitPolicy(policy);
@@ -2627,4 +2648,4 @@ export {
     isSubmitPolicy,
 };
 
-export type {MemberEmailsToAccountIDs, PolicyFeature};
+export type {MemberEmailsToAccountIDs, PolicyFeature, PolicyFeatureAccess};
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 4e07f974c753..f5a1e1ff5a2e 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -2809,7 +2809,7 @@ function getPolicyChangeLogAddEmployeeMessage(translate: LocalizedTranslate, rep
 
     const originalMessage = getOriginalMessage(reportAction);
     const email = originalMessage?.email ?? '';
-    const role = translate('workspace.common.roleName', originalMessage?.role ?? '').toLowerCase();
+    const role = originalMessage?.role ?? '';
     const formattedEmail = formatPhoneNumber(email);
     return translate('report.actions.type.addEmployee', formattedEmail, role, originalMessage?.didJoinPolicy);
 }
@@ -3199,6 +3199,19 @@ function getWorkspaceCustomUnitRateAddedMessage(translate: LocalizedTranslate, a
     return getReportActionText(action);
 }
 
+function getCustomUnitRateDateRangeForMessage(translate: LocalizedTranslate, startDate?: string, endDate?: string): string {
+    if (startDate && endDate) {
+        return translate('workspaceActions.customUnitRateDateRangeStartToEnd', DateUtils.formatToReadableString(startDate), DateUtils.formatToReadableString(endDate));
+    }
+    if (startDate) {
+        return translate('workspaceActions.customUnitRateDateRangeFrom', DateUtils.formatToReadableString(startDate));
+    }
+    if (endDate) {
+        return translate('workspaceActions.customUnitRateDateRangeUntilEnd', DateUtils.formatToReadableString(endDate));
+    }
+    return translate('workspaceActions.customUnitRateDateRangeAllDates');
+}
+
 function getWorkspaceCustomUnitRateUpdatedMessage(translate: LocalizedTranslate, action: ReportAction): string {
     const {customUnitName, customUnitRateName, updatedField, oldValue, newValue, newTaxPercentage, oldTaxPercentage, newStartDate, newEndDate, oldStartDate, oldEndDate} =
         getOriginalMessage(action as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE>) ?? {};
@@ -3231,52 +3244,12 @@ function getWorkspaceCustomUnitRateUpdatedMessage(translate: LocalizedTranslate,
     }
 
     if (customUnitRateName && updatedField === RATE_CHANGELOG_UPDATED_FIELD.DATE_RANGE) {
-        const startDateChanged = newStartDate !== oldStartDate;
-        const endDateChanged = newEndDate !== oldEndDate;
-
-        if (startDateChanged && endDateChanged && newStartDate && newEndDate) {
-            const formattedOldStartDate = oldStartDate ? DateUtils.formatToReadableString(oldStartDate) : undefined;
-            const formattedOldEndDate = oldEndDate ? DateUtils.formatToReadableString(oldEndDate) : undefined;
-            return translate(
-                'workspaceActions.updatedCustomUnitRateStartAndEndDate',
-                customUnitRateName,
-                DateUtils.formatToReadableString(newStartDate),
-                DateUtils.formatToReadableString(newEndDate),
-                formattedOldStartDate,
-                formattedOldEndDate,
-            );
-        }
-
-        let startDateMessage = '';
-        let endDateMessage = '';
-
-        if (startDateChanged) {
-            if (!newStartDate && oldStartDate) {
-                startDateMessage = translate('workspaceActions.removedCustomUnitRateStartDate', customUnitRateName, DateUtils.formatToReadableString(oldStartDate));
-            } else if (newStartDate) {
-                const formattedOldDate = oldStartDate ? DateUtils.formatToReadableString(oldStartDate) : undefined;
-                startDateMessage = translate('workspaceActions.updatedCustomUnitRateStartDate', customUnitRateName, DateUtils.formatToReadableString(newStartDate), formattedOldDate);
-            }
-        }
-
-        if (endDateChanged) {
-            if (!newEndDate && oldEndDate) {
-                endDateMessage = translate('workspaceActions.removedCustomUnitRateEndDate', customUnitRateName, DateUtils.formatToReadableString(oldEndDate));
-            } else if (newEndDate) {
-                const formattedOldDate = oldEndDate ? DateUtils.formatToReadableString(oldEndDate) : undefined;
-                endDateMessage = translate('workspaceActions.updatedCustomUnitRateEndDate', customUnitRateName, DateUtils.formatToReadableString(newEndDate), formattedOldDate);
-            }
-        }
-
-        if (startDateMessage && endDateMessage) {
-            return `${startDateMessage}, ${endDateMessage}`;
-        }
-        if (startDateMessage) {
-            return startDateMessage;
-        }
-        if (endDateMessage) {
-            return endDateMessage;
+        const oldDateRange = getCustomUnitRateDateRangeForMessage(translate, oldStartDate, oldEndDate);
+        let newDateRange = getCustomUnitRateDateRangeForMessage(translate, newStartDate, newEndDate);
+        if (newStartDate && newEndDate) {
+            newDateRange = translate('workspaceActions.customUnitRateDateRangeFrom', newDateRange);
         }
+        return translate('workspaceActions.updatedCustomUnitRateDateRange', customUnitRateName, newDateRange, oldDateRange);
     }
 
     return getReportActionText(action);
@@ -3508,6 +3481,31 @@ function getAutoPayApprovedReportsEnabledMessage(translate: LocalizedTranslate,
     return translate('workspaceActions.updatedAutoPayApprovedReports', {enabled: !!enabled});
 }
 
+function formatTax(taxName?: string, taxPercentage?: string): string {
+    if (!taxName) {
+        return '';
+    }
+    return taxPercentage ? `${taxName} (${taxPercentage})` : taxName;
+}
+
+function getCategoryTaxRateMessage(translate: LocalizedTranslate, action: ReportAction): string {
+    const {categoryName, oldTaxName, oldTaxPercentage, newTaxName, newTaxPercentage} =
+        getOriginalMessage(action as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE>) ?? {};
+
+    if (!categoryName || !newTaxName || !oldTaxName) {
+        return getReportActionText(action);
+    }
+
+    const oldTax = formatTax(oldTaxName, oldTaxPercentage);
+    const newTax = formatTax(newTaxName, newTaxPercentage);
+
+    return translate('workspaceActions.updatedCategoryTaxRate', {
+        categoryName: getDecodedCategoryName(categoryName),
+        oldTax,
+        newTax,
+    });
+}
+
 function getAutoReimbursementMessage(translate: LocalizedTranslate, action: ReportAction): string {
     const {oldLimit, newLimit, currency} = getOriginalMessage(action as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT>) ?? {};
 
@@ -4812,6 +4810,7 @@ export {
     getRequireCompanyCardsEnabledMessage,
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
+    getCategoryTaxRateMessage,
     getMccGroupCategoryMessage,
     formatAddressToString,
     getCompanyAddressUpdateMessage,
diff --git a/src/libs/ReportNameUtils.ts b/src/libs/ReportNameUtils.ts
index 3741da9cdc13..8c2d3bf048a5 100644
--- a/src/libs/ReportNameUtils.ts
+++ b/src/libs/ReportNameUtils.ts
@@ -8,6 +8,7 @@ import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleCon
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {
+    IntroSelected,
     PersonalDetails,
     PersonalDetailsList,
     Policy,
@@ -27,6 +28,7 @@ import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from './LocalePhoneNum
 import {translateLocal} from './Localize';
 // eslint-disable-next-line import/no-cycle
 import {getForReportAction, getMovedReportID} from './ModifiedExpenseMessage';
+import isTrackOnboardingChoice from './OnboardingUtils';
 import Parser from './Parser';
 import {getDisplayNameOrDefault} from './PersonalDetailsUtils';
 import {getCleanedTagName, isPolicyAdmin, isPolicyFieldListEmpty} from './PolicyUtils';
@@ -38,6 +40,7 @@ import {
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
     getCardIssuedMessage,
+    getCategoryTaxRateMessage,
     getChangedApproverActionMessage,
     getCompanyAddressUpdateMessage,
     getCompanyCardConnectionBrokenMessage,
@@ -163,6 +166,7 @@ import {
     isThread,
     isTripRoom,
     isUserCreatedPolicyRoom,
+    shouldShowMarkAsDone,
 } from './ReportUtils';
 import {getAddExpensifyCardRuleMessage, getRemoveExpensifyCardRuleMessage, getUpdateExpensifyCardRuleMessage} from './SpendRuleChangeLogUtils';
 
@@ -192,6 +196,15 @@ Onyx.connect({
     },
 });
 
+let introSelected: OnyxEntry<IntroSelected>;
+// eslint-disable-next-line rulesdir/no-onyx-connect -- NextStepUtils is a pure utility called from action files that cannot use hooks
+Onyx.connect({
+    key: ONYXKEYS.NVP_INTRO_SELECTED,
+    callback: (value) => {
+        introSelected = value;
+    },
+});
+
 function generateArchivedReportName(reportName: string): string {
     return `${reportName} (${translateLocal('common.archived')}) `;
 }
@@ -435,6 +448,15 @@ function computeReportNameBasedOnReportAction(
         if (harvesting) {
             return Parser.htmlToText(translate('iou.automaticallySubmitted'));
         }
+        if (
+            shouldShowMarkAsDone({
+                isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice),
+                policy: reportPolicy,
+                report: parentReport,
+            })
+        ) {
+            return translate('iou.markedAsDone', getOriginalMessage(parentReportAction)?.message);
+        }
         return translate('iou.submitted', getOriginalMessage(parentReportAction)?.message);
     }
 
@@ -584,6 +606,9 @@ function computeReportNameBasedOnReportAction(
     if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT)) {
         return getAutoReimbursementMessage(translate, parentReportAction);
     }
+    if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE)) {
+        return getCategoryTaxRateMessage(translate, parentReportAction);
+    }
     if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MCC_GROUP_CATEGORY)) {
         return getMccGroupCategoryMessage(translate, parentReportAction);
     }
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index a00a0a03aff4..ab1aca3a4e5e 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -151,11 +151,9 @@ import {
     isExpensifyTeam,
     isGroupPolicy as isGroupPolicyPolicyUtils,
     isInstantSubmitEnabled,
-    isPaidGroupPolicy as isPaidGroupPolicyPolicyUtils,
     isPendingDeletePolicy,
     isPolicyAdmin as isPolicyAdminPolicyUtils,
     isPolicyAuditor,
-    isPolicyMember,
     isPolicyMemberWithoutPendingDelete,
     isPolicyOwner,
     isSubmitAndClose,
@@ -1700,7 +1698,9 @@ function isCurrentUserInvoiceReceiver(report: OnyxEntry<Report>): boolean {
 }
 
 /**
- * Whether the provided report belongs to a paid group or Submit policy
+ * Whether the report belongs to a group policy (Collect, Control, or Submit). Report-based counterpart
+ * of `PolicyUtils.isGroupPolicy`. Prefer this over `isPaidGroupPolicy(report)` for feature gating
+ * (violations, report fields, etc.) so free group plans like Submit are not excluded.
  */
 // TODO: Remove this function and use isGroupPolicy directly after https://github.com/Expensify/App/issues/66415 is done
 function isReportInGroupPolicy(report: OnyxInputOrEntry<Report>, policy?: OnyxInputOrEntry<Policy>): boolean {
@@ -1708,7 +1708,9 @@ function isReportInGroupPolicy(report: OnyxInputOrEntry<Report>, policy?: OnyxIn
 }
 
 /**
- * Whether the provided report belongs to a Control or Collect policy
+ * Whether the report belongs to a paid policy (Collect/Control) only. Report-based counterpart of
+ * `PolicyUtils.isPaidGroupPolicy`. For group-feature gating use `isReportInGroupPolicy` instead,
+ * otherwise Submit workspaces are wrongly excluded.
  */
 function isPaidGroupPolicy(report: OnyxEntry<Report>): boolean {
     const policyType = getPolicyType(report, allPolicies);
@@ -1716,10 +1718,12 @@ function isPaidGroupPolicy(report: OnyxEntry<Report>): boolean {
 }
 
 /**
- * Whether the provided report belongs to a Control or Collect policy and is an expense report
+ * Whether the provided report belongs to a group policy (Collect, Control, or Submit) and is an expense report.
+ * Use for report-field-style features that Submit workspaces also support, so the free Submit plan isn't
+ * incorrectly excluded.
  */
-function isPaidGroupPolicyExpenseReport(report: OnyxEntry<Report>): boolean {
-    return isExpenseReport(report) && isPaidGroupPolicy(report);
+function isGroupPolicyExpenseReport(report: OnyxEntry<Report>): boolean {
+    return isExpenseReport(report) && isReportInGroupPolicy(report);
 }
 
 /**
@@ -4459,6 +4463,9 @@ function isHoldCreator(transaction: OnyxEntry<Transaction>, reportID: string | u
  * 2. Report is settled, closed, approved, or submitted and already forwarded for review
  */
 function isReportFieldDisabled(report: OnyxEntry<Report>, reportField: OnyxEntry<PolicyReportField>, policy: OnyxEntry<Policy>): boolean {
+    if (isInvoiceReport(report)) {
+        return true;
+    }
     const isReportSettled = isSettled(report?.reportID);
     const isReportClosed = isClosedReport(report);
     const isTitleField = isReportFieldOfTypeTitle(reportField);
@@ -4500,7 +4507,7 @@ function canEditReportTitle(report: OnyxEntry<Report>, policy: OnyxEntry<Policy>
         getAvailableReportFields(report, Object.values(policy?.fieldList ?? {})).find((reportField) => isReportFieldOfTypeTitle(reportField)) ?? getTitleFieldWithFallback(policy);
     const isFieldDisabled = isReportFieldDisabled(report, titleField, policy);
 
-    return !isFieldDisabled && isAdminOwnerApproverOrReportOwner(report, policy, currentUserAccountID) && isExpenseReport(report) && isPaidGroupPolicyPolicyUtils(policy);
+    return !isFieldDisabled && isAdminOwnerApproverOrReportOwner(report, policy, currentUserAccountID) && isExpenseReport(report) && isGroupPolicyPolicyUtils(policy);
 }
 
 /**
@@ -4577,7 +4584,7 @@ function getAvailableReportFields(report: OnyxEntry<Report>, policyReportFields:
     const mergedFieldIds = Array.from(new Set([...policyReportFields.map(({fieldID}) => fieldID), ...reportFields.map(({fieldID}) => fieldID)]));
 
     const fields = mergedFieldIds.map((id) => {
-        const field = report?.fieldList?.[getReportFieldKey(id)] ?? report?.fieldList?.[id];
+        const field = report?.fieldList?.[getReportFieldKey(id)];
         const policyReportField = policyReportFields.find(({fieldID}) => fieldID === id);
 
         if (field) {
@@ -4620,7 +4627,7 @@ function getTransactionDetails(
     }
 
     const report = getReportOrDraftReport(transaction?.reportID, undefined, 'report' in transaction ? transaction.report : undefined);
-    const isFromExpenseReport = (!isEmptyObject(report) && isExpenseReport(report)) || isPaidGroupPolicyPolicyUtils(policy);
+    const isFromExpenseReport = (!isEmptyObject(report) && isExpenseReport(report)) || isGroupPolicyPolicyUtils(policy);
 
     return {
         created: getFormattedCreated(transaction, createdDateFormat),
@@ -5647,6 +5654,11 @@ function getModifiedExpenseOriginalMessage(
         originalMessage.reimbursable = transactionChanges?.reimbursable ? 'reimbursable' : 'non-reimbursable';
     }
 
+    if ('vendor' in transactionChanges) {
+        originalMessage.oldVendor = oldTransaction?.comment?.vendor ?? null;
+        originalMessage.vendor = transactionChanges?.vendor ?? null;
+    }
+
     if ('billable' in transactionChanges) {
         const oldBillable = getBillable(oldTransaction);
         originalMessage.oldBillable = oldBillable ? 'billable' : 'non-billable';
@@ -5949,20 +5961,20 @@ function goBackFromPrivateNotes(report: OnyxEntry<Report>, accountID?: number) {
     Navigation.goBack();
 }
 
-function navigateOnDeleteExpense(backToRoute: Route) {
+function navigateOnDeleteExpense(backToRoute: Route, afterTransition?: () => void) {
     if (isSearchTopmostFullScreenRoute()) {
-        Navigation.dismissModal();
+        Navigation.dismissModal({afterTransition});
         return;
     }
 
     const rootState = navigationRef.getRootState();
     const focusedRoute = findFocusedRoute(rootState);
     if (focusedRoute?.params && 'backTo' in focusedRoute.params) {
-        Navigation.goBack(focusedRoute.params.backTo as Route);
+        Navigation.goBack(focusedRoute.params.backTo as Route, {afterTransition});
         return;
     }
 
-    Navigation.goBack(backToRoute);
+    Navigation.goBack(backToRoute, {afterTransition});
 }
 
 /**
@@ -10973,7 +10985,7 @@ function canJoinChat(
     }
 
     // For restricted visibility rooms, the user must be a workspace member to join
-    if (isUserCreatedPolicyRoom(report) && report?.visibility === CONST.REPORT.VISIBILITY.RESTRICTED && !isPolicyMember(policy, deprecatedCurrentUserEmail)) {
+    if (isUserCreatedPolicyRoom(report) && report?.visibility === CONST.REPORT.VISIBILITY.RESTRICTED && !getPolicyRole(policy, deprecatedCurrentUserEmail)) {
         return false;
     }
 
@@ -11055,10 +11067,7 @@ function createDraftWorkspaceAndNavigateToConfirmationScreen(
     ]);
     setMoneyRequestReportID(transactionID, expenseChatReportID);
     if (isCategorizing) {
-        const confirmationRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID, undefined, true);
-        Navigation.navigate(
-            createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID), confirmationRoute),
-        );
+        Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID));
     } else {
         Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID, undefined, true));
     }
@@ -11183,10 +11192,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({
                 },
             ]);
             if (policyExpenseReportID) {
-                const confirmationRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID, undefined, true);
-                Navigation.navigate(
-                    createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID), confirmationRoute),
-                );
+                Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID));
             } else {
                 Log.warn('policyExpenseReportID is not valid during expense categorizing');
             }
@@ -11194,16 +11200,15 @@ function createDraftTransactionAndNavigateToParticipantSelector({
         }
         if (filteredPoliciesCount === 0 || filteredPoliciesCount > 1) {
             Navigation.navigate(
-                createDynamicRoute(
-                    DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                        action: actionName,
-                        iouType: CONST.IOU.TYPE.SUBMIT,
-                        transactionID,
-                        reportID,
-                        upgradePath: actionName === CONST.IOU.ACTION.CATEGORIZE ? CONST.UPGRADE_PATHS.CATEGORIES : '',
-                        shouldSubmitExpense: true,
-                    }),
-                ),
+                ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                    action: actionName,
+                    iouType: CONST.IOU.TYPE.SUBMIT,
+                    transactionID,
+                    reportID,
+                    backTo: '',
+                    upgradePath: actionName === CONST.IOU.ACTION.CATEGORIZE ? CONST.UPGRADE_PATHS.CATEGORIES : '',
+                    shouldSubmitExpense: true,
+                }),
             );
             return;
         }
@@ -11221,10 +11226,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({
             },
         ]);
         if (policyExpenseReportID) {
-            const confirmationRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID, undefined, true);
-            Navigation.navigate(
-                createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID), confirmationRoute),
-            );
+            Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID));
         } else {
             Log.warn('policyExpenseReportID is not valid during expense categorizing');
         }
@@ -11232,7 +11234,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({
     }
 
     if (actionName === CONST.IOU.ACTION.SHARE) {
-        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_ACCOUNTANT.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, reportID), Navigation.getActiveRoute()));
+        Navigation.navigate(ROUTES.MONEY_REQUEST_ACCOUNTANT.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, reportID, Navigation.getActiveRoute()));
         return;
     }
 
@@ -12309,7 +12311,7 @@ function isWorkspaceEligibleForReportChange(submitterEmail: string | undefined,
     if (report?.stateNum === CONST.REPORT.STATE_NUM.APPROVED && report.statusNum === CONST.REPORT.STATUS_NUM.CLOSED && !isPolicyAdminPolicyUtils(newPolicy)) {
         return false;
     }
-    return isPaidGroupPolicyPolicyUtils(newPolicy) && !!newPolicy.role && !isPendingDeletePolicy(newPolicy);
+    return isGroupPolicyPolicyUtils(newPolicy) && !!newPolicy.role && !isPendingDeletePolicy(newPolicy);
 }
 
 /**
@@ -12889,39 +12891,19 @@ function shouldHideSingleReportField(reportField: PolicyReportField) {
     return isReportFieldOfTypeTitle(reportField) || !hasEnableOption;
 }
 
-function isReportNameValuePairField(value: unknown): value is PolicyReportField {
-    return typeof value === 'object' && value !== null && 'fieldID' in value && typeof value.fieldID === 'string' && 'name' in value && typeof value.name === 'string';
-}
-
-function getReportFieldFromReportNameValuePairs(reportNameValuePairs: OnyxEntry<ReportNameValuePairs>, reportFieldIDOrKey: string): PolicyReportField | undefined {
-    for (const [key, value] of Object.entries(reportNameValuePairs ?? {})) {
-        if (key === reportFieldIDOrKey && isReportNameValuePairField(value)) {
-            return value;
-        }
-    }
-
-    return undefined;
-}
-
 /**
  * Get both field values map and fields-by-name map in a single pass
  */
 function getReportFieldMaps(report: OnyxEntry<Report>, fieldList: Record<string, PolicyReportField>): {fieldValues: Record<string, string>; fieldsByName: Record<string, PolicyReportField>} {
     const fields = getAvailableReportFields(report, Object.values(fieldList ?? {}));
-    const reportNameValuePairs = allReportNameValuePair?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`];
     const fieldValues: Record<string, string> = {};
     const fieldsByName: Record<string, PolicyReportField> = {};
 
     for (const field of fields) {
         if (field.name) {
-            const fieldKey = getReportFieldKey(field.fieldID);
-            const shouldReadReportNameValuePair = report?.type === CONST.REPORT.TYPE.INVOICE && field.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-            const reportNameValuePairField = shouldReadReportNameValuePair
-                ? (getReportFieldFromReportNameValuePairs(reportNameValuePairs, fieldKey) ?? getReportFieldFromReportNameValuePairs(reportNameValuePairs, field.fieldID))
-                : undefined;
             const key = field.name.toLowerCase();
-            fieldValues[key] = reportNameValuePairField?.value ?? field.value ?? field.defaultValue ?? '';
-            fieldsByName[key] = reportNameValuePairField ? {...field, value: reportNameValuePairField.value} : field;
+            fieldValues[key] = field.value ?? field.defaultValue ?? '';
+            fieldsByName[key] = field;
         }
     }
 
@@ -13012,6 +12994,18 @@ function getLinkedIOUTransaction(reportAction: OnyxEntry<ReportAction | Optimist
     return transactionID ? transactions.find((item) => item.transactionID === transactionID) : undefined;
 }
 
+/**
+ * Returns true if the "Mark as done" copy/button should be shown.
+ * Aligns with backend: only shown when all four conditions are true (isTrackIntentUser, isSubmitAndClose, isSubmitter, isSubmittingToSelf).
+ *
+ */
+function shouldShowMarkAsDone({isTrackIntentUser, report, policy}: {isTrackIntentUser?: boolean; report: OnyxEntry<Report>; policy: OnyxEntry<Policy>}): boolean {
+    if (!isTrackIntentUser || !isSubmitAndClose(policy) || !isReportOwner(report)) {
+        return false;
+    }
+    return getNextApproverAccountID(report) === report?.ownerAccountID;
+}
+
 export {
     areAllRequestsBeingSmartScanned,
     buildConciergeGreetingReportAction,
@@ -13240,8 +13234,7 @@ export {
     isOpenExpenseReport,
     isOpenTaskReport,
     isOptimisticPersonalDetail,
-    isPaidGroupPolicy,
-    isPaidGroupPolicyExpenseReport,
+    isGroupPolicyExpenseReport,
     isPayer,
     isPolicyAdmin,
     isPolicyExpenseChat,
@@ -13355,7 +13348,6 @@ export {
     buildOptimisticResolvedDuplicatesReportAction,
     getTitleReportField,
     getTitleFieldWithFallback,
-    getReportFieldFromReportNameValuePairs,
     getReportFieldsByPolicyID,
     getChatListItemReportName,
     buildOptimisticMovedTransactionAction,
@@ -13396,6 +13388,7 @@ export {
     getTransactionSortValue,
     isSortableColumnName,
     getLinkedIOUTransaction,
+    shouldShowMarkAsDone,
     hasHeldExpensesFromTransactions,
     canModifyHoldStatus,
 };
diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts
index 4061fec21aa4..a8e50f597574 100644
--- a/src/libs/SearchUIUtils.ts
+++ b/src/libs/SearchUIUtils.ts
@@ -17,6 +17,8 @@ import TransactionGroupListItem from '@components/Search/SearchList/ListItem/Tra
 import TransactionListItem from '@components/Search/SearchList/ListItem/TransactionListItem';
 import type {
     ExpenseReportListItemType,
+    GroupChildrenContainerItemType,
+    GroupHeaderItemType,
     ReportActionListItemType,
     SearchListItem,
     TaskListItemType,
@@ -34,6 +36,7 @@ import type {
     TransactionWithdrawalIDGroupListItemType,
     TransactionYearGroupListItemType,
 } from '@components/Search/SearchList/ListItem/types';
+import {GROUP_ITEM_TYPES} from '@components/Search/SearchList/ListItem/types';
 import type {
     GroupedItem,
     QueryFilters,
@@ -100,7 +103,7 @@ import {setOptimisticDataForTransactionThreadPreview} from './actions/Search';
 import {convertAttendeesToArray} from './AttendeeUtils';
 import type {CardFeedForDisplay} from './CardFeedUtils';
 import {getCardFeedsForDisplay} from './CardFeedUtils';
-import {getCardDescriptionForSearchTable, getFeedNameForDisplay} from './CardUtils';
+import {getCardDescriptionForSearchTable, getFeedNameForDisplay, isPersonalCard} from './CardUtils';
 import {getCategoryGLCode, getDecodedCategoryName} from './CategoryUtils';
 import DateUtils from './DateUtils';
 import interceptAnonymousUser from './interceptAnonymousUser';
@@ -603,6 +606,7 @@ type GetSectionsParams = {
     isOffline?: boolean;
     cardFeeds?: OnyxCollection<OnyxTypes.CardFeeds>;
     cardList?: OnyxEntry<OnyxTypes.CardList>;
+    nonPersonalAndWorkspaceCardList?: OnyxEntry<OnyxTypes.CardList>;
     customCardNames?: Record<number, string>;
     allTransactionViolations?: OnyxCollection<OnyxTypes.TransactionViolation[]>;
     visibleReportActionsData?: OnyxTypes.VisibleReportActionsDerivedValue;
@@ -3196,6 +3200,7 @@ function getCardSections(
     cardFeeds?: OnyxCollection<OnyxTypes.CardFeeds>,
     customCardNames?: Record<number, string>,
     cardList?: OnyxEntry<OnyxTypes.CardList>,
+    nonPersonalAndWorkspaceCardList?: OnyxEntry<OnyxTypes.CardList>,
 ): [TransactionCardGroupListItemType[], number, boolean] {
     const cardSections: Record<string, TransactionCardGroupListItemType> = {};
     const cardDescriptionByCardID = new Map<number, string>();
@@ -3232,6 +3237,11 @@ function getCardSections(
                 formattedCardName = formattedCardNameWithDotAndLastFour(formattedCardName, cardGroup.lastFourPAN);
             }
 
+            const card = cardList?.[cardGroup.cardID];
+            // A workspace/company card from a card feed can also lack a `fundID`, so `isPersonalCard` alone would misclassify it.
+            // The non-personal card list keeps every company/workspace-feed card while filtering personal cards out, so presence
+            // there means the card is definitively NOT personal.
+            const isPersonal = !!card && isPersonalCard(card) && !nonPersonalAndWorkspaceCardList?.[cardGroup.cardID];
             cardSections[key] = {
                 groupedBy: CONST.SEARCH.GROUP_BY.CARD,
                 transactions: [],
@@ -3239,18 +3249,20 @@ function getCardSections(
                 ...personalDetails,
                 ...cardGroup,
                 formattedCardName,
-                formattedFeedName: getFeedNameForDisplay(
-                    translate,
-                    cardGroup.bank as OnyxTypes.CompanyCardFeed,
-                    cardFeeds,
-                    cardList?.[cardGroup.cardID]?.fundID
-                        ? cardFeeds?.[`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${cardList[cardGroup.cardID].fundID}`]?.settings?.companyCardNicknames?.[
-                              cardGroup.bank as OnyxTypes.CompanyCardFeed
-                          ]
-                        : undefined,
-                    true,
-                    cardGroup?.feedCountry,
-                ),
+                formattedFeedName: isPersonal
+                    ? translate('cardTransactions.personalCard')
+                    : getFeedNameForDisplay(
+                          translate,
+                          cardGroup.bank as OnyxTypes.CompanyCardFeed,
+                          cardFeeds,
+                          card?.fundID
+                              ? cardFeeds?.[`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${card.fundID}`]?.settings?.companyCardNicknames?.[
+                                    cardGroup.bank as OnyxTypes.CompanyCardFeed
+                                ]
+                              : undefined,
+                          true,
+                          cardGroup?.feedCountry,
+                      ),
                 keyForList: key,
             };
         }
@@ -3588,6 +3600,7 @@ function getSections({
     isOffline,
     cardFeeds,
     cardList,
+    nonPersonalAndWorkspaceCardList,
     customCardNames,
     allTransactionViolations,
     visibleReportActionsData,
@@ -3632,7 +3645,7 @@ function getSections({
             case CONST.SEARCH.GROUP_BY.FROM:
                 return getMemberSections(data, queryJSON, formatPhoneNumber);
             case CONST.SEARCH.GROUP_BY.CARD:
-                return getCardSections(data, queryJSON, translate, cardFeeds, customCardNames, cardList);
+                return getCardSections(data, queryJSON, translate, cardFeeds, customCardNames, cardList, nonPersonalAndWorkspaceCardList);
             case CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID:
                 return getWithdrawalIDSections(data, queryJSON);
             case CONST.SEARCH.GROUP_BY.CATEGORY:
@@ -6208,6 +6221,24 @@ function hasFlexColumn(columns?: SearchColumnType[]): boolean {
     return !!columns?.some((col) => FLEX_COLUMNS.has(col));
 }
 
+function splitGroupsIntoPairs(data: SearchListItem[]): {splitData: SearchListItem[]; stickyHeaderIndices: number[]} {
+    const splitData: SearchListItem[] = [];
+    const stickyHeaderIndices: number[] = [];
+
+    for (const item of data) {
+        if ('transactions' in item) {
+            const key = item.keyForList ?? '';
+            stickyHeaderIndices.push(splitData.length);
+            splitData.push({...item, listItemType: GROUP_ITEM_TYPES.GROUP_HEADER, keyForList: `header_${key}`} as GroupHeaderItemType);
+            splitData.push({...item, listItemType: GROUP_ITEM_TYPES.CHILDREN_CONTAINER, keyForList: `children_${key}`} as GroupChildrenContainerItemType);
+        } else {
+            splitData.push(item);
+        }
+    }
+
+    return {splitData, stickyHeaderIndices};
+}
+
 export {
     getSearchBulkEditPolicyID,
     getSuggestedSearches,
@@ -6293,6 +6324,7 @@ export {
     isPolicyEligibleForSpendOverTime,
     hasFlexColumn,
     isTransactionSearchType,
+    splitGroupsIntoPairs,
     SKIPPED_SEARCH_FILTERS,
 };
 export type {SavedSearchMenuItem, SearchTypeMenuSection, SearchTypeMenuItem, SearchDateModifier, SearchDateModifierLower, SearchKey, ArchivedReportsIDSet, GroupBySection, SearchFilter};
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 5cab9b06fe37..aa26db8dd98d 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -46,6 +46,7 @@ import {
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
     getCardIssuedMessage,
+    getCategoryTaxRateMessage,
     getChangedApproverActionMessage,
     getCompanyAddressUpdateMessage,
     getCompanyCardConnectionBrokenMessage,
@@ -215,6 +216,8 @@ type WelcomeMessageParams = {
     reportDetailsLink?: string;
     shouldShowUsePlusButtonText?: boolean;
     additionalText?: string;
+    isTrackIntentUser?: boolean;
+    currentUserAccountID?: number;
 };
 
 function compareStringDates(a: string, b: string): 0 | 1 | -1 {
@@ -395,6 +398,7 @@ function getReportsToDisplayInLHN({
         }
 
         const reportDraftComment = draftComments?.[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`];
+        const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]);
 
         const {shouldDisplay, hasErrorsOtherThanFailedReceipt} = shouldDisplayReportInLHN({
             report,
@@ -406,7 +410,7 @@ function getReportsToDisplayInLHN({
             draftComment: reportDraftComment,
             transactions,
             isOffline,
-            isReportArchived: isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]),
+            isReportArchived,
             reportAttributes,
             currentUserLogin,
             currentUserAccountID,
@@ -414,8 +418,9 @@ function getReportsToDisplayInLHN({
 
         if (shouldDisplay) {
             const requiresAttention = reportAttributes?.[report?.reportID]?.requiresAttention ?? false;
-            const hasAttentionOrError = requiresAttention || hasErrorsOtherThanFailedReceipt;
-            reportsToDisplay[reportID] = hasAttentionOrError ? {...report, requiresAttention, hasErrorsOtherThanFailedReceipt} : report;
+            const isUnreadReport = getIsUnreadReportForInboxTab(report, isReportArchived);
+            reportsToDisplay[reportID] =
+                requiresAttention || hasErrorsOtherThanFailedReceipt || isUnreadReport ? {...report, requiresAttention, hasErrorsOtherThanFailedReceipt, isUnreadReport} : report;
         }
     }
 
@@ -476,6 +481,7 @@ function updateReportsToDisplayInLHN({
         // Get the specific draft comment for this report instead of using a single draft comment for all reports
         // This fixes the issue where the current report's draft comment was incorrectly used to filter all reports
         const reportDraftComment = draftComments?.[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`];
+        const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`] ?? {});
 
         const {shouldDisplay, hasErrorsOtherThanFailedReceipt} = shouldDisplayReportInLHN({
             report,
@@ -487,7 +493,7 @@ function updateReportsToDisplayInLHN({
             draftComment: reportDraftComment,
             transactions,
             isOffline,
-            isReportArchived: isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`] ?? {}),
+            isReportArchived,
             reportAttributes,
             currentUserLogin,
             currentUserAccountID,
@@ -495,16 +501,19 @@ function updateReportsToDisplayInLHN({
 
         if (shouldDisplay) {
             const requiresAttention = reportAttributes?.[report?.reportID]?.requiresAttention ?? false;
-            const hasAttentionOrError = requiresAttention || hasErrorsOtherThanFailedReceipt;
+            const isUnreadReport = getIsUnreadReportForInboxTab(report, isReportArchived);
+            // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+            const hasFlags = requiresAttention || hasErrorsOtherThanFailedReceipt || isUnreadReport;
             const existingEntry = displayedReports[reportID];
 
-            if (hasAttentionOrError) {
+            if (hasFlags) {
                 if (
                     existingEntry !== report ||
                     existingEntry?.requiresAttention !== requiresAttention ||
-                    existingEntry?.hasErrorsOtherThanFailedReceipt !== hasErrorsOtherThanFailedReceipt
+                    existingEntry?.hasErrorsOtherThanFailedReceipt !== hasErrorsOtherThanFailedReceipt ||
+                    existingEntry?.isUnreadReport !== isUnreadReport
                 ) {
-                    getMutableCopy()[reportID] = {...report, requiresAttention, hasErrorsOtherThanFailedReceipt};
+                    getMutableCopy()[reportID] = {...report, requiresAttention, hasErrorsOtherThanFailedReceipt, isUnreadReport};
                 }
             } else if (existingEntry !== report) {
                 getMutableCopy()[reportID] = report;
@@ -793,6 +802,7 @@ function getOptionData({
     reportAttributesDerived,
     policyTags,
     currentUserLogin,
+    isTrackIntentUser,
 }: {
     report: OnyxEntry<Report>;
     oneTransactionThreadReport: OnyxEntry<Report>;
@@ -817,6 +827,7 @@ function getOptionData({
     reportAttributesDerived?: ReportAttributesDerivedValue['reports'];
     policyTags?: OnyxEntry<PolicyTagLists>;
     currentUserLogin: string;
+    isTrackIntentUser?: boolean;
 }): OptionData | undefined {
     // When a user signs out, Onyx is cleared. Due to the lazy rendering with a virtual list, it's possible for
     // this method to be called after the Onyx data has been cleared out. In that case, it's fine to do
@@ -975,6 +986,7 @@ function getOptionData({
             policyTags,
             currentUserLogin,
             lastAction,
+            isTrackIntentUser,
         });
     }
 
@@ -1119,6 +1131,8 @@ function getOptionData({
             result.alternateText = getAutoPayApprovedReportsEnabledMessage(translate, lastAction);
         } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT) {
             result.alternateText = getAutoReimbursementMessage(translate, lastAction);
+        } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE) {
+            result.alternateText = getCategoryTaxRateMessage(translate, lastAction);
         } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MCC_GROUP_CATEGORY) {
             result.alternateText = getMccGroupCategoryMessage(translate, lastAction);
         } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_DEFAULT_APPROVER) {
@@ -1281,6 +1295,8 @@ function getOptionData({
                         conciergeReportID,
                         reportAttributes: reportAttributesDerived,
                         isReportArchived,
+                        isTrackIntentUser,
+                        currentUserAccountID,
                     }).messageText ?? translate('report.noActivityYet'),
                 );
             }
@@ -1386,6 +1402,8 @@ function getWelcomeMessage(params: WelcomeMessageParams): WelcomeMessage {
         reportDetailsLink = '',
         shouldShowUsePlusButtonText = false,
         additionalText = '',
+        isTrackIntentUser = false,
+        currentUserAccountID,
     } = params;
 
     const welcomeMessage: WelcomeMessage = {};
@@ -1401,6 +1419,9 @@ function getWelcomeMessage(params: WelcomeMessageParams): WelcomeMessage {
         if (policy?.description) {
             welcomeMessage.messageHtml = policy.description;
             welcomeMessage.messageText = Parser.htmlToText(welcomeMessage.messageHtml);
+        } else if (isTrackIntentUser && report?.ownerAccountID === currentUserAccountID) {
+            welcomeMessage.messageHtml = translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatTrack');
+            welcomeMessage.messageText = Parser.htmlToText(welcomeMessage.messageHtml);
         } else {
             welcomeMessage.messageHtml = translate(
                 'reportActionsView.beginningOfChatHistoryPolicyExpenseChat',
@@ -1491,6 +1512,72 @@ function getRoomWelcomeMessage(
     return welcomeMessage;
 }
 
+/**
+ * Whether a report should appear in the "Unread" Inbox tab: it has unread messages and is not muted.
+ * Computed once while building the LHN report set (which is cached/incremental) so the tab filter only reads a flag.
+ */
+function getIsUnreadReportForInboxTab(report: Report, isReportArchived: boolean): boolean {
+    // The `lastActorAccountID` guard matches getOptionData: it keeps chats whose only visible message was
+    // deleted out of the Unread tab even though isUnread() can still be true (lastVisibleActionCreated isn't reset).
+    return isUnread(report, undefined, isReportArchived) && !!report.lastActorAccountID && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
+}
+
+/** Whether a report belongs in the "To-do" Inbox tab: it has an outstanding GBR (requiresAttention) or RBR (errors). */
+function getIsTodoReportForInboxTab(report: ReportsToDisplayInLHN[string]): boolean {
+    return !!report.requiresAttention || !!report.hasErrorsOtherThanFailedReceipt;
+}
+
+/**
+ * Filters the already-ordered LHN report IDs down to the ones that belong to the active Inbox tab.
+ * The "All" tab returns everything (and still honors Most Recent / Focus mode upstream); the other
+ * tabs narrow that same set to reports requiring action (To-do) or with unread messages (Unread).
+ */
+function filterReportsForInboxTab(reportIDs: string[], reportsToDisplay: ReportsToDisplayInLHN, activeTab: ValueOf<typeof CONST.INBOX_TAB>): string[] {
+    if (activeTab === CONST.INBOX_TAB.ALL) {
+        return reportIDs;
+    }
+
+    return reportIDs.filter((reportID) => {
+        const report = reportsToDisplay[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+        if (!report) {
+            return false;
+        }
+
+        switch (activeTab) {
+            case CONST.INBOX_TAB.TODO:
+                return getIsTodoReportForInboxTab(report);
+            case CONST.INBOX_TAB.UNREAD:
+                return !!report.isUnreadReport;
+            default:
+                return true;
+        }
+    });
+}
+
+/** Counts how many of the ordered reports fall into the To-do and Unread Inbox tabs, for the count badge shown on each. */
+function getInboxTabCounts(reportIDs: string[], reportsToDisplay: ReportsToDisplayInLHN): Record<typeof CONST.INBOX_TAB.TODO | typeof CONST.INBOX_TAB.UNREAD, number> {
+    let todoCount = 0;
+    let unreadCount = 0;
+
+    for (const reportID of reportIDs) {
+        const report = reportsToDisplay[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+        if (!report) {
+            continue;
+        }
+        if (getIsTodoReportForInboxTab(report)) {
+            todoCount++;
+        }
+        if (report.isUnreadReport) {
+            unreadCount++;
+        }
+    }
+
+    return {
+        [CONST.INBOX_TAB.TODO]: todoCount,
+        [CONST.INBOX_TAB.UNREAD]: unreadCount,
+    };
+}
+
 // Exported for unit testing only. Do not use directly in production code.
 export {
     categorizeReportsForLHN as _categorizeReportsForLHN,
@@ -1507,4 +1594,6 @@ export default {
     getReportsToDisplayInLHN,
     updateReportsToDisplayInLHN,
     shouldDisplayReportInLHN,
+    filterReportsForInboxTab,
+    getInboxTabCounts,
 };
diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index fe355b114ad9..c5cff6e27412 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -1,12 +1,10 @@
 import {Str} from 'expensify-common';
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
+import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import type {LocaleContextProps} from '@components/LocaleContextProvider';
 import type {CurrencyListActionsContextType} from '@hooks/useCurrencyList';
 import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
 import type {BankAccountList} from '@src/types/onyx';
-import type AgentPrompt from '@src/types/onyx/AgentPrompt';
 import type {ApprovalWorkflowOnyx, Approver, Member} from '@src/types/onyx/ApprovalWorkflow';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
 import type {PersonalDetailsList} from '@src/types/onyx/PersonalDetails';
@@ -718,93 +716,6 @@ function mergeWorkflowMembersWithAvailableMembers(workflowMembers: Member[], all
     return [...workflowMembers, ...additionalMembers];
 }
 
-type ResolveOptimisticAgentParams = {
-    /** Optimistic accountID assigned to the pending agent before CREATE_AGENT resolved */
-    optimisticAccountID: number;
-
-    /** Agent prompt captured while the optimistic entry was still live; used for cross-tab fallback */
-    pendingAgentPrompt: string | undefined;
-
-    /** Live personal details map */
-    personalDetails: PersonalDetailsList;
-
-    /** The owning policy's employeeList */
-    employeeList: Policy['employeeList'];
-
-    /** SHARED_NVP_AGENT_PROMPT collection */
-    agentPrompts: OnyxCollection<AgentPrompt> | undefined;
-
-    /** `{optimisticID: realID}` map written by CREATE_AGENT's onyxData */
-    optimisticAccountIDMapping: Record<string, number> | undefined;
-
-    /** Emails already on the workflow's approver chain — skipped to avoid resolving to a pre-existing approver */
-    knownApproverEmails: Set<string>;
-};
-
-type ResolvedOptimisticAgent = {
-    personalDetail: PersonalDetails;
-    accountID: number;
-    email: string;
-};
-
-/**
- * Resolves a pending (optimistic) agent approver to its real personal detail after CREATE_AGENT
- * lands. Tries the `OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING` lookup first (the originating tab's
- * primary path), then falls back to matching by agent prompt — needed when a different tab
- * reconciles and never saw the mapping write. When several agents share the same prompt text the
- * loop picks the highest positive accountID, since the server assigns IDs monotonically and the
- * freshest agent is therefore the largest.
- */
-function resolveOptimisticAgent({
-    optimisticAccountID,
-    pendingAgentPrompt,
-    personalDetails,
-    employeeList,
-    agentPrompts,
-    optimisticAccountIDMapping,
-    knownApproverEmails,
-}: ResolveOptimisticAgentParams): ResolvedOptimisticAgent | undefined {
-    const mappedRealAccountID = optimisticAccountIDMapping?.[optimisticAccountID];
-    if (mappedRealAccountID) {
-        const mappedDetail = personalDetails[mappedRealAccountID];
-        if (mappedDetail?.login && employeeList?.[mappedDetail.login] && !knownApproverEmails.has(mappedDetail.login)) {
-            return {
-                personalDetail: mappedDetail,
-                accountID: mappedDetail.accountID ?? mappedRealAccountID,
-                email: mappedDetail.login,
-            };
-        }
-    }
-
-    if (!pendingAgentPrompt || !agentPrompts) {
-        return undefined;
-    }
-
-    const optimisticPromptKey = `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`;
-    let bestCandidateAccountID = -Infinity;
-    let bestCandidate: ResolvedOptimisticAgent | undefined;
-    for (const [promptKey, promptValue] of Object.entries(agentPrompts)) {
-        if (promptKey === optimisticPromptKey || !promptValue || promptValue.prompt !== pendingAgentPrompt) {
-            continue;
-        }
-        const candidateAccountID = Number(promptKey.slice(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT.length));
-        if (!Number.isFinite(candidateAccountID) || candidateAccountID <= 0 || candidateAccountID <= bestCandidateAccountID) {
-            continue;
-        }
-        const candidateDetail = personalDetails[candidateAccountID];
-        if (!candidateDetail?.login || !employeeList?.[candidateDetail.login] || knownApproverEmails.has(candidateDetail.login)) {
-            continue;
-        }
-        bestCandidate = {
-            personalDetail: candidateDetail,
-            accountID: candidateDetail.accountID ?? candidateAccountID,
-            email: candidateDetail.login,
-        };
-        bestCandidateAccountID = candidateAccountID;
-    }
-    return bestCandidate;
-}
-
 export {
     calculateApprovers,
     convertPolicyEmployeesToApprovalWorkflows,
@@ -815,6 +726,5 @@ export {
     getOverLimitForwardsToDisplayName,
     INITIAL_APPROVAL_WORKFLOW,
     mergeWorkflowMembersWithAvailableMembers,
-    resolveOptimisticAgent,
     updateWorkflowDataOnApproverRemoval,
 };
diff --git a/src/libs/WorkspaceReportFieldUtils.ts b/src/libs/WorkspaceReportFieldUtils.ts
index 306bd7048a3c..a7d127e9d728 100644
--- a/src/libs/WorkspaceReportFieldUtils.ts
+++ b/src/libs/WorkspaceReportFieldUtils.ts
@@ -1,4 +1,3 @@
-import type {ValueOf} from 'type-fest';
 import type {FormInputErrors} from '@components/Form/types';
 import type {LocalizedTranslate} from '@components/LocaleContextProvider';
 import CONST from '@src/CONST';
@@ -64,9 +63,8 @@ function validateReportFieldListValueName(
 /**
  * Generates a field ID based on the field name.
  */
-function generateFieldID(name: string, target?: ValueOf<typeof CONST.REPORT_FIELD_TARGETS>) {
-    const targetPrefix = target ? `${target.toUpperCase()}_` : '';
-    return `field_id_${targetPrefix}${name.replaceAll(CONST.REGEX.ANY_SPACE, '_').toUpperCase()}`;
+function generateFieldID(name: string) {
+    return `field_id_${name.replaceAll(CONST.REGEX.ANY_SPACE, '_').toUpperCase()}`;
 }
 
 /**
@@ -108,33 +106,8 @@ function hasFormulaPartsInInitialValue(initialValue?: string): boolean {
 /**
  * Checks if a report field name already exists in the policy's field list (case-insensitive).
  */
-function isReportFieldNameExisting(fieldList: Record<string, PolicyReportField> | undefined, fieldName: string, expectedTarget?: ValueOf<typeof CONST.REPORT_FIELD_TARGETS>): boolean {
-    return Object.values(fieldList ?? {}).some((reportField) => {
-        if (!isReportFieldTargetValid(reportField, expectedTarget)) {
-            return false;
-        }
-
-        return reportField.name.toLowerCase() === fieldName.toLowerCase();
-    });
-}
-
-/**
- * Determines whether a report field matches the expected target.
- */
-function isReportFieldTargetValid(reportField: PolicyReportField | null, expectedTarget?: ValueOf<typeof CONST.REPORT_FIELD_TARGETS>): boolean {
-    if (!reportField) {
-        return false;
-    }
-
-    if (expectedTarget === CONST.REPORT_FIELD_TARGETS.INVOICE) {
-        return reportField.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    }
-
-    if (expectedTarget === CONST.REPORT_FIELD_TARGETS.EXPENSE) {
-        return !reportField.target || reportField.target === CONST.REPORT_FIELD_TARGETS.EXPENSE;
-    }
-
-    return true;
+function isReportFieldNameExisting(fieldList: Record<string, PolicyReportField> | undefined, fieldName: string): boolean {
+    return Object.values(fieldList ?? {}).some((reportField) => reportField.name.toLowerCase() === fieldName.toLowerCase());
 }
 
 /**
@@ -245,5 +218,4 @@ export {
     getUnsupportedReportFieldFormulaParts,
     hasFormulaPartsInInitialValue,
     isReportFieldNameExisting,
-    isReportFieldTargetValid,
 };
diff --git a/src/libs/actions/Agent.ts b/src/libs/actions/Agent.ts
index 247e9c5135b3..8d00bfc446a4 100644
--- a/src/libs/actions/Agent.ts
+++ b/src/libs/actions/Agent.ts
@@ -72,11 +72,6 @@ function createAgent(
             key: `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`,
             value: null,
         },
-        {
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING,
-            value: {[optimisticAccountID]: null},
-        },
     ];
 
     const failureData: AnyOnyxUpdate[] = [
@@ -94,45 +89,8 @@ function createAgent(
                 errors: getMicroSecondOnyxErrorWithTranslationKey('agentsPage.error.genericAdd'),
             },
         },
-        {
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING,
-            value: {[optimisticAccountID]: null},
-        },
     ];
 
-    // When the agent is being created as part of a workspace flow, also mirror the
-    // pending/error state onto the policy. That way the failure surfaces as a brick road
-    // indicator on the workspace and an inline error on the Workflows page, instead of
-    // being hidden away in Settings > Agents (where the admin may never look).
-    if (policyID) {
-        const policyKey = `${ONYXKEYS.COLLECTION.POLICY}${policyID}` as const;
-        optimisticData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: policyKey,
-            value: {
-                pendingFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD},
-                errorFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null},
-            },
-        });
-        successData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: policyKey,
-            value: {
-                pendingFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null},
-                errorFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null},
-            },
-        });
-        failureData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: policyKey,
-            value: {
-                pendingFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null},
-                errorFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: getMicroSecondOnyxErrorWithTranslationKey('agentsPage.error.genericAdd')},
-            },
-        });
-    }
-
     write(
         WRITE_COMMANDS.CREATE_AGENT,
         {firstName, prompt, customExpensifyAvatarID, file, policyID, optimisticAccountID: String(optimisticAccountID)},
@@ -147,20 +105,6 @@ function clearAgentError(optimisticAccountID: number) {
     Onyx.set(`${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`, null);
 }
 
-/**
- * Discard a failed optimistic agent that was seeded into an approval workflow. Wipes the
- * deferred workflow save (so the agent stops appearing as a pending approver), the optimistic
- * personal detail + prompt entry, the optimistic->real ID mapping slot, and the policy-level
- * addAgent error. Used by the RBR X click on the workflows page.
- */
-function clearPendingAgentFromApprovalWorkflow(policyID: string, firstApproverEmail: string, optimisticAccountID: number) {
-    Onyx.merge(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES, {[`${policyID}:${firstApproverEmail}`]: null});
-    Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {[optimisticAccountID]: null});
-    Onyx.set(`${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`, null);
-    Onyx.merge(ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING, {[optimisticAccountID]: null});
-    Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null}});
-}
-
 function clearAgentUpdateError(accountID: number) {
     Onyx.merge(`${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${accountID}`, {errors: null, nameErrors: null, promptErrors: null, avatarErrors: null});
 }
@@ -385,7 +329,6 @@ export {
     openProfilePage,
     createAgent,
     clearAgentError,
-    clearPendingAgentFromApprovalWorkflow,
     clearAgentUpdateError,
     clearAgentNameUpdateError,
     clearAgentPromptUpdateError,
diff --git a/src/libs/actions/ClearReportActionErrors.ts b/src/libs/actions/ClearReportActionErrors.ts
index fa6d53930616..dbe7df2e86dc 100644
--- a/src/libs/actions/ClearReportActionErrors.ts
+++ b/src/libs/actions/ClearReportActionErrors.ts
@@ -8,7 +8,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
 import type * as OnyxTypes from '@src/types/onyx';
 import type ReportAction from '@src/types/onyx/ReportAction';
 import type {SearchResultDataType} from '@src/types/onyx/SearchResults';
-import {deleteReport} from './Report';
+import deleteReport from './Report/DeleteReport';
 
 type IgnoreDirection = 'parent' | 'child';
 
diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts
index 0325a337fd17..86e137d4562b 100644
--- a/src/libs/actions/Delegate.ts
+++ b/src/libs/actions/Delegate.ts
@@ -2,7 +2,12 @@ import HybridAppModule from '@expensify/react-native-hybrid-app';
 import Onyx from 'react-native-onyx';
 import type {OnyxEntry, OnyxKey, OnyxUpdate} from 'react-native-onyx';
 import * as API from '@libs/API';
-import type {AddDelegateParams as APIAddDelegateParams, RemoveDelegateParams as APIRemoveDelegateParams, UpdateDelegateRoleParams as APIUpdateDelegateRoleParams} from '@libs/API/parameters';
+import type {
+    AddDelegateParams as APIAddDelegateParams,
+    RemoveDelegateParams as APIRemoveDelegateParams,
+    RemoveDelegatorParams as APIRemoveDelegatorParams,
+    UpdateDelegateRoleParams as APIUpdateDelegateRoleParams,
+} from '@libs/API/parameters';
 import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
 import * as ErrorUtils from '@libs/ErrorUtils';
 import Log from '@libs/Log';
@@ -79,7 +84,7 @@ type WithValidateCode = {
 
 type WithFieldName = {
     // Constrain to known keys to avoid misspells at call sites
-    fieldName: 'addDelegate' | 'updateDelegateRole'; // but string could work as well
+    fieldName: 'addDelegate' | 'updateDelegateRole' | 'connect' | 'removeDelegator' | 'removeDelegate';
 };
 
 type WithOldDotFlag = {
@@ -570,8 +575,80 @@ function removeDelegate({email, delegatedAccess}: RemoveDelegateParams) {
     API.write(WRITE_COMMANDS.REMOVE_DELEGATE, parameters, {optimisticData, successData, failureData});
 }
 
+function removeDelegator({email, delegatedAccess}: RemoveDelegateParams) {
+    if (!email || !delegatedAccess?.delegators) {
+        return;
+    }
+
+    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.ACCOUNT>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: ONYXKEYS.ACCOUNT,
+            value: {
+                delegatedAccess: {
+                    errorFields: {
+                        removeDelegator: {
+                            [email]: null,
+                        },
+                    },
+                    delegators: delegatedAccess.delegators?.map((delegator) =>
+                        delegator.email === email
+                            ? {
+                                  ...delegator,
+                                  pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
+                                  pendingFields: {email: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, role: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE},
+                              }
+                            : delegator,
+                    ),
+                },
+            },
+        },
+    ];
+
+    const successData: Array<OnyxUpdate<typeof ONYXKEYS.ACCOUNT>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: ONYXKEYS.ACCOUNT,
+            value: {
+                delegatedAccess: {
+                    delegators: delegatedAccess.delegators?.filter((delegator) => delegator.email !== email),
+                },
+            },
+        },
+    ];
+
+    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.ACCOUNT>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: ONYXKEYS.ACCOUNT,
+            value: {
+                delegatedAccess: {
+                    errorFields: {
+                        removeDelegator: {
+                            [email]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('delegate.genericError'),
+                        },
+                    },
+                    delegators: delegatedAccess.delegators?.map((delegator) =>
+                        delegator.email === email
+                            ? {
+                                  ...delegator,
+                                  pendingAction: null,
+                                  pendingFields: undefined,
+                              }
+                            : delegator,
+                    ),
+                },
+            },
+        },
+    ];
+
+    const parameters: APIRemoveDelegatorParams = {delegatorEmail: email};
+
+    API.write(WRITE_COMMANDS.REMOVE_DELEGATOR, parameters, {optimisticData, successData, failureData});
+}
+
 function clearDelegateErrorsByField({email, fieldName, delegatedAccess}: ClearDelegateErrorsByFieldParams) {
-    if (!delegatedAccess?.delegates) {
+    if (!delegatedAccess) {
         return;
     }
 
@@ -704,6 +781,7 @@ export {
     isConnectedAsDelegate,
     updateDelegateRole,
     removeDelegate,
+    removeDelegator,
     openSecuritySettingsPage,
     clearOnyxForDelegateTransition,
 };
diff --git a/src/libs/actions/IOU/Duplicate.ts b/src/libs/actions/IOU/Duplicate.ts
index c42b56b270d4..aa0221d54dd7 100644
--- a/src/libs/actions/IOU/Duplicate.ts
+++ b/src/libs/actions/IOU/Duplicate.ts
@@ -76,6 +76,26 @@ function getIOUActionForTransactions(transactionIDList: Array<string | undefined
     );
 }
 
+type DiscardedSource = {
+    amount: number;
+    actions: Array<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>;
+};
+
+function buildSoftDeleteReportActionUpdate(
+    reportAction: OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>,
+    deletedTime: string | null,
+): NullishDeep<PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>> {
+    if (deletedTime === null) {
+        return {originalMessage: {deleted: null}, message: reportAction.message};
+    }
+    const firstMessage = Array.isArray(reportAction.message) ? reportAction.message.at(0) : null;
+    return {
+        originalMessage: {deleted: deletedTime},
+        ...(firstMessage && {message: [{...firstMessage, deleted: deletedTime}, ...(Array.isArray(reportAction.message) ? reportAction.message.slice(1) : [])]}),
+        ...(!Array.isArray(reportAction.message) && {message: {deleted: deletedTime}}),
+    };
+}
+
 type DuplicateTransactionParams = {
     transactionID: string | undefined;
     originalSelectedTransaction: OnyxEntry<OnyxTypes.Transaction>;
@@ -209,95 +229,62 @@ function mergeDuplicates({
         };
     });
 
-    const duplicateTransactionTotals = params.transactionIDList.reduce((total, id) => {
-        const duplicateTransaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`];
-        if (!duplicateTransaction) {
-            return total;
-        }
-        return total + duplicateTransaction.amount;
-    }, 0);
-
     const expenseReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${params.reportID}`];
-    const expenseReportOptimisticData: OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT> = {
-        onyxMethod: Onyx.METHOD.MERGE,
-        key: `${ONYXKEYS.COLLECTION.REPORT}${params.reportID}`,
-        value: {
-            total: (expenseReport?.total ?? 0) - duplicateTransactionTotals,
-        },
-    };
-    const expenseReportFailureData: OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT> = {
-        onyxMethod: Onyx.METHOD.MERGE,
-        key: `${ONYXKEYS.COLLECTION.REPORT}${params.reportID}`,
-        value: {
-            total: expenseReport?.total,
-        },
-    };
-
-    const iouActionsToDelete = params.reportID ? getIOUActionForTransactions(params.transactionIDList, params.reportID) : [];
 
+    // Group each discarded duplicate's IOU action and amount by its own source report so the
+    // soft-delete MERGE and total decrement target the correct keys when duplicates span reports.
+    const sources = new Map<string, DiscardedSource>();
+    for (const id of params.transactionIDList) {
+        const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`];
+        if (!transaction?.reportID) {
+            continue;
+        }
+        const entry = sources.get(transaction.reportID) ?? {amount: 0, actions: []};
+        entry.amount += transaction.amount;
+        entry.actions.push(...getIOUActionForTransactions([id], transaction.reportID));
+        sources.set(transaction.reportID, entry);
+    }
     const deletedTime = DateUtils.getDBTime();
-    const expenseReportActionsOptimisticData: OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS> = {
-        onyxMethod: Onyx.METHOD.MERGE,
-        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${params.reportID}`,
-        value: iouActionsToDelete.reduce<Record<string, PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>((val, reportAction) => {
-            const firstMessage = Array.isArray(reportAction.message) ? reportAction.message.at(0) : null;
-            // eslint-disable-next-line no-param-reassign
-            val[reportAction.reportActionID] = {
-                originalMessage: {
-                    deleted: deletedTime,
-                },
-                ...(firstMessage && {
-                    message: [
-                        {
-                            ...firstMessage,
-                            deleted: deletedTime,
-                        },
-                        ...(Array.isArray(reportAction.message) ? reportAction.message.slice(1) : []),
-                    ],
-                }),
-                ...(!Array.isArray(reportAction.message) && {
-                    message: {
-                        deleted: deletedTime,
-                    },
-                }),
-            };
-            return val;
-        }, {}),
-    };
-    const expenseReportActionsFailureData: OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS> = {
-        onyxMethod: Onyx.METHOD.MERGE,
-        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${params.reportID}`,
-        value: iouActionsToDelete.reduce<Record<string, NullishDeep<PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>>((val, reportAction) => {
-            // eslint-disable-next-line no-param-reassign
-            val[reportAction.reportActionID] = {
-                originalMessage: {
-                    deleted: null,
-                },
-                message: reportAction.message,
-            };
-            return val;
-        }, {}),
-    };
-
+    const expenseReportOptimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT>> = [];
+    const expenseReportFailureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT>> = [];
+    const expenseReportActionsOptimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
+    const expenseReportActionsFailureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
     const cleanUpTransactionThreadReportsOptimisticData = [];
     const cleanUpTransactionThreadReportsSuccessData = [];
     const cleanUpTransactionThreadReportsFailureData = [];
-    let updatedReportPreviewAction;
-    for (const [index, iouAction] of Object.entries(iouActionsToDelete)) {
-        const transactionThreadID = iouAction.childReportID;
-        const shouldDeleteTransactionThread = !!transactionThreadID;
-        const cleanUpTransactionThreadReportOnyxDataForIouAction = getCleanUpTransactionThreadReportOnyxData({
-            transactionThreadID,
-            shouldDeleteTransactionThread,
-            reportAction: iouAction,
-            updatedReportPreviewAction,
-            shouldAddUpdatedReportPreviewActionToOnyxData: Number(index) === iouActionsToDelete.length - 1,
-            currentUserAccountID,
+    for (const [sourceReportID, {amount, actions}] of sources) {
+        const sourceReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`];
+        expenseReportOptimisticData.push({onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`, value: {total: (sourceReport?.total ?? 0) - amount}});
+        expenseReportFailureData.push({onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`, value: {total: sourceReport?.total}});
+        expenseReportActionsOptimisticData.push({
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`,
+            value: Object.fromEntries(actions.map((a) => [a.reportActionID, buildSoftDeleteReportActionUpdate(a, deletedTime)])),
         });
-        cleanUpTransactionThreadReportsOptimisticData.push(...cleanUpTransactionThreadReportOnyxDataForIouAction.optimisticData);
-        cleanUpTransactionThreadReportsSuccessData.push(...cleanUpTransactionThreadReportOnyxDataForIouAction.successData);
-        cleanUpTransactionThreadReportsFailureData.push(...cleanUpTransactionThreadReportOnyxDataForIouAction.failureData);
-        updatedReportPreviewAction = cleanUpTransactionThreadReportOnyxDataForIouAction.updatedReportPreviewAction;
+        expenseReportActionsFailureData.push({
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`,
+            value: Object.fromEntries(actions.map((a) => [a.reportActionID, buildSoftDeleteReportActionUpdate(a, null)])),
+        });
+
+        // Reset the report-preview accumulator per source so each source report's chat parent
+        // gets its own flushed update (and we don't leak one source's preview action into another).
+        let updatedReportPreviewAction;
+        for (const [index, iouAction] of actions.entries()) {
+            const transactionThreadID = iouAction.childReportID;
+            const cleanUp = getCleanUpTransactionThreadReportOnyxData({
+                transactionThreadID,
+                shouldDeleteTransactionThread: !!transactionThreadID,
+                reportAction: iouAction,
+                updatedReportPreviewAction,
+                shouldAddUpdatedReportPreviewActionToOnyxData: index === actions.length - 1,
+                currentUserAccountID,
+            });
+            cleanUpTransactionThreadReportsOptimisticData.push(...cleanUp.optimisticData);
+            cleanUpTransactionThreadReportsSuccessData.push(...cleanUp.successData);
+            cleanUpTransactionThreadReportsFailureData.push(...cleanUp.failureData);
+            updatedReportPreviewAction = cleanUp.updatedReportPreviewAction;
+        }
     }
     const optimisticReportAction = buildOptimisticResolvedDuplicatesReportAction();
 
@@ -331,8 +318,8 @@ function mergeDuplicates({
         optimisticTransactionData,
         ...optimisticTransactionDuplicatesData,
         ...optimisticTransactionViolations,
-        expenseReportOptimisticData,
-        expenseReportActionsOptimisticData,
+        ...expenseReportOptimisticData,
+        ...expenseReportActionsOptimisticData,
         optimisticReportActionData,
         ...cleanUpTransactionThreadReportsOptimisticData,
     );
@@ -341,8 +328,8 @@ function mergeDuplicates({
         failureTransactionData,
         ...failureTransactionDuplicatesData,
         ...failureTransactionViolations,
-        expenseReportFailureData,
-        expenseReportActionsFailureData,
+        ...expenseReportFailureData,
+        ...expenseReportActionsFailureData,
         failureReportActionData,
         ...cleanUpTransactionThreadReportsFailureData,
     );
diff --git a/src/libs/actions/IOU/MoneyRequest.ts b/src/libs/actions/IOU/MoneyRequest.ts
index 42f178ff3df9..4aa02dd5cc74 100644
--- a/src/libs/actions/IOU/MoneyRequest.ts
+++ b/src/libs/actions/IOU/MoneyRequest.ts
@@ -407,6 +407,10 @@ function startMoneyRequest(
     isFromFloatingActionButton?: boolean,
 ) {
     const sourceRoute = Navigation.getActiveRoute();
+    // Only the split flow exposes a Distance tab from here, so prefetch the default P2P mileage rate solely for splits to avoid an unnecessary read on other flows.
+    if (iouType === CONST.IOU.TYPE.SPLIT) {
+        getDefaultP2PMileageRate();
+    }
     startSpan(CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE, {
         name: '/money-request-create',
         op: CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE,
diff --git a/src/libs/actions/IOU/UpdateMoneyRequest.ts b/src/libs/actions/IOU/UpdateMoneyRequest.ts
index 162494c4e2f0..df874b2fe5b3 100644
--- a/src/libs/actions/IOU/UpdateMoneyRequest.ts
+++ b/src/libs/actions/IOU/UpdateMoneyRequest.ts
@@ -424,6 +424,16 @@ function updateMoneyRequestAttendees({
     API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_ATTENDEES, params, onyxData);
 }
 
+type UpdateMoneyRequestVendorParams = {
+    transactionID: string;
+    vendorID: string;
+    transaction?: OnyxEntry<OnyxTypes.Transaction>;
+    transactionThreadReport?: OnyxEntry<OnyxTypes.Report>;
+    parentReport?: OnyxEntry<OnyxTypes.Report>;
+    policy?: OnyxEntry<OnyxTypes.Policy>;
+    delegateAccountID: number | undefined;
+};
+
 /**
  * Update the QBO vendor matched to a non-reimbursable expense. The vendor lives on the transaction's
  * `comment.vendor` NVP as `{ externalID, isManuallySet }`. `isManuallySet` is hard-coded to `true` here
@@ -432,17 +442,35 @@ function updateMoneyRequestAttendees({
  *
  * Passing `vendorID=''` clears the vendor from the transaction.
  */
-function updateMoneyRequestVendor(transactionID: string, vendorID: string, transaction?: OnyxEntry<OnyxTypes.Transaction>) {
+function updateMoneyRequestVendor({transactionID, vendorID, transaction, transactionThreadReport, parentReport, policy, delegateAccountID}: UpdateMoneyRequestVendorParams) {
     // Fall back to the cached Onyx transaction when the caller doesn't pass one so failureData can
     // restore the actual previous vendor on API failure instead of clearing it.
     const resolvedTransaction = transaction ?? getAllTransactions()?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
     const previousVendor = resolvedTransaction?.comment?.vendor;
-    const optimisticReportActionID = rand64();
     const isClearing = !vendorID;
 
     const newVendorOptimisticValue = isClearing ? null : {externalID: vendorID, isManuallySet: true};
 
-    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS>> = [
+    // Build an optimistic MODIFIED_EXPENSE so the transaction thread shows "set vendor X" /
+    // "changed vendor from X to Y" / "removed the vendor" immediately. Auth's UpdateMoneyRequestVendor
+    // command writes the same {externalID, isManuallySet} shape to the action's originalMessage; the
+    // optimistic action mirrors that so the local render matches the eventual server payload.
+    const optimisticModifiedExpense =
+        resolvedTransaction && transactionThreadReport?.reportID
+            ? buildOptimisticModifiedExpenseReportAction(
+                  transactionThreadReport,
+                  resolvedTransaction,
+                  {vendor: newVendorOptimisticValue},
+                  isExpenseReport(parentReport),
+                  policy,
+                  delegateAccountID,
+              )
+            : null;
+    const optimisticReportActionID = optimisticModifiedExpense?.reportActionID ?? rand64();
+
+    const optimisticData: Array<
+        OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.REPORT>
+    > = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
@@ -450,25 +478,90 @@ function updateMoneyRequestVendor(transactionID: string, vendorID: string, trans
                 comment: {
                     vendor: newVendorOptimisticValue,
                 },
+                pendingFields: {
+                    vendor: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                },
             },
         },
     ];
 
-    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS>> = [];
+    const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
+            value: {
+                pendingFields: {
+                    vendor: null,
+                },
+            },
+        },
+    ];
 
     // Only roll back the vendor when we have a known prior snapshot. If the transaction isn't passed
     // in AND isn't cached in Onyx yet, we don't know what to restore — writing null here would silently
     // clear a vendor we don't know about. The next server sync will reconcile.
-    if (resolvedTransaction) {
-        failureData.push({
+    const failureData: Array<
+        OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.REPORT>
+    > = [
+        {
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
             value: {
-                comment: {
-                    vendor: previousVendor ?? null,
+                pendingFields: {
+                    vendor: null,
+                },
+                ...(resolvedTransaction && {
+                    comment: {
+                        vendor: previousVendor ?? null,
+                    },
+                }),
+            },
+        },
+    ];
+
+    if (optimisticModifiedExpense && transactionThreadReport?.reportID) {
+        optimisticData.push(
+            {
+                onyxMethod: Onyx.METHOD.MERGE,
+                key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}` as const,
+                value: {
+                    [optimisticModifiedExpense.reportActionID]: optimisticModifiedExpense as OnyxTypes.ReportAction,
+                },
+            },
+            {
+                onyxMethod: Onyx.METHOD.MERGE,
+                key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}` as const,
+                value: {
+                    lastReadTime: optimisticModifiedExpense.created,
                 },
             },
+        );
+        successData.push({
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}` as const,
+            value: {
+                [optimisticModifiedExpense.reportActionID]: {pendingAction: null},
+            },
         });
+        failureData.push(
+            {
+                onyxMethod: Onyx.METHOD.MERGE,
+                key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}` as const,
+                value: {
+                    [optimisticModifiedExpense.reportActionID]: {
+                        ...(optimisticModifiedExpense as OnyxTypes.ReportAction),
+                        errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage'),
+                    },
+                },
+            },
+            {
+                onyxMethod: Onyx.METHOD.MERGE,
+                key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}` as const,
+                value: {
+                    lastReadTime: transactionThreadReport.lastReadTime,
+                },
+            },
+        );
     }
 
     // Optimistically clear any existing inactive-vendor violation. This is the user-driven write
@@ -501,7 +594,7 @@ function updateMoneyRequestVendor(transactionID: string, vendorID: string, trans
             vendorID,
             isManuallySet: true,
         },
-        {optimisticData, failureData},
+        {optimisticData, successData, failureData},
     );
 }
 
@@ -1565,7 +1658,7 @@ function getUpdateMoneyRequestParams(params: GetUpdateMoneyRequestParamsType): U
                 getRecentAttendees(),
                 // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
                 (attendee) => attendee.email || attendee.displayName,
-            ).slice(0, CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW),
+            ).slice(0, CONST.IOU.MAX_RECENT_ATTENDEES),
         });
     }
 
diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts
index 1f8a888b7471..6009565cc770 100644
--- a/src/libs/actions/Link.ts
+++ b/src/libs/actions/Link.ts
@@ -8,6 +8,7 @@ import asyncOpenURL from '@libs/asyncOpenURL';
 import * as Environment from '@libs/Environment/Environment';
 import getIsNarrowLayout from '@libs/getIsNarrowLayout';
 import isPublicScreenRoute from '@libs/isPublicScreenRoute';
+import Log from '@libs/Log';
 import {isOnboardingFlowName} from '@libs/Navigation/helpers/isNavigatorName';
 import normalizePath from '@libs/Navigation/helpers/normalizePath';
 import shouldOpenOnAdminRoom from '@libs/Navigation/helpers/shouldOpenOnAdminRoom';
@@ -403,6 +404,25 @@ function getTravelDotLink(policyID: OnyxEntry<string>) {
     });
 }
 
+/**
+ * Fetches a short-lived auth token and appends it to the given setup link.
+ * Falls back to returning the original link if the token request fails.
+ */
+function getShortLivedAuthTokenURL(setupLink: string): Promise<string> {
+    // eslint-disable-next-line rulesdir/no-api-side-effects-method
+    return API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.OPEN_OLD_DOT_LINK, {}, {})
+        .then((response) => {
+            if (!response?.shortLivedAuthToken) {
+                return setupLink;
+            }
+            return Url.appendParam(setupLink, 'authToken', response.shortLivedAuthToken);
+        })
+        .catch((error) => {
+            Log.warn('[Link] Failed to fetch short-lived auth token', {error});
+            return setupLink;
+        });
+}
+
 export {
     openOldDotLink,
     openExternalLink,
@@ -414,4 +434,5 @@ export {
     getTravelDotLink,
     buildOldDotURL,
     openReportFromDeepLink,
+    getShortLivedAuthTokenURL,
 };
diff --git a/src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts b/src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts
index 161c7f72ecf8..63d8bfd1478c 100644
--- a/src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts
+++ b/src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts
@@ -1,6 +1,7 @@
 import type {ValueOf} from 'type-fest';
 import ONYXKEYS from '@src/ONYXKEYS';
 import cardFeedErrorsConfig from './configs/cardFeedErrors';
+import flaggedExpensesConfig from './configs/flaggedExpenses';
 import nonPersonalAndWorkspaceCardListConfig from './configs/nonPersonalAndWorkspaceCardList';
 import openAndSubmittedReportsByPolicyIDConfig from './configs/openAndSubmittedReportsByPolicyID';
 import outstandingReportsByPolicyIDConfig from './configs/outstandingReportsByPolicyID';
@@ -27,6 +28,7 @@ const ONYX_DERIVED_VALUES = {
     [ONYXKEYS.DERIVED.TODOS]: todosConfig,
     [ONYXKEYS.DERIVED.RAM_ONLY_SORTED_REPORT_ACTIONS]: sortedReportActionsConfig,
     [ONYXKEYS.DERIVED.OPEN_AND_SUBMITTED_REPORTS_BY_POLICY_ID]: openAndSubmittedReportsByPolicyIDConfig,
+    [ONYXKEYS.DERIVED.FLAGGED_EXPENSES]: flaggedExpensesConfig,
 } as const satisfies {
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
     [Key in ValueOf<typeof ONYXKEYS.DERIVED>]: OnyxDerivedValueConfig<Key, any>;
diff --git a/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts b/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
new file mode 100644
index 000000000000..d69e39d75686
--- /dev/null
+++ b/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
@@ -0,0 +1,94 @@
+import {getVisibleTransactionViolations} from '@libs/TransactionUtils';
+import createOnyxDerivedValueConfig from '@userActions/OnyxDerived/createOnyxDerivedValueConfig';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {FlaggedExpensesDerivedValue} from '@src/types/onyx';
+import type Report from '@src/types/onyx/Report';
+import type TransactionViolations from '@src/types/onyx/TransactionViolation';
+
+type FlaggedExpenseEntry = FlaggedExpensesDerivedValue['flaggedExpenses'][number];
+
+const EMPTY_VALUE: FlaggedExpensesDerivedValue = {flaggedExpenses: []};
+
+/**
+ * Returns true when this report is an OPEN/OPEN expense report owned by the current user.
+ *
+ * `currentUserAccountID` is required. Callers should pass `session?.accountID ?? CONST.DEFAULT_NUMBER_ID`
+ * so that the ownership check fails closed when the session is not yet populated (no real ownerAccountID is 0).
+ */
+function isCurrentUserOpenExpenseReport(report: Report | null | undefined, currentUserAccountID: number): boolean {
+    if (!report) {
+        return false;
+    }
+    if (report.type !== CONST.REPORT.TYPE.EXPENSE) {
+        return false;
+    }
+    if (report.ownerAccountID !== currentUserAccountID) {
+        return false;
+    }
+    return report.stateNum === CONST.REPORT.STATE_NUM.OPEN && report.statusNum === CONST.REPORT.STATUS_NUM.OPEN;
+}
+
+/** Returns true when at least one visible violation should surface in the "Review X expenses" row. */
+function hasReviewableViolation(violations: TransactionViolations | null | undefined): boolean {
+    if (!violations || violations.length === 0) {
+        return false;
+    }
+
+    return violations.some((violation) => {
+        if (!violation) {
+            return false;
+        }
+        if (violation.showInReview === false) {
+            return false;
+        }
+        if (violation.name === CONST.REPORT_VIOLATIONS.FIELD_REQUIRED) {
+            return false;
+        }
+        if (violation.type === CONST.VIOLATION_TYPES.NOTICE || violation.type === CONST.VIOLATION_TYPES.WARNING) {
+            return violation.showInReview === true;
+        }
+        return true;
+    });
+}
+
+export default createOnyxDerivedValueConfig({
+    key: ONYXKEYS.DERIVED.FLAGGED_EXPENSES,
+    dependencies: [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.COLLECTION.TRANSACTION, ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, ONYXKEYS.COLLECTION.POLICY, ONYXKEYS.SESSION],
+    compute: ([allReports, allTransactions, allTransactionViolations, allPolicies, session]) => {
+        if (!allReports || !allTransactions) {
+            return EMPTY_VALUE;
+        }
+
+        const currentUserAccountID = session?.accountID ?? CONST.DEFAULT_NUMBER_ID;
+        const currentUserEmail = session?.email ?? '';
+        const flaggedExpenses: FlaggedExpenseEntry[] = [];
+
+        for (const transactionKey of Object.keys(allTransactions)) {
+            const transaction = allTransactions[transactionKey];
+            if (!transaction?.transactionID || !transaction.reportID) {
+                continue;
+            }
+
+            const report = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`];
+            if (!isCurrentUserOpenExpenseReport(report, currentUserAccountID)) {
+                continue;
+            }
+
+            const violations = allTransactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`];
+            if (!violations || violations.length === 0) {
+                continue;
+            }
+
+            const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`];
+            const visibleViolations = getVisibleTransactionViolations(transaction, violations, currentUserEmail, currentUserAccountID, report, policy);
+            if (!hasReviewableViolation(visibleViolations)) {
+                continue;
+            }
+
+            flaggedExpenses.push({transactionID: transaction.transactionID, reportID: transaction.reportID});
+        }
+
+        return {flaggedExpenses};
+    },
+});
diff --git a/src/libs/actions/PersistedRequests.ts b/src/libs/actions/PersistedRequests.ts
index a689e238a2d7..847946eeb51e 100644
--- a/src/libs/actions/PersistedRequests.ts
+++ b/src/libs/actions/PersistedRequests.ts
@@ -260,10 +260,12 @@ function save<TKey extends OnyxKey>(requestToPersist: Request<TKey>): Promise<vo
                 queueLength: getLength(),
             });
         })
-        .catch(() => {
-            Log.info('[PersistedRequests] ERROR: Failed to persist request to disk', false, {
+        .catch((error) => {
+            // Disk-write failure risks losing this request on a crash — alert as a storage emergency.
+            Log.alert('[PersistedRequests] ERROR: Failed to persist request to disk', {
                 command: requestToPersist.command,
                 queueLength: getLength(),
+                error,
             });
         });
 }
@@ -334,9 +336,18 @@ function deleteRequestsByIndices(indices: number[]): Promise<void> {
     persistedRequests = persistedRequests.filter((_, index) => !indicesSet.has(index));
 
     // Update the persisted requests in storage or state as necessary
-    return trackOnyxWrite(Onyx.set(ONYXKEYS.PERSISTED_REQUESTS, persistedRequests)).then(() => {
-        Log.info(`Multiple (${indices.length}) requests removed from the queue. Queue length is ${persistedRequests.length}`);
-    });
+    return trackOnyxWrite(Onyx.set(ONYXKEYS.PERSISTED_REQUESTS, persistedRequests))
+        .then(() => {
+            Log.info(`Multiple (${indices.length}) requests removed from the queue. Queue length is ${persistedRequests.length}`);
+        })
+        .catch((error) => {
+            // Swallow so the conflict promise resolves (in-memory queue is the source of truth); alert as a storage emergency.
+            Log.alert('[PersistedRequests] ERROR: Failed to persist request deletion to disk', {
+                indicesCount: indices.length,
+                queueLength: getLength(),
+                error,
+            });
+        });
 }
 
 function update<TKey extends OnyxKey>(oldRequestIndex: number, newRequest: Request<TKey>): Promise<void> {
@@ -349,7 +360,14 @@ function update<TKey extends OnyxKey>(oldRequestIndex: number, newRequest: Reque
     if (requestIndex != null) {
         knownRequestIDs.add(requestIndex);
     }
-    return trackOnyxWrite(Onyx.set(ONYXKEYS.PERSISTED_REQUESTS, requests));
+    return trackOnyxWrite(Onyx.set(ONYXKEYS.PERSISTED_REQUESTS, requests)).catch((error) => {
+        // Swallow so the conflict promise resolves (in-memory queue is the source of truth); alert as a storage emergency.
+        Log.alert('[PersistedRequests] ERROR: Failed to persist updated request to disk', {
+            command: newRequest.command,
+            queueLength: getLength(),
+            error,
+        });
+    });
 }
 
 function shouldPersistOngoingRequest(request: AnyRequest | null): boolean {
diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts
index 24f238a45417..18d2cfe83ee9 100644
--- a/src/libs/actions/Policy/Member.ts
+++ b/src/libs/actions/Policy/Member.ts
@@ -45,6 +45,16 @@ type WorkspaceMembersRoleData = {
     role: ValueOf<typeof CONST.POLICY.ROLE>;
 };
 
+function hasPolicyAdminsRoomsAccess(role: string | undefined): boolean {
+    return (
+        role === CONST.POLICY.ROLE.ADMIN ||
+        role === CONST.POLICY.ROLE.CARD_ADMIN ||
+        role === CONST.POLICY.ROLE.PEOPLE_ADMIN ||
+        role === CONST.POLICY.ROLE.PAYMENTS_ADMIN ||
+        role === CONST.POLICY.ROLE.EDITOR
+    );
+}
+
 let allReportActions: OnyxCollection<ReportActions>;
 Onyx.connect({
     key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
@@ -349,7 +359,7 @@ function removeMembers(policy: OnyxEntry<Policy>, selectedMemberEmails: string[]
         selectedMemberEmails
             .filter((login) => {
                 const role = login ? policy?.employeeList?.[login]?.role : '';
-                return role === CONST.POLICY.ROLE.ADMIN || role === CONST.POLICY.ROLE.AUDITOR;
+                return hasPolicyAdminsRoomsAccess(role);
             })
             .map((login) => policyMemberEmailsToAccountIDs[login]),
     );
@@ -643,7 +653,7 @@ function buildUpdateWorkspaceMembersRoleOnyxData(policy: OnyxEntry<Policy>, sele
     if (adminRoom) {
         const failureDataParticipants: Record<number, Participant | null> = {...adminRoom.participants};
         const optimisticParticipants: Record<number, Participant | null> = {};
-        if (newRole === CONST.POLICY.ROLE.ADMIN || newRole === CONST.POLICY.ROLE.AUDITOR) {
+        if (hasPolicyAdminsRoomsAccess(newRole)) {
             for (const accountID of selectedMemberAccountIDs) {
                 if (adminRoom?.participants?.[accountID]) {
                     continue;
@@ -819,10 +829,7 @@ function buildAddMembersToWorkspaceOnyxData(
     const newPersonalDetailsOnyxData = PersonalDetailsUtils.getPersonalDetailsOnyxDataForOptimisticUsers(newLogins, newAccountIDs, formatPhoneNumber);
 
     const announceRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, policyID, accountIDs);
-    // Admins and auditors are always in the #admins room. Editors (Submit workspaces) join it too for
-    // visibility into configuration changes.
-    const shouldAddToAdminsRoom = effectiveRole === CONST.POLICY.ROLE.ADMIN || effectiveRole === CONST.POLICY.ROLE.AUDITOR || effectiveRole === CONST.POLICY.ROLE.EDITOR;
-    const adminRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policyID, shouldAddToAdminsRoom ? accountIDs : []);
+    const adminRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policyID, hasPolicyAdminsRoomsAccess(effectiveRole) ? accountIDs : []);
     const optimisticAnnounceChat = ReportUtils.buildOptimisticAnnounceChat(policyID, [...policyMemberAccountIDs, ...accountIDs], currentUser.accountID);
     const announceRoomChat = optimisticAnnounceChat.announceChatData;
 
diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts
index 887e7f1d1951..ad7bfe87022b 100644
--- a/src/libs/actions/Policy/Policy.ts
+++ b/src/libs/actions/Policy/Policy.ts
@@ -29,7 +29,6 @@ import type {
     EnablePolicyConnectionsParams,
     EnablePolicyExpensifyCardsParams,
     EnablePolicyHRParams,
-    EnablePolicyInvoiceFieldsParams,
     EnablePolicyInvoicingParams,
     EnablePolicyReportFieldsParams,
     EnablePolicyTaxesParams,
@@ -4902,19 +4901,16 @@ function enableCompanyCards(policyID: string, enabled: boolean, shouldGoBack = t
     }
 }
 
-function enablePolicyFields(policyID: string, enabled: boolean, command: typeof WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS | typeof WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS) {
-    const enableFieldKey =
-        command === WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS ? CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED : CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED;
-
+function enablePolicyReportFields(policyID: string, enabled: boolean) {
     const onyxData: OnyxData<typeof ONYXKEYS.COLLECTION.POLICY> = {
         optimisticData: [
             {
                 onyxMethod: Onyx.METHOD.MERGE,
                 key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
                 value: {
-                    [enableFieldKey]: enabled,
+                    areReportFieldsEnabled: enabled,
                     pendingFields: {
-                        [enableFieldKey]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                        areReportFieldsEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                     },
                 },
             },
@@ -4925,7 +4921,7 @@ function enablePolicyFields(policyID: string, enabled: boolean, command: typeof
                 key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
                 value: {
                     pendingFields: {
-                        [enableFieldKey]: null,
+                        areReportFieldsEnabled: null,
                     },
                 },
             },
@@ -4935,26 +4931,18 @@ function enablePolicyFields(policyID: string, enabled: boolean, command: typeof
                 onyxMethod: Onyx.METHOD.MERGE,
                 key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
                 value: {
-                    [enableFieldKey]: !enabled,
+                    areReportFieldsEnabled: !enabled,
                     pendingFields: {
-                        [enableFieldKey]: null,
+                        areReportFieldsEnabled: null,
                     },
                 },
             },
         ],
     };
 
-    const parameters: EnablePolicyReportFieldsParams | EnablePolicyInvoiceFieldsParams = {policyID, enabled};
-
-    API.writeWithNoDuplicatesEnableFeatureConflicts(command, parameters, onyxData);
-}
-
-function enablePolicyReportFields(policyID: string, enabled: boolean) {
-    enablePolicyFields(policyID, enabled, WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS);
-}
+    const parameters: EnablePolicyReportFieldsParams = {policyID, enabled};
 
-function enablePolicyInvoiceFields(policyID: string, enabled: boolean) {
-    enablePolicyFields(policyID, enabled, WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS);
+    API.writeWithNoDuplicatesEnableFeatureConflicts(WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS, parameters, onyxData);
 }
 
 function enablePolicyTaxes(policyID: string, enabled: true, currentTaxRates: TaxRatesWithDefault | undefined): void;
@@ -7544,7 +7532,6 @@ export {
     enablePolicyHR,
     enablePolicyReceiptPartners,
     enablePolicyReportFields,
-    enablePolicyInvoiceFields,
     enablePolicyTaxes,
     enablePolicyWorkflows,
     enablePolicyTimeTracking,
diff --git a/src/libs/actions/Policy/ReportField.ts b/src/libs/actions/Policy/ReportField.ts
index 27d182329f0c..b802d6a4a1d2 100644
--- a/src/libs/actions/Policy/ReportField.ts
+++ b/src/libs/actions/Policy/ReportField.ts
@@ -3,18 +3,12 @@ import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
 import Onyx from 'react-native-onyx';
 import * as API from '@libs/API';
 import type {
-    CreateWorkspaceInvoiceFieldListValueParams,
-    CreateWorkspaceInvoiceFieldParams,
     CreateWorkspaceReportFieldListValueParams,
     CreateWorkspaceReportFieldParams,
-    DeletePolicyInvoiceField,
     DeletePolicyReportField,
-    EnableWorkspaceInvoiceFieldListValueParams,
     EnableWorkspaceReportFieldListValueParams,
     OpenPolicyReportFieldsPageParams,
-    RemoveWorkspaceInvoiceFieldListValueParams,
     RemoveWorkspaceReportFieldListValueParams,
-    UpdateWorkspaceInvoiceFieldInitialValueParams,
     UpdateWorkspaceReportFieldInitialValueParams,
 } from '@libs/API/parameters';
 import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
@@ -57,8 +51,7 @@ type DeleteReportFieldsListValueParams = {
 type CreateReportFieldParams = Pick<WorkspaceReportFieldForm, 'name' | 'type' | 'initialValue'> & {
     listValues: string[];
     disabledListValues: boolean[];
-    policyReportIDs: Array<string | undefined> | undefined;
-    isInvoiceField?: boolean;
+    policyExpenseReportIDs: Array<string | undefined> | undefined;
     policy: OnyxEntry<Policy>;
 };
 
@@ -105,19 +98,6 @@ function openPolicyReportFieldsPage(policyID: string) {
     API.read(READ_COMMANDS.OPEN_POLICY_REPORT_FIELDS_PAGE, params);
 }
 
-function openPolicyInvoicesPage(policyID: string) {
-    if (!policyID) {
-        Log.warn('openPolicyInvoicesPage invalid params', {policyID});
-        return;
-    }
-
-    const params: OpenPolicyReportFieldsPageParams = {
-        policyID,
-    };
-
-    API.read(READ_COMMANDS.OPEN_POLICY_INVOICES_PAGE, params);
-}
-
 /**
  * Sets the initial form values for the workspace report fields form.
  */
@@ -185,19 +165,14 @@ function deleteReportFieldsListValue({valueIndexes, listValues, disabledListValu
 /**
  * Creates a new report field.
  */
-function createReportField({name, type, initialValue, listValues, disabledListValues, policyReportIDs, isInvoiceField = false, policy}: CreateReportFieldParams) {
+function createReportField({name, type, initialValue, listValues, disabledListValues, policyExpenseReportIDs, policy}: CreateReportFieldParams) {
     if (!policy) {
         Log.warn('Policy data is not present');
         return;
     }
 
     const previousFieldList = policy?.fieldList ?? {};
-    const target = isInvoiceField ? CONST.REPORT_FIELD_TARGETS.INVOICE : CONST.REPORT_FIELD_TARGETS.EXPENSE;
-    const defaultFieldID = WorkspaceReportFieldUtils.generateFieldID(name);
-    const defaultFieldKey = ReportUtils.getReportFieldKey(defaultFieldID);
-    const defaultField = previousFieldList[defaultFieldKey];
-    const shouldUseTargetSpecificFieldID = isInvoiceField || (defaultField && !WorkspaceReportFieldUtils.isReportFieldTargetValid(defaultField, target));
-    const fieldID = shouldUseTargetSpecificFieldID ? WorkspaceReportFieldUtils.generateFieldID(name, target) : defaultFieldID;
+    const fieldID = WorkspaceReportFieldUtils.generateFieldID(name);
     const fieldKey = ReportUtils.getReportFieldKey(fieldID);
 
     // User selected type Text but entered a formula Initial value, treat it as a Formula type for optimistic UI
@@ -207,7 +182,7 @@ function createReportField({name, type, initialValue, listValues, disabledListVa
     const optimisticReportFieldDataForPolicy: Omit<OnyxValueWithOfflineFeedback<PolicyReportField>, 'value'> = {
         name,
         type: optimisticType,
-        target,
+        target: 'expense',
         defaultValue: initialValue,
         values: listValues,
         disabledOptions: disabledListValues,
@@ -230,7 +205,7 @@ function createReportField({name, type, initialValue, listValues, disabledListVa
                 errorFields: null,
             },
         },
-        ...(policyReportIDs ?? []).map(
+        ...(policyExpenseReportIDs ?? []).map(
             (reportID): OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT> => ({
                 key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
                 onyxMethod: Onyx.METHOD.MERGE,
@@ -256,7 +231,7 @@ function createReportField({name, type, initialValue, listValues, disabledListVa
                 },
             },
         },
-        ...(policyReportIDs ?? []).map(
+        ...(policyExpenseReportIDs ?? []).map(
             (reportID): OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT> => ({
                 key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
                 onyxMethod: Onyx.METHOD.MERGE,
@@ -286,18 +261,12 @@ function createReportField({name, type, initialValue, listValues, disabledListVa
         failureData,
     };
 
-    const parameters: CreateWorkspaceReportFieldParams | CreateWorkspaceInvoiceFieldParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([optimisticReportFieldDataForPolicy]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([optimisticReportFieldDataForPolicy]),
-          };
-
-    const createCommand = isInvoiceField ? WRITE_COMMANDS.CREATE_WORKSPACE_INVOICE_FIELD : WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD;
-    API.write(createCommand, parameters, onyxData);
+    const parameters: CreateWorkspaceReportFieldParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([optimisticReportFieldDataForPolicy]),
+    };
+
+    API.write(WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD, parameters, onyxData);
 }
 
 function deleteReportFields({policy, reportFieldsToUpdate}: DeleteReportFieldsParams) {
@@ -307,24 +276,19 @@ function deleteReportFields({policy, reportFieldsToUpdate}: DeleteReportFieldsPa
     }
 
     const allReportFields = policy?.fieldList ?? {};
-    const resolvedReportFieldKeys = reportFieldsToUpdate.filter((reportFieldKey) => !!allReportFields[reportFieldKey]);
-    if (resolvedReportFieldKeys.length === 0) {
-        Log.warn('No valid report fields to delete', {reportFieldsToUpdate});
-        return;
-    }
 
-    const updatedReportFields = Object.fromEntries(Object.entries(allReportFields).filter(([key]) => !resolvedReportFieldKeys.includes(key)));
-    const optimisticReportFields = resolvedReportFieldKeys.reduce<Record<string, Partial<OnyxValueWithOfflineFeedback<PolicyReportField>>>>((acc, reportFieldKey) => {
+    const updatedReportFields = Object.fromEntries(Object.entries(allReportFields).filter(([key]) => !reportFieldsToUpdate.includes(key)));
+    const optimisticReportFields = reportFieldsToUpdate.reduce<Record<string, Partial<OnyxValueWithOfflineFeedback<PolicyReportField>>>>((acc, reportFieldKey) => {
         acc[reportFieldKey] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE};
         return acc;
     }, {});
 
-    const successReportFields = resolvedReportFieldKeys.reduce<Record<string, null>>((acc, reportFieldKey) => {
+    const successReportFields = reportFieldsToUpdate.reduce<Record<string, null>>((acc, reportFieldKey) => {
         acc[reportFieldKey] = null;
         return acc;
     }, {});
 
-    const failureReportFields = resolvedReportFieldKeys.reduce<Record<string, Partial<OnyxValueWithOfflineFeedback<PolicyReportField>>>>((acc, reportFieldKey) => {
+    const failureReportFields = reportFieldsToUpdate.reduce<Record<string, Partial<OnyxValueWithOfflineFeedback<PolicyReportField>>>>((acc, reportFieldKey) => {
         acc[reportFieldKey] = {pendingAction: null};
         return acc;
     }, {});
@@ -363,24 +327,12 @@ function deleteReportFields({policy, reportFieldsToUpdate}: DeleteReportFieldsPa
         ],
     };
 
-    const fieldsToDelete = resolvedReportFieldKeys.map((reportFieldKey) => allReportFields[reportFieldKey]).filter((reportField): reportField is PolicyReportField => !!reportField);
-    const isInvoiceField = fieldsToDelete.length > 0 && fieldsToDelete.every((reportField) => reportField.target === CONST.REPORT_FIELD_TARGETS.INVOICE);
-    const updatedReportFieldsValues = Object.values(updatedReportFields);
-    const remainingInvoiceFields = updatedReportFieldsValues.filter((reportField) => reportField.target === CONST.REPORT_FIELD_TARGETS.INVOICE);
-    const remainingExpenseFields = updatedReportFieldsValues.filter((reportField) => !reportField.target || reportField.target === CONST.REPORT_FIELD_TARGETS.EXPENSE);
-    const invoiceFieldsPayload = remainingInvoiceFields;
-    const parameters: DeletePolicyReportField | DeletePolicyInvoiceField = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify(invoiceFieldsPayload),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify(remainingExpenseFields),
-          };
-    const deleteCommand = isInvoiceField ? WRITE_COMMANDS.DELETE_POLICY_INVOICE_FIELD : WRITE_COMMANDS.DELETE_POLICY_REPORT_FIELD;
-
-    API.write(deleteCommand, parameters, onyxData);
+    const parameters: DeletePolicyReportField = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify(Object.values(updatedReportFields)),
+    };
+
+    API.write(WRITE_COMMANDS.DELETE_POLICY_REPORT_FIELD, parameters, onyxData);
 }
 
 /**
@@ -448,19 +400,12 @@ function updateReportFieldInitialValue({policy, reportFieldID, newInitialValue}:
             },
         ],
     };
-    const isInvoiceField = updatedReportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const parameters: UpdateWorkspaceReportFieldInitialValueParams | UpdateWorkspaceInvoiceFieldInitialValueParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([updatedReportField]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([updatedReportField]),
-          };
-    const updateCommand = isInvoiceField ? WRITE_COMMANDS.UPDATE_WORKSPACE_INVOICE_FIELD_INITIAL_VALUE : WRITE_COMMANDS.UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE;
-
-    API.write(updateCommand, parameters, onyxData);
+    const parameters: UpdateWorkspaceReportFieldInitialValueParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([updatedReportField]),
+    };
+
+    API.write(WRITE_COMMANDS.UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE, parameters, onyxData);
 }
 
 function updateReportFieldListValueEnabled({policy, reportFieldID, valueIndexes, enabled}: UpdateReportFieldListValueEnabledParams) {
@@ -499,19 +444,12 @@ function updateReportFieldListValueEnabled({policy, reportFieldID, valueIndexes,
         ],
     };
 
-    const isInvoiceField = reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const parameters: EnableWorkspaceReportFieldListValueParams | EnableWorkspaceInvoiceFieldListValueParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([updatedReportField]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([updatedReportField]),
-          };
-    const enableCommand = isInvoiceField ? WRITE_COMMANDS.ENABLE_WORKSPACE_INVOICE_FIELD_LIST_VALUE : WRITE_COMMANDS.ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE;
-
-    API.write(enableCommand, parameters, onyxData);
+    const parameters: EnableWorkspaceReportFieldListValueParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([updatedReportField]),
+    };
+
+    API.write(WRITE_COMMANDS.ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE, parameters, onyxData);
 }
 
 /**
@@ -546,19 +484,12 @@ function addReportFieldListValue({policy, reportFieldID, valueName}: AddReportFi
         ],
     };
 
-    const isInvoiceField = reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const parameters: CreateWorkspaceReportFieldListValueParams | CreateWorkspaceInvoiceFieldListValueParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([updatedReportField]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([updatedReportField]),
-          };
-    const createCommand = isInvoiceField ? WRITE_COMMANDS.CREATE_WORKSPACE_INVOICE_FIELD_LIST_VALUE : WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE;
-
-    API.write(createCommand, parameters, onyxData);
+    const parameters: CreateWorkspaceReportFieldListValueParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([updatedReportField]),
+    };
+
+    API.write(WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE, parameters, onyxData);
 }
 
 /**
@@ -601,19 +532,12 @@ function removeReportFieldListValue({policy, reportFieldID, valueIndexes}: Remov
         ],
     };
 
-    const isInvoiceField = reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const parameters: RemoveWorkspaceReportFieldListValueParams | RemoveWorkspaceInvoiceFieldListValueParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([updatedReportField]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([updatedReportField]),
-          };
-    const removeCommand = isInvoiceField ? WRITE_COMMANDS.REMOVE_WORKSPACE_INVOICE_FIELD_LIST_VALUE : WRITE_COMMANDS.REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE;
-
-    API.write(removeCommand, parameters, onyxData);
+    const parameters: RemoveWorkspaceReportFieldListValueParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([updatedReportField]),
+    };
+
+    API.write(WRITE_COMMANDS.REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE, parameters, onyxData);
 }
 
 export type {CreateReportFieldParams};
@@ -629,7 +553,6 @@ export {
     updateReportFieldInitialValue,
     updateReportFieldListValueEnabled,
     openPolicyReportFieldsPage,
-    openPolicyInvoicesPage,
     addReportFieldListValue,
     removeReportFieldListValue,
 };
diff --git a/src/libs/actions/Report/DeleteReport.ts b/src/libs/actions/Report/DeleteReport.ts
new file mode 100644
index 000000000000..22b334189607
--- /dev/null
+++ b/src/libs/actions/Report/DeleteReport.ts
@@ -0,0 +1,66 @@
+import Onyx from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import Log from '@libs/Log';
+import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
+import type CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report, ReportAction, ReportActions} from '@src/types/onyx';
+
+// We use connectWithoutView because deleteReport doesn't affect the UI rendering
+// and this avoids unnecessary re-rendering because we recursively delete the report and its children
+// which requires us to subscribe to the whole report and report actions collection.
+let allReports: OnyxCollection<Report>;
+Onyx.connectWithoutView({
+    key: ONYXKEYS.COLLECTION.REPORT,
+    waitForCollectionCallback: true,
+    callback: (value) => (allReports = value),
+});
+
+let allReportActions: OnyxCollection<ReportActions>;
+Onyx.connectWithoutView({
+    key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
+    waitForCollectionCallback: true,
+    callback: (value) => (allReportActions = value),
+});
+
+/** Deletes a report, along with its reportActions, any linked reports, and any linked IOU report. */
+function deleteReport(reportID: string | undefined, shouldDeleteChildReports = false) {
+    if (!reportID) {
+        Log.warn('[Report] deleteReport called with no reportID');
+        return;
+    }
+    const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+    const onyxData: Record<string, null> = {
+        [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]: null,
+        [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]: null,
+    };
+
+    // Delete linked transactions
+    const reportActionsForReport = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`];
+
+    const transactionIDs = Object.values(reportActionsForReport ?? {})
+        .filter((reportAction): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> => isMoneyRequestAction(reportAction))
+        .map((reportAction) => getOriginalMessage(reportAction)?.IOUTransactionID);
+
+    for (const transactionID of [...new Set(transactionIDs)]) {
+        onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] = null;
+    }
+
+    Onyx.multiSet(onyxData);
+
+    if (shouldDeleteChildReports) {
+        for (const reportAction of Object.values(reportActionsForReport ?? {})) {
+            if (!reportAction.childReportID) {
+                continue;
+            }
+            deleteReport(reportAction.childReportID, shouldDeleteChildReports);
+        }
+    }
+
+    // Delete linked IOU report
+    if (report?.iouReportID) {
+        deleteReport(report.iouReportID, shouldDeleteChildReports);
+    }
+}
+
+export default deleteReport;
diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts
index c5bfa6d6c1e6..c8d51a595aaa 100644
--- a/src/libs/actions/Report/index.ts
+++ b/src/libs/actions/Report/index.ts
@@ -236,6 +236,7 @@ import type {SearchResultDataType} from '@src/types/onyx/SearchResults';
 import type {FileObject} from '@src/types/utils/Attachment';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
 import type {Dimensions} from '@src/types/utils/Layout';
+import deleteReport from './DeleteReport';
 
 type SubscriberCallback = (isFromCurrentUser: boolean, reportAction: ReportAction | undefined) => void;
 
@@ -4360,46 +4361,6 @@ function addPolicyReport(policyReport: OptimisticChatReport) {
     API.write(WRITE_COMMANDS.ADD_WORKSPACE_ROOM, parameters, {optimisticData, successData, failureData});
 }
 
-/** Deletes a report, along with its reportActions, any linked reports, and any linked IOU report. */
-function deleteReport(reportID: string | undefined, shouldDeleteChildReports = false) {
-    if (!reportID) {
-        Log.warn('[Report] deleteReport called with no reportID');
-        return;
-    }
-    const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
-    const onyxData: Record<string, null> = {
-        [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]: null,
-        [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]: null,
-    };
-
-    // Delete linked transactions
-    const reportActionsForReport = allReportActions?.[reportID];
-
-    const transactionIDs = Object.values(reportActionsForReport ?? {})
-        .filter((reportAction): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> => ReportActionsUtils.isMoneyRequestAction(reportAction))
-        .map((reportAction) => ReportActionsUtils.getOriginalMessage(reportAction)?.IOUTransactionID);
-
-    for (const transactionID of [...new Set(transactionIDs)]) {
-        onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] = null;
-    }
-
-    Onyx.multiSet(onyxData);
-
-    if (shouldDeleteChildReports) {
-        for (const reportAction of Object.values(reportActionsForReport ?? {})) {
-            if (!reportAction.childReportID) {
-                continue;
-            }
-            deleteReport(reportAction.childReportID, shouldDeleteChildReports);
-        }
-    }
-
-    // Delete linked IOU report
-    if (report?.iouReportID) {
-        deleteReport(report.iouReportID, shouldDeleteChildReports);
-    }
-}
-
 /**
  * @param reportID The reportID of the policy report (workspace room)
  */
@@ -7836,7 +7797,6 @@ export {
     completeOnboarding,
     extractRHPVariantFromResponse,
     createNewReport,
-    deleteReport,
     clearAllReportActionDrafts,
     deleteReportComment,
     deleteReportField,
diff --git a/src/libs/actions/RequestConflictUtils.ts b/src/libs/actions/RequestConflictUtils.ts
index f5b052d99230..b554ccdf42ec 100644
--- a/src/libs/actions/RequestConflictUtils.ts
+++ b/src/libs/actions/RequestConflictUtils.ts
@@ -32,7 +32,6 @@ const enablePolicyFeatureCommand = [
     WRITE_COMMANDS.ENABLE_POLICY_TAGS,
     WRITE_COMMANDS.ENABLE_POLICY_TAXES,
     WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS,
-    WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS,
     WRITE_COMMANDS.ENABLE_POLICY_WORKFLOWS,
     WRITE_COMMANDS.SET_POLICY_RULES_ENABLED,
     WRITE_COMMANDS.ENABLE_POLICY_INVOICING,
diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts
index f5c969ebd0cd..f7441b0a8bab 100644
--- a/src/libs/actions/Search.ts
+++ b/src/libs/actions/Search.ts
@@ -31,7 +31,7 @@ import type {SearchFullscreenNavigatorParamList} from '@libs/Navigation/types';
 import enhanceParameters from '@libs/Network/enhanceParameters';
 import {rand64} from '@libs/NumberUtils';
 import {getActivePaymentType} from '@libs/PaymentUtils';
-import {getSubmitReportManagerAccountID, getValidConnectedIntegration, isDelayedSubmissionEnabled} from '@libs/PolicyUtils';
+import {getSubmitReportManagerAccountID, getValidConnectedIntegration, isDelayedSubmissionEnabled, isSubmitAndClose} from '@libs/PolicyUtils';
 import type {OptimisticExportIntegrationAction} from '@libs/ReportUtils';
 import {
     buildOptimisticExportIntegrationAction,
@@ -840,12 +840,23 @@ function search({
 
 function submitMoneyRequestOnSearch(hash: number, reportList: Report[], policy: Policy[], currentSearchKey?: SearchKey) {
     const firstReport = (reportList.at(0) ?? {}) as Report;
-    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE>> = [
+    const isSubmitAndClosePolicy = isSubmitAndClose(policy.at(0));
+    const optimisticData: Array<
+        OnyxUpdate<typeof ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE | typeof ONYXKEYS.COLLECTION.REPORT>
+    > = [
         {
             onyxMethod: Onyx.METHOD.MERGE_COLLECTION,
             key: ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE,
             value: Object.fromEntries(reportList.map((report) => [`${ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE}${report?.reportID}`, {isActionLoading: true}])),
         },
+        ...reportList.map((report) => ({
+            onyxMethod: Onyx.METHOD.MERGE as const,
+            key: `${ONYXKEYS.COLLECTION.REPORT}${report?.reportID}`,
+            value: {
+                stateNum: isSubmitAndClosePolicy ? CONST.REPORT.STATE_NUM.APPROVED : CONST.REPORT.STATE_NUM.SUBMITTED,
+                statusNum: isSubmitAndClosePolicy ? CONST.REPORT.STATUS_NUM.CLOSED : CONST.REPORT.STATUS_NUM.SUBMITTED,
+            },
+        })),
     ];
 
     const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE | typeof ONYXKEYS.COLLECTION.SNAPSHOT>> = [
diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts
index 5edcbe62a444..6307a8181666 100644
--- a/src/libs/actions/Transaction.ts
+++ b/src/libs/actions/Transaction.ts
@@ -20,7 +20,7 @@ import {translateLocal} from '@libs/Localize';
 import {buildNextStepNew, buildOptimisticNextStep} from '@libs/NextStepUtils';
 import * as NumberUtils from '@libs/NumberUtils';
 import {rand64, roundToTwoDecimalPlaces} from '@libs/NumberUtils';
-import {getDistanceRateCustomUnitRate, hasDependentTags, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {getDistanceRateCustomUnitRate, hasDependentTags, isGroupPolicy} from '@libs/PolicyUtils';
 import {
     getAllReportActions,
     getIOUActionForReportID,
@@ -1162,7 +1162,7 @@ function changeTransactionsReport({
         // Auto-select a valid default distance rate when moving to a workspace where the current rate is invalid,
         // and recalculate derived fields (amount, merchant, currency) to match the new rate.
         let transactionForViolations = transaction;
-        if (isPaidGroupPolicy(policy) && policy?.id && isDistanceRequest(transaction)) {
+        if (isGroupPolicy(policy) && policy?.id && isDistanceRequest(transaction)) {
             const currentRateID = transaction.comment?.customUnit?.customUnitRateID;
             const currentRate = currentRateID ? getDistanceRateCustomUnitRate(policy, currentRateID) : undefined;
             if (!currentRateID || !currentRate || currentRate.enabled === false) {
@@ -1262,7 +1262,7 @@ function changeTransactionsReport({
 
         let transactionReimbursable = transaction.reimbursable;
         // 2. Calculate transaction violations if moving transaction to a workspace
-        if (isPaidGroupPolicy(policy) && policy?.id) {
+        if (isGroupPolicy(policy) && policy?.id) {
             const violationData = ViolationsUtils.getViolationsOnyxData({
                 updatedTransaction: transactionForViolations,
                 transactionViolations: currentTransactionViolations[transaction.transactionID] ?? [],
@@ -1659,7 +1659,7 @@ function changeTransactionsReport({
 
     const reportTransactions = getReportTransactions(reportID);
     for (const transaction of reportTransactions) {
-        if (!isPaidGroupPolicy(policy) || !policy?.id) {
+        if (!isGroupPolicy(policy) || !policy?.id) {
             continue;
         }
         const violationData = ViolationsUtils.getViolationsOnyxData({
diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts
index e517c243121b..44b3476e5899 100644
--- a/src/libs/actions/User.ts
+++ b/src/libs/actions/User.ts
@@ -1028,6 +1028,10 @@ function updatePreferredSkinTone(skinTone: number) {
     API.write(WRITE_COMMANDS.UPDATE_PREFERRED_EMOJI_SKIN_TONE, parameters, {optimisticData});
 }
 
+function setInboxTab(tab: ValueOf<typeof CONST.INBOX_TAB>) {
+    Onyx.merge(ONYXKEYS.NVP_INBOX_TAB, tab);
+}
+
 /**
  * Sync user chat priority mode with Onyx and Server
  * @param mode
@@ -1934,12 +1938,13 @@ export {
     isBlockedFromConcierge,
     subscribeToUserEvents,
     updatePreferredSkinTone,
+    setInboxTab,
+    updateChatPriorityMode,
     setShouldUseStagingServer,
     togglePlatformMute,
     joinScreenShare,
     clearScreenShareRequest,
     generateStatementPDF,
-    updateChatPriorityMode,
     setContactMethodAsDefault,
     updateTheme,
     setHighContrastIntent,
diff --git a/src/libs/actions/Workflow.ts b/src/libs/actions/Workflow.ts
index 3e3d7c598bdb..1bf80b830df2 100644
--- a/src/libs/actions/Workflow.ts
+++ b/src/libs/actions/Workflow.ts
@@ -421,52 +421,6 @@ function validateApprovalWorkflow(approvalWorkflow: ApprovalWorkflowOnyx): appro
     return isEmptyObject(errors);
 }
 
-/**
- * Build the key used to identify a deferred agent workflow save. We pin it to the policy +
- * the workflow's primary approver email so two different workflows in the same policy don't
- * stomp on each other, and so the WorkflowsPage watcher can look up the right entry when it
- * comes time to fire the real save.
- */
-function buildDeferredAgentWorkflowSaveKey(policyID: string, firstApproverEmail: string) {
-    return `${policyID}:${firstApproverEmail}`;
-}
-
-/**
- * Persist a workflow save the admin issued while a freshly-created agent was still pending.
- * The Edit Approvers modal dismisses immediately on save, the WorkspaceWorkflowsPage shows
- * the workflow with the agent rendered faded, and the watcher fires the actual save once
- * the agent's real email lands.
- */
-function queueDeferredAgentWorkflowSave(
-    policyID: string,
-    firstApproverEmail: string,
-    approvalWorkflow: ApprovalWorkflowOnyx,
-    initialApprovalWorkflow: ApprovalWorkflow,
-    pendingAgentAccountID: number,
-    pendingAgentPrompt: string,
-) {
-    const key = buildDeferredAgentWorkflowSaveKey(policyID, firstApproverEmail);
-    Onyx.merge(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES, {
-        [key]: {
-            policyID,
-            firstApproverEmail,
-            approvalWorkflow,
-            initialApprovalWorkflow,
-            pendingAgentAccountID,
-            pendingAgentPrompt,
-        },
-    });
-}
-
-/**
- * Remove a deferred save entry. Called by the watcher after it has fired the actual save
- * (or when the user manually navigates back to the editor and saves with the real email).
- */
-function clearDeferredAgentWorkflowSave(policyID: string, firstApproverEmail: string) {
-    const key = buildDeferredAgentWorkflowSaveKey(policyID, firstApproverEmail);
-    Onyx.merge(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES, {[key]: null});
-}
-
 export {
     createApprovalWorkflow,
     updateApprovalWorkflow,
@@ -480,7 +434,4 @@ export {
     clearApprovalWorkflow,
     validateApprovalWorkflow,
     setApprovalWorkflowIsInitialFlow,
-    buildDeferredAgentWorkflowSaveKey,
-    queueDeferredAgentWorkflowSave,
-    clearDeferredAgentWorkflowSave,
 };
diff --git a/src/libs/actions/connections/FinancialForce.ts b/src/libs/actions/connections/FinancialForce.ts
index 135274759cc7..14230aa74776 100644
--- a/src/libs/actions/connections/FinancialForce.ts
+++ b/src/libs/actions/connections/FinancialForce.ts
@@ -11,6 +11,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
 import type {FinancialForceConnectionConfig} from '@src/types/onyx/Policy';
 
 type FinancialForceFFAExportStatus = typeof CONST.CERTINIA_EXPORT_STATUS.APPROVED | typeof CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS;
+type FinancialForceReportExportStatus = typeof CONST.CERTINIA_EXPORT_STATUS.APPROVED | typeof CONST.CERTINIA_EXPORT_STATUS.SUBMITTED;
 
 function prepareOnyxDataForFinancialForceCodingUpdate<K extends keyof FinancialForceConnectionConfig['coding']>(
     policyID: string,
@@ -168,6 +169,84 @@ function prepareOnyxDataForFinancialForceExportUpdate<K extends keyof FinancialF
     return {optimisticData, failureData, successData};
 }
 
+function prepareOnyxDataForFinancialForceAdvancedUpdate<K extends keyof FinancialForceConnectionConfig['advanced']>(
+    policyID: string,
+    settingName: K,
+    settingValue: FinancialForceConnectionConfig['advanced'][K],
+    oldSettingValue?: FinancialForceConnectionConfig['advanced'][K],
+) {
+    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            advanced: {
+                                [settingName]: settingValue,
+                            },
+                            pendingFields: {
+                                [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                            },
+                            errorFields: {
+                                [settingName]: null,
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            advanced: {
+                                [settingName]: oldSettingValue ?? null,
+                            },
+                            pendingFields: {
+                                [settingName]: null,
+                            },
+                            errorFields: {
+                                [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            pendingFields: {
+                                [settingName]: null,
+                            },
+                            errorFields: {
+                                [settingName]: null,
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    return {optimisticData, failureData, successData};
+}
+
 function getFinancialForceSetupLink(policyID: string, isSandbox = false) {
     const commandURL = getCommandURL({
         command: READ_COMMANDS.CONNECT_POLICY_TO_FINANCIAL_FORCE,
@@ -422,10 +501,123 @@ function updateFinancialForceSyncReimbursedReports(policyID: string, enabled: bo
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_REIMBURSED_REPORTS, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
+function updateFinancialForceParentTagMapping(
+    policyID: string,
+    parentTagMapping: ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING>,
+    previousValue: ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING> | null,
+) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceCodingUpdate(
+        policyID,
+        CONST.CERTINIA_CONFIG.PARENT_TAG_MAPPING,
+        parentTagMapping,
+        previousValue ?? undefined,
+    );
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_PARENT_TAG_MAPPING, {policyID, parentTagMapping}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceSyncMilestones(policyID: string, enabled: boolean, previousValue?: boolean) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceCodingUpdate(policyID, CONST.CERTINIA_CONFIG.SYNC_MILESTONES, enabled, previousValue);
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES, {policyID, enabled}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceReportExportStatus(policyID: string, status: FinancialForceReportExportStatus, previousStatus: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS> | null) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceExportUpdate(
+        policyID,
+        CONST.CERTINIA_CONFIG.REPORT_EXPORT_STATUS,
+        status,
+        previousStatus ?? undefined,
+    );
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS, {policyID, exportStatus: status}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceTaxNonBillable(policyID: string, enabled: boolean, previousValue?: boolean) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.TAX_NON_BILLABLE, enabled, previousValue);
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE, {policyID, enabled}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceExportForeignCurrency(policyID: string, enabled: boolean, previousValue?: boolean) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.EXPORT_FOREIGN_CURRENCY, enabled, previousValue);
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY, {policyID, enabled}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceCompany(policyID: string, companyID: string, previousCompanyID: string | null) {
+    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            credentials: {
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: companyID,
+                            },
+                            pendingFields: {
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                            },
+                            errorFields: {
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: null,
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            credentials: {
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: previousCompanyID ?? null,
+                            },
+                            pendingFields: {
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: null,
+                            },
+                            errorFields: {
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            pendingFields: {
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: null,
+                            },
+                            errorFields: {
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: null,
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_COMPANY, {policyID, companyID}, {optimisticData, failureData, successData});
+}
+
 export {
     clearFinancialForceErrorField,
     connectPolicyToFinancialForce,
     updateFinancialForceAutoSync,
+    updateFinancialForceCompany,
     updateFinancialForceDefaultVendor,
     updateFinancialForceDimension1Mapping,
     updateFinancialForceDimension2Mapping,
@@ -433,7 +625,12 @@ export {
     updateFinancialForceDimension4Mapping,
     updateFinancialForceExportDate,
     updateFinancialForceExporter,
+    updateFinancialForceExportForeignCurrency,
     updateFinancialForceExportStatus,
+    updateFinancialForceParentTagMapping,
+    updateFinancialForceReportExportStatus,
+    updateFinancialForceSyncMilestones,
     updateFinancialForceSyncReimbursedReports,
     updateFinancialForceSyncTax,
+    updateFinancialForceTaxNonBillable,
 };
diff --git a/src/libs/actions/replaceOptimisticReportWithActualReport.ts b/src/libs/actions/replaceOptimisticReportWithActualReport.ts
index 150f65a6827d..0bb103ce149f 100644
--- a/src/libs/actions/replaceOptimisticReportWithActualReport.ts
+++ b/src/libs/actions/replaceOptimisticReportWithActualReport.ts
@@ -140,7 +140,18 @@ function replaceOptimisticReportWithActualReport(report: Report, draftReportComm
         const backTo = (currentRouteInfo?.params as {backTo?: Route})?.backTo;
         const screenName = currentRouteInfo?.name;
 
-        const isOptimisticReportFocused = activeRoute.includes(`/r/${reportID}`);
+        // Besides the central-pane report route (/r/:reportID), the optimistic report can also be focused
+        // in the RHP transaction-thread carousel (search/view/:reportID) used by the "Review X expenses"
+        // flow. Matched via route name + reportID param (not a path substring) since the carousel's nested
+        // backTo can contain other report IDs. Without this, the report is cleared out from under the user
+        // and ReportNavigateAwayHandler treats it as removed, dismissing the RHP and navigating to the parent.
+        const isOptimisticReportFocusedInSearchRHP =
+            screenName === SCREENS.RIGHT_MODAL.SEARCH_REPORT &&
+            !!currentRouteInfo?.params &&
+            typeof currentRouteInfo.params === 'object' &&
+            'reportID' in currentRouteInfo.params &&
+            currentRouteInfo.params.reportID === reportID;
+        const isOptimisticReportFocused = activeRoute.includes(`/r/${reportID}`) || isOptimisticReportFocusedInSearchRHP;
 
         // Fix specific case: https://github.com/Expensify/App/pull/77657#issuecomment-3678696730.
         // When user is editing a money request report (/e/:reportID route) and has
diff --git a/src/libs/shouldUseDefaultExpensePolicy.ts b/src/libs/shouldUseDefaultExpensePolicy.ts
index 68e454f0260c..504705e3718d 100644
--- a/src/libs/shouldUseDefaultExpensePolicy.ts
+++ b/src/libs/shouldUseDefaultExpensePolicy.ts
@@ -2,7 +2,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import type {IOUType} from '@src/CONST';
 import CONST from '@src/CONST';
 import type {BillingGraceEndPeriod, OnyxInputOrEntry, Policy} from '@src/types/onyx';
-import {isPaidGroupPolicy} from './PolicyUtils';
+import {isGroupPolicy} from './PolicyUtils';
 import {shouldRestrictUserBillableActions} from './SubscriptionUtils';
 
 function shouldUseDefaultExpensePolicy(
@@ -15,7 +15,7 @@ function shouldUseDefaultExpensePolicy(
 ) {
     return (
         iouType === CONST.IOU.TYPE.CREATE &&
-        isPaidGroupPolicy(defaultExpensePolicy) &&
+        isGroupPolicy(defaultExpensePolicy) &&
         defaultExpensePolicy?.isPolicyExpenseChatEnabled &&
         !shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserAccountID)
     );
diff --git a/src/pages/DynamicEditReportFieldPage.tsx b/src/pages/DynamicEditReportFieldPage.tsx
index d0aeb95db2ce..55d3522dd929 100644
--- a/src/pages/DynamicEditReportFieldPage.tsx
+++ b/src/pages/DynamicEditReportFieldPage.tsx
@@ -23,12 +23,11 @@ import type {EditRequestNavigatorParamList} from '@libs/Navigation/types';
 import {isPolicyFieldListEmpty} from '@libs/PolicyUtils';
 import {getReportName as getReportNameFromReportNameUtils} from '@libs/ReportNameUtils';
 import {
-    getReportFieldFromReportNameValuePairs,
     getReportFieldKey,
     getTitleFieldWithFallback,
     hasViolations as hasViolationsReportUtils,
+    isGroupPolicyExpenseReport,
     isInvoiceReport,
-    isPaidGroupPolicyExpenseReport,
     isReportFieldDisabled,
     isReportFieldDisabledForUser,
     isReportFieldOfTypeTitle,
@@ -49,7 +48,6 @@ function DynamicEditReportFieldPage({route}: DynamicEditReportFieldPageProps) {
     const fieldKey = getReportFieldKey(route.params.fieldID);
     const backPath = useDynamicBackPath(DYNAMIC_ROUTES.EDIT_REPORT_FIELD.path);
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
-    const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`);
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);
     const reportAttributesSelector = useCallback((attributes: OnyxEntry<ReportAttributesDerivedValue>) => reportByIDsSelector([reportID])(attributes), [reportID]);
     const [reportAttributesByReportID] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {
@@ -58,10 +56,8 @@ function DynamicEditReportFieldPage({route}: DynamicEditReportFieldPageProps) {
     const [recentlyUsedReportFields] = useOnyx(ONYXKEYS.RECENTLY_USED_REPORT_FIELDS);
 
     const isTitleField = route.params.fieldID === CONST.REPORT_FIELD_TITLE_FIELD_ID;
-    const reportFieldFromNVP = getReportFieldFromReportNameValuePairs(reportNameValuePairs, fieldKey) ?? getReportFieldFromReportNameValuePairs(reportNameValuePairs, route.params.fieldID);
-    let reportField =
-        reportFieldFromNVP ?? report?.fieldList?.[fieldKey] ?? report?.fieldList?.[route.params.fieldID] ?? policy?.fieldList?.[fieldKey] ?? policy?.fieldList?.[route.params.fieldID];
-    let policyField = policy?.fieldList?.[fieldKey] ?? policy?.fieldList?.[route.params.fieldID] ?? reportField;
+    let reportField = report?.fieldList?.[fieldKey] ?? policy?.fieldList?.[fieldKey];
+    let policyField = policy?.fieldList?.[fieldKey] ?? reportField;
 
     // If the title field is missing, use fallback so that it can still be edited and matches the OldDot behavior.
     if (isTitleField && !reportField && !policyField) {
@@ -81,8 +77,7 @@ function DynamicEditReportFieldPage({route}: DynamicEditReportFieldPageProps) {
     const {showConfirmModal} = useConfirmModal();
     const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
     const isReportFieldTitle = isReportFieldOfTypeTitle(reportField);
-    const isReportFieldsFeatureEnabled = report?.type === CONST.REPORT.TYPE.INVOICE ? policy?.areInvoiceFieldsEnabled : policy?.areReportFieldsEnabled;
-    const reportFieldsEnabled = ((isPaidGroupPolicyExpenseReport(report) || isInvoiceReport(report)) && !!isReportFieldsFeatureEnabled) || isReportFieldTitle;
+    const reportFieldsEnabled = ((isGroupPolicyExpenseReport(report) || isInvoiceReport(report)) && !!policy?.areReportFieldsEnabled) || isReportFieldTitle;
     const hasOtherViolations =
         report?.fieldList && Object.entries(report.fieldList).some(([key, field]) => key !== fieldKey && field.value === '' && !isReportFieldDisabled(report, reportField, policy));
 
diff --git a/src/pages/EnablePayments/Wallet/AddBankAccount/AddBankAccount.tsx b/src/pages/EnablePayments/Wallet/AddBankAccount/AddBankAccount.tsx
index 1902739a7e43..bbdbfae6b36a 100644
--- a/src/pages/EnablePayments/Wallet/AddBankAccount/AddBankAccount.tsx
+++ b/src/pages/EnablePayments/Wallet/AddBankAccount/AddBankAccount.tsx
@@ -99,6 +99,7 @@ function AddBankAccount() {
                             <InteractiveStepSubHeader
                                 startStepIndex={0}
                                 stepNames={CONST.WALLET.STEP_NAMES}
+                                currentStepAccessibilityDescription={translate('bankAccount.addBankAccount')}
                             />
                         </View>
                         <SubStep
diff --git a/src/pages/EnablePayments/Wallet/VerifyIdentity/VerifyIdentity.tsx b/src/pages/EnablePayments/Wallet/VerifyIdentity/VerifyIdentity.tsx
index 6540e2305d2f..1fc05e15a9fe 100644
--- a/src/pages/EnablePayments/Wallet/VerifyIdentity/VerifyIdentity.tsx
+++ b/src/pages/EnablePayments/Wallet/VerifyIdentity/VerifyIdentity.tsx
@@ -63,6 +63,7 @@ function VerifyIdentity() {
                 <InteractiveStepSubHeader
                     startStepIndex={2}
                     stepNames={CONST.WALLET.STEP_NAMES}
+                    currentStepAccessibilityDescription={translate('onfidoStep.verifyIdentity')}
                 />
             </View>
             <FullPageOfflineBlockingView>
diff --git a/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx b/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx
index badd7d37fc67..5125a556cbfb 100644
--- a/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx
+++ b/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx
@@ -160,6 +160,7 @@ function MissingPersonalDetailsContent({privatePersonalDetails, draftValues, hea
                 <InteractiveStepSubPageHeader
                     stepNames={stepIndexList}
                     currentStepIndex={pageIndex}
+                    currentStepAccessibilityDescription={headerTitle ?? translate('workspace.expensifyCard.addShippingDetails')}
                     onStepSelected={moveTo}
                 />
             </View>
diff --git a/src/pages/MultifactorAuthentication/PromptPage.tsx b/src/pages/MultifactorAuthentication/PromptPage.tsx
index 329e27432e81..35588b068fb3 100644
--- a/src/pages/MultifactorAuthentication/PromptPage.tsx
+++ b/src/pages/MultifactorAuthentication/PromptPage.tsx
@@ -5,7 +5,7 @@ import Button from '@components/Button';
 import FixedFooter from '@components/FixedFooter';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import LoadingIndicator from '@components/LoadingIndicator';
-import {useMultifactorAuthentication, useMultifactorAuthenticationActions, usePromptContent} from '@components/MultifactorAuthentication/Context';
+import {useMultifactorAuthentication, useMultifactorAuthenticationActions, useMultifactorAuthenticationState, usePromptContent} from '@components/MultifactorAuthentication/Context';
 import MultifactorAuthenticationPromptContent from '@components/MultifactorAuthentication/PromptContent';
 import ScreenWrapper from '@components/ScreenWrapper';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
@@ -24,6 +24,7 @@ function MultifactorAuthenticationPromptPage({route}: MultifactorAuthenticationP
     const styles = useThemeStyles();
     const {requestCancel} = useMultifactorAuthentication();
     const {dispatch} = useMultifactorAuthenticationActions();
+    const {isCancelConfirmVisible} = useMultifactorAuthenticationState();
     const {accountID} = useCurrentUserPersonalDetails();
 
     const {illustration, title, subtitle, shouldDisplayConfirmButton} = usePromptContent(route.params.promptType);
@@ -33,8 +34,7 @@ function MultifactorAuthenticationPromptPage({route}: MultifactorAuthenticationP
         dispatch({type: 'SET_SOFT_PROMPT_APPROVED', payload: true});
     };
 
-    // Outside-clicks and Escape route through the central cancel handler; return
-    // false to keep the focus trap intact while the confirm modal opens.
+    // Escape opens the cancel confirmation; returning false keeps the trap active.
     const interceptFocusTrapEscape = () => {
         requestCancel();
         return false;
@@ -44,9 +44,10 @@ function MultifactorAuthenticationPromptPage({route}: MultifactorAuthenticationP
         <ScreenWrapper
             testID={MultifactorAuthenticationPromptPage.displayName}
             focusTrapSettings={{
+                // Turn the trap off while the cancel confirmation modal is up so it can't swallow
+                // the modal's clicks, and back on when it closes. See https://github.com/Expensify/App/issues/93193
+                active: isCancelConfirmVisible ? false : undefined,
                 focusTrapOptions: {
-                    allowOutsideClick: interceptFocusTrapEscape,
-                    clickOutsideDeactivates: interceptFocusTrapEscape,
                     escapeDeactivates: interceptFocusTrapEscape,
                 },
             }}
diff --git a/src/pages/MultifactorAuthentication/ValidateCodePage.tsx b/src/pages/MultifactorAuthentication/ValidateCodePage.tsx
index 55b02952184c..5b4cffba0195 100644
--- a/src/pages/MultifactorAuthentication/ValidateCodePage.tsx
+++ b/src/pages/MultifactorAuthentication/ValidateCodePage.tsx
@@ -50,7 +50,7 @@ function MultifactorAuthenticationValidateCodePage() {
     const {requestCancel} = useMultifactorAuthentication();
 
     const {dispatch} = useMultifactorAuthenticationActions();
-    const {continuableError} = useMultifactorAuthenticationState();
+    const {continuableError, isCancelConfirmVisible} = useMultifactorAuthenticationState();
 
     // Refs
     const inputRef = useRef<MagicCodeInputHandle>(null);
@@ -198,8 +198,7 @@ function MultifactorAuthenticationValidateCodePage() {
         dispatch({type: 'SET_VALIDATE_CODE', payload: inputCode});
     };
 
-    // Outside-clicks and Escape route through the central cancel handler; return
-    // false to keep the focus trap intact while the confirm modal opens.
+    // Escape opens the cancel confirmation; returning false keeps the trap active.
     const interceptFocusTrapEscape = () => {
         requestCancel();
         return false;
@@ -209,9 +208,10 @@ function MultifactorAuthenticationValidateCodePage() {
         <ScreenWrapper
             testID={MultifactorAuthenticationValidateCodePage.displayName}
             focusTrapSettings={{
+                // Turn the trap off while the cancel confirmation modal is up so it can't swallow
+                // the modal's clicks, and back on when it closes. See https://github.com/Expensify/App/issues/93193
+                active: isCancelConfirmVisible ? false : undefined,
                 focusTrapOptions: {
-                    allowOutsideClick: interceptFocusTrapEscape,
-                    clickOutsideDeactivates: interceptFocusTrapEscape,
                     escapeDeactivates: interceptFocusTrapEscape,
                 },
             }}
diff --git a/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx b/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx
index 2dbd5c0cf89e..07bb165bde75 100644
--- a/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx
+++ b/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx
@@ -32,7 +32,6 @@ import {setOnboardingAdminsChatReportID, setOnboardingPolicyID} from '@libs/acti
 import Log from '@libs/Log';
 import {navigateAfterOnboardingWithMicrotaskQueue} from '@libs/navigateAfterOnboarding';
 import Navigation from '@libs/Navigation/Navigation';
-// eslint-disable-next-line no-restricted-imports
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import {isPaidGroupPolicy, isPolicyAdmin} from '@libs/PolicyUtils';
 import CONST from '@src/CONST';
diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx b/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx
index 59924eca1837..f93e797ba791 100644
--- a/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx
+++ b/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx
@@ -28,7 +28,7 @@ import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {ReimbursementAccountNavigatorParamList} from '@libs/Navigation/types';
 import {goBackFromInvalidPolicy, isPendingDeletePolicy, isPolicyAdmin} from '@libs/PolicyUtils';
-import {hasInProgressUSDVBBA, hasInProgressVBBA} from '@libs/ReimbursementAccountUtils';
+import {hasInProgressUSDVBBA, hasInProgressVBBA, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
 import shouldReopenOnfido from '@libs/shouldReopenOnfido';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {isFullScreenName} from '@navigation/helpers/isNavigatorName';
@@ -97,6 +97,7 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen
     const {translate} = useLocalize();
     const {isOffline} = useNetwork();
     const requestorStepRef = useRef<View>(null);
+    const hasRequestedNewBankAccountRef = useRef(false);
     const prevReimbursementAccount = usePrevious(reimbursementAccount);
     const prevIsOffline = usePrevious(isOffline);
     const achData = reimbursementAccount?.achData;
@@ -230,7 +231,9 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen
     }
 
     useEffect(() => {
-        if ((isPreviousPolicy && !!reimbursementAccount) || isLoadingOnyxValue(reimbursementAccountMetadata)) {
+        // Consume this route intent only once so the response changing isPreviousPolicy does not trigger another request.
+        const shouldOpenNewBankAccount = route.params.stepToOpen === REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW && !hasRequestedNewBankAccountRef.current;
+        if ((!shouldOpenNewBankAccount && isPreviousPolicy && !!reimbursementAccount) || isLoadingOnyxValue(reimbursementAccountMetadata)) {
             return;
         }
 
@@ -245,6 +248,9 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen
             setBankAccountSubStep(null);
             setPlaidEvent(null);
         }
+        if (shouldOpenNewBankAccount) {
+            hasRequestedNewBankAccountRef.current = true;
+        }
         fetchData();
         // eslint-disable-next-line react-hooks/exhaustive-deps
     }, [isPreviousPolicy]); // Only re-run this effect when isPreviousPolicy changes, which happens once when the component first loads
diff --git a/src/pages/Search/SearchPageNarrow/StaticSearchTypeMenu.tsx b/src/pages/Search/SearchPageNarrow/StaticSearchTypeMenu.tsx
index d348ea95d2fe..0d4af448002d 100644
--- a/src/pages/Search/SearchPageNarrow/StaticSearchTypeMenu.tsx
+++ b/src/pages/Search/SearchPageNarrow/StaticSearchTypeMenu.tsx
@@ -15,11 +15,11 @@ import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import staticPolicyInfoSelector from './staticPolicyInfoSelector';
 
-function getActiveKey(similarSearchHash: number, hasPaidGroupPolicy: boolean, searches: Record<string, SearchTypeMenuItem>): string {
+function getActiveKey(similarSearchHash: number, hasGroupPolicy: boolean, searches: Record<string, SearchTypeMenuItem>): string {
     const reportsSearch = searches[CONST.SEARCH.SEARCH_KEYS.REPORTS];
     const expensesSearch = searches[CONST.SEARCH.SEARCH_KEYS.EXPENSES];
     const submitSearch = searches[CONST.SEARCH.SEARCH_KEYS.SUBMIT];
-    const candidates = [reportsSearch, expensesSearch, ...(hasPaidGroupPolicy ? [submitSearch] : [])];
+    const candidates = [reportsSearch, expensesSearch, ...(hasGroupPolicy ? [submitSearch] : [])];
     return candidates.find((entry) => similarSearchHash === entry.similarSearchHash)?.key ?? reportsSearch.key;
 }
 
@@ -27,7 +27,7 @@ function StaticSearchTypeMenu({queryJSON}: {queryJSON: SearchQueryJSON}) {
     const {translate} = useLocalize();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['Receipt', 'Document', 'Pencil']);
     const [policyInfo] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: staticPolicyInfoSelector});
-    const hasPaidGroupPolicy = policyInfo?.hasPaidGroupPolicy ?? false;
+    const hasGroupPolicy = policyInfo?.hasGroupPolicy ?? false;
     const session = useSession();
     const accountID = session?.accountID ?? CONST.DEFAULT_NUMBER_ID;
 
@@ -41,11 +41,11 @@ function StaticSearchTypeMenu({queryJSON}: {queryJSON: SearchQueryJSON}) {
         {key: expensesSearch.key, icon: expensifyIcons.Receipt, title: translate(expensesSearch.translationPath)},
     ];
 
-    if (hasPaidGroupPolicy) {
+    if (hasGroupPolicy) {
         tabs.push({key: submitSearch.key, icon: expensifyIcons.Pencil, title: translate(submitSearch.translationPath)});
     }
 
-    const activeKey = getActiveKey(queryJSON.similarSearchHash, hasPaidGroupPolicy, suggestedSearches);
+    const activeKey = getActiveKey(queryJSON.similarSearchHash, hasGroupPolicy, suggestedSearches);
 
     return (
         <SearchTypeMenuNarrowContent
diff --git a/src/pages/Search/SearchPageNarrow/staticPolicyInfoSelector.ts b/src/pages/Search/SearchPageNarrow/staticPolicyInfoSelector.ts
index c3b4d1a627b0..0d100d10b519 100644
--- a/src/pages/Search/SearchPageNarrow/staticPolicyInfoSelector.ts
+++ b/src/pages/Search/SearchPageNarrow/staticPolicyInfoSelector.ts
@@ -1,16 +1,17 @@
 import type {OnyxCollection} from 'react-native-onyx';
-import {shouldShowPolicy} from '@libs/PolicyUtils';
-import CONST from '@src/CONST';
+import {isGroupPolicy, shouldShowPolicy} from '@libs/PolicyUtils';
 import type {Policy} from '@src/types/onyx';
 
 type StaticPolicyInfo = {
     hasMultipleWorkspaces: boolean;
-    hasPaidGroupPolicy: boolean;
+    // True for any group workspace (Collect, Control, or Submit). Gates the "Submit" search tab,
+    // which Submit workspaces also need — matches `getSuggestedSearchesVisibility` in SearchUIUtils.
+    hasGroupPolicy: boolean;
 };
 
 function staticPolicyInfoSelector(policies: OnyxCollection<Policy>): StaticPolicyInfo {
     let workspaceCount = 0;
-    let hasPaidGroupPolicy = false;
+    let hasGroupPolicy = false;
 
     for (const policy of Object.values(policies ?? {})) {
         if (!policy) {
@@ -19,15 +20,15 @@ function staticPolicyInfoSelector(policies: OnyxCollection<Policy>): StaticPolic
         if (!policy.isJoinRequestPending && shouldShowPolicy(policy, false, undefined)) {
             workspaceCount++;
         }
-        if (policy.type === CONST.POLICY.TYPE.TEAM || policy.type === CONST.POLICY.TYPE.CORPORATE) {
-            hasPaidGroupPolicy = true;
+        if (isGroupPolicy(policy)) {
+            hasGroupPolicy = true;
         }
-        if (workspaceCount > 1 && hasPaidGroupPolicy) {
+        if (workspaceCount > 1 && hasGroupPolicy) {
             break;
         }
     }
 
-    return {hasMultipleWorkspaces: workspaceCount > 1, hasPaidGroupPolicy};
+    return {hasMultipleWorkspaces: workspaceCount > 1, hasGroupPolicy};
 }
 
 export default staticPolicyInfoSelector;
diff --git a/src/pages/Search/SearchTransactionsChangeReport.tsx b/src/pages/Search/SearchTransactionsChangeReport.tsx
index 6a2a8f0eb190..de20d2bc120a 100644
--- a/src/pages/Search/SearchTransactionsChangeReport.tsx
+++ b/src/pages/Search/SearchTransactionsChangeReport.tsx
@@ -140,15 +140,13 @@ function SearchTransactionsChangeReport() {
             const firstTransactionID = selectedTransactionsKeys.at(0);
             if (firstTransactionID) {
                 Navigation.navigate(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                            action: CONST.IOU.ACTION.EDIT,
-                            iouType: CONST.IOU.TYPE.SUBMIT,
-                            transactionID: firstTransactionID,
-                            reportID: selectedTransactions[firstTransactionID]?.reportID ?? CONST.REPORT.UNREPORTED_REPORT_ID,
-                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                        }),
-                    ),
+                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                        action: CONST.IOU.ACTION.EDIT,
+                        iouType: CONST.IOU.TYPE.SUBMIT,
+                        transactionID: firstTransactionID,
+                        reportID: selectedTransactions[firstTransactionID]?.reportID ?? CONST.REPORT.UNREPORTED_REPORT_ID,
+                        upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                    }),
                 );
             }
             return;
@@ -160,15 +158,13 @@ function SearchTransactionsChangeReport() {
         }
         if (!policyForMovingExpensesID) {
             Navigation.navigate(
-                createDynamicRoute(
-                    DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                        action: CONST.IOU.ACTION.CREATE,
-                        iouType: CONST.IOU.TYPE.CREATE,
-                        transactionID: generateReportID(),
-                        reportID: generateReportID(),
-                        upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                    }),
-                ),
+                ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                    action: CONST.IOU.ACTION.CREATE,
+                    iouType: CONST.IOU.TYPE.CREATE,
+                    transactionID: generateReportID(),
+                    reportID: generateReportID(),
+                    upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                }),
             );
             return;
         }
diff --git a/src/pages/SetDefaultWorkspacePage.tsx b/src/pages/SetDefaultWorkspacePage.tsx
index 73ac8f2d92ff..ce6e55c43d86 100644
--- a/src/pages/SetDefaultWorkspacePage.tsx
+++ b/src/pages/SetDefaultWorkspacePage.tsx
@@ -16,7 +16,7 @@ import useWorkspaceList from '@hooks/useWorkspaceList';
 import Log from '@libs/Log';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import {isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {isGroupPolicy} from '@libs/PolicyUtils';
 import type {MoneyRequestNavigatorParamList} from '@navigation/types';
 import {setNameValuePair} from '@userActions/User';
 import CONST from '@src/CONST';
@@ -68,7 +68,7 @@ function SetDefaultWorkspacePage({route}: SetDefaultWorkspacePageProps) {
         selectedPolicyIDs: undefined,
         searchTerm: debouncedSearchTerm,
         localeCompare,
-        additionalFilter: (newPolicy) => isPaidGroupPolicy(newPolicy),
+        additionalFilter: (newPolicy) => isGroupPolicy(newPolicy),
     });
 
     const textInputOptions = useMemo(
diff --git a/src/pages/Share/SubmitDetailsPage.tsx b/src/pages/Share/SubmitDetailsPage.tsx
index fbc4246e9c4f..2d0bf0f73840 100644
--- a/src/pages/Share/SubmitDetailsPage.tsx
+++ b/src/pages/Share/SubmitDetailsPage.tsx
@@ -45,7 +45,7 @@ import Navigation from '@libs/Navigation/Navigation';
 import type {ShareNavigatorParamList} from '@libs/Navigation/types';
 import {rand64} from '@libs/NumberUtils';
 import {getParticipantsOption, getReportOption} from '@libs/OptionsListUtils';
-import {hasOnlyPersonalPolicies as hasOnlyPersonalPoliciesUtil, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {hasOnlyPersonalPolicies as hasOnlyPersonalPoliciesUtil, isGroupPolicy} from '@libs/PolicyUtils';
 import {shouldValidateFile} from '@libs/ReceiptUtils';
 import {isMoneyRequestReport, isSelfDM} from '@libs/ReportUtils';
 import {getDefaultTaxCode, getIsFromGlobalCreate, getTaxValue} from '@libs/TransactionUtils';
@@ -195,7 +195,7 @@ function SubmitDetailsPage({
     }, [defaultBillable]);
 
     useEffect(() => {
-        const defaultReimbursable = (isPolicyExpenseChat && isPaidGroupPolicy(policy)) || isCreatingTrackExpense ? (policy?.defaultReimbursable ?? true) : true;
+        const defaultReimbursable = (isPolicyExpenseChat && isGroupPolicy(policy)) || isCreatingTrackExpense ? (policy?.defaultReimbursable ?? true) : true;
         setMoneyRequestReimbursable(CONST.IOU.OPTIMISTIC_TRANSACTION_ID, defaultReimbursable);
     }, [policy, isPolicyExpenseChat, isCreatingTrackExpense]);
 
diff --git a/src/pages/TransactionDuplicate/Confirmation.tsx b/src/pages/TransactionDuplicate/Confirmation.tsx
index ce26ba0a978f..28456f38eca8 100644
--- a/src/pages/TransactionDuplicate/Confirmation.tsx
+++ b/src/pages/TransactionDuplicate/Confirmation.tsx
@@ -21,6 +21,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import useTransactionsByID from '@hooks/useTransactionsByID';
 import useTransactionThreadReportIDs from '@hooks/useTransactionThreadReportIDs';
 import {mergeDuplicates, resolveDuplicates} from '@libs/actions/IOU/Duplicate';
+import {setDeleteTransactionNavigateBackUrl} from '@libs/actions/Report';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
@@ -33,6 +34,7 @@ import * as ReportUtils from '@src/libs/ReportUtils';
 import {generateReportID} from '@src/libs/ReportUtils';
 import * as TransactionUtils from '@src/libs/TransactionUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Transaction} from '@src/types/onyx';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
@@ -102,12 +104,22 @@ function Confirmation() {
     const handleMergeDuplicates = useCallback(() => {
         const transactionThreadReportID = childReportID ?? generateReportID();
         const mergeParams = !childReportID ? {...transactionsMergeParams, transactionThreadReportID} : transactionsMergeParams;
+        // Server deletes the discarded transaction's now-empty expense report on merge and
+        // pushes back a "Report not found" payload for it. Hint the guard and redirect to
+        // the kept transaction's report so the user doesn't land on the discarded one.
+        const keptReportRoute = ROUTES.REPORT_WITH_ID.getRoute(mergeParams.reportID);
+        setDeleteTransactionNavigateBackUrl(keptReportRoute);
         mergeDuplicates({...mergeParams, ...taxData, currentUserAccountID, currentUserLogin: currentUserLogin ?? ''});
         if (isSuperWideRHPDisplayed) {
             Navigation.dismissToSuperWideRHP();
             return;
         }
-        Navigation.dismissModal();
+        const topmostReportID = Navigation.getTopmostReportId?.();
+        if (topmostReportID === mergeParams.reportID) {
+            Navigation.dismissModal();
+        } else {
+            Navigation.goBack(keptReportRoute);
+        }
     }, [childReportID, transactionsMergeParams, taxData, currentUserAccountID, currentUserLogin, isSuperWideRHPDisplayed]);
 
     const handleResolveDuplicates = useCallback(() => {
diff --git a/src/pages/TransactionDuplicate/ReviewFields.tsx b/src/pages/TransactionDuplicate/ReviewFields.tsx
index f59f3cc02be5..74fa180f042f 100644
--- a/src/pages/TransactionDuplicate/ReviewFields.tsx
+++ b/src/pages/TransactionDuplicate/ReviewFields.tsx
@@ -70,6 +70,7 @@ function ReviewFields<K extends keyof ReviewDuplicates>({stepNames, label, optio
                     <InteractiveStepSubHeader
                         stepNames={stepNames}
                         startStepIndex={index}
+                        currentStepAccessibilityDescription={label}
                     />
                 </View>
             )}
diff --git a/src/pages/WorkspaceCurrencySelectionPage.tsx b/src/pages/WorkspaceCurrencySelectionPage.tsx
index d28c51ff8ad8..78d4e0859b2c 100644
--- a/src/pages/WorkspaceCurrencySelectionPage.tsx
+++ b/src/pages/WorkspaceCurrencySelectionPage.tsx
@@ -10,6 +10,7 @@ import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {setWorkspaceConfirmationCurrency} from '@libs/actions/Policy/Policy';
 import Navigation from '@libs/Navigation/Navigation';
+import {skipNextFocusRestore} from '@libs/NavigationFocusReturn';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Route} from '@src/ROUTES';
@@ -39,6 +40,10 @@ function WorkspaceCurrencySelectionPage({route}: WorkspaceCurrencySelectionPageP
     const onSelect = useCallback(
         (option: CurrencyListItem) => {
             setWorkspaceConfirmationCurrency(option.currencyCode);
+            // After selecting, don't restore focus to the currency menu item on the confirmation page —
+            // a focused button suppresses the form's submit-on-Enter, so the next Enter would re-open this
+            // page instead of creating the workspace. The header Back button keeps the default focus restore.
+            skipNextFocusRestore();
             goBack();
         },
         [goBack],
diff --git a/src/pages/home/ForYouSection/ForYouSkeleton.tsx b/src/pages/home/ForYouSection/ForYouSkeleton.tsx
index d073fd8008d1..7549e5d3abe2 100644
--- a/src/pages/home/ForYouSection/ForYouSkeleton.tsx
+++ b/src/pages/home/ForYouSection/ForYouSkeleton.tsx
@@ -43,7 +43,7 @@ function ForYouSkeleton({reasonAttributes}: Props) {
             const iconY = 12;
             const titleX = iconX + 40 + gap;
             const titleWidth = getTitleSkeletonWidth(args.itemIndex);
-            const buttonWidth = styles.widgetItemButton.minWidth;
+            const buttonWidth = styles.widgetItemButton.minWidth ?? 0;
             const buttonHeight = 28;
             const buttonX = pageWidth - horizontalPadding - buttonWidth;
             const buttonY = (ITEM_HEIGHT - buttonHeight) / 2;
diff --git a/src/pages/home/ForYouSection/index.tsx b/src/pages/home/ForYouSection/index.tsx
index 9cdb43c4e220..52494eb0739f 100644
--- a/src/pages/home/ForYouSection/index.tsx
+++ b/src/pages/home/ForYouSection/index.tsx
@@ -11,6 +11,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
 import {buildQueryStringFromFilterFormValues} from '@libs/SearchQueryUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
+import colors from '@styles/theme/colors';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
@@ -18,6 +19,7 @@ import {accountIDSelector} from '@src/selectors/Session';
 import todosReportCountsSelector, {EMPTY_TODOS_SINGLE_REPORT_IDS, todosSingleReportIDsSelector} from '@src/selectors/Todos';
 import EmptyState from './EmptyState';
 import ForYouSkeleton from './ForYouSkeleton';
+import useReviewFlaggedExpenses from './useReviewFlaggedExpenses';
 
 function ForYouSection() {
     const styles = useThemeStyles();
@@ -33,24 +35,32 @@ function ForYouSection() {
     const [hasLoadedApp = false] = useOnyx(ONYXKEYS.HAS_LOADED_APP);
     const [reportCounts = CONST.EMPTY_TODOS_REPORT_COUNTS] = useOnyx(ONYXKEYS.DERIVED.TODOS, {selector: todosReportCountsSelector});
     const [singleReportIDs = EMPTY_TODOS_SINGLE_REPORT_IDS] = useOnyx(ONYXKEYS.DERIVED.TODOS, {selector: todosSingleReportIDsSelector});
+    const {count: flaggedExpensesCount, reviewExpenses} = useReviewFlaggedExpenses();
 
-    const icons = useMemoizedLazyExpensifyIcons(['MoneyBag', 'Send', 'ThumbsUp', 'Export']);
+    const icons = useMemoizedLazyExpensifyIcons(['ReceiptSearch', 'MoneyBag', 'Send', 'ThumbsUp', 'Export']);
 
     const submitCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.SUBMIT] ?? 0;
     const approveCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.APPROVE] ?? 0;
     const payCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.PAY] ?? 0;
     const exportCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.EXPORT] ?? 0;
 
-    const hasAnyTodos = submitCount > 0 || approveCount > 0 || payCount > 0 || exportCount > 0;
+    const hasAnyTodos = flaggedExpensesCount > 0 || submitCount > 0 || approveCount > 0 || payCount > 0 || exportCount > 0;
+
+    const navigateToReport = useCallback(
+        (reportID: string) => {
+            if (shouldUseNarrowLayout) {
+                Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, undefined, undefined, ROUTES.HOME));
+                return;
+            }
+            Navigation.navigate(ROUTES.EXPENSE_REPORT_RHP.getRoute({reportID, backTo: ROUTES.HOME}));
+        },
+        [shouldUseNarrowLayout],
+    );
 
     const createNavigationHandler = useCallback(
         (action: string, queryParams: Record<string, unknown>, reportID?: string) => () => {
             if (reportID) {
-                if (shouldUseNarrowLayout) {
-                    Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, undefined, undefined, ROUTES.HOME));
-                } else {
-                    Navigation.navigate(ROUTES.EXPENSE_REPORT_RHP.getRoute({reportID, backTo: ROUTES.HOME}));
-                }
+                navigateToReport(reportID);
                 return;
             }
 
@@ -64,12 +74,22 @@ function ForYouSection() {
                 }),
             );
         },
-        [shouldUseNarrowLayout],
+        [navigateToReport],
     );
 
     const todoItems = useMemo(
         () =>
             [
+                {
+                    key: 'reviewExpenses',
+                    count: flaggedExpensesCount,
+                    icon: icons.ReceiptSearch,
+                    iconBackgroundColor: colors.tangerine100,
+                    iconFill: colors.tangerine500,
+                    translationKey: 'homePage.forYouSection.reviewExpenses' as const,
+                    handler: reviewExpenses,
+                    buttonProps: {danger: true} as const,
+                },
                 {
                     key: 'submit',
                     count: submitCount,
@@ -107,21 +127,36 @@ function ForYouSection() {
                     ),
                 },
             ].filter((item) => item.count > 0),
-        [accountID, approveCount, createNavigationHandler, exportCount, icons.Export, icons.MoneyBag, icons.Send, icons.ThumbsUp, payCount, singleReportIDs, submitCount],
+        [
+            accountID,
+            approveCount,
+            createNavigationHandler,
+            reviewExpenses,
+            exportCount,
+            flaggedExpensesCount,
+            icons.Export,
+            icons.MoneyBag,
+            icons.ReceiptSearch,
+            icons.Send,
+            icons.ThumbsUp,
+            payCount,
+            singleReportIDs,
+            submitCount,
+        ],
     );
 
     const renderTodoItems = () => (
         <View style={styles.getForYouSectionContainerStyle(shouldUseNarrowLayout)}>
-            {todoItems.map(({key, count, icon, translationKey, handler}) => (
+            {todoItems.map(({key, count, icon, iconBackgroundColor, iconFill, translationKey, handler, buttonProps}) => (
                 <BaseWidgetItem
                     key={key}
                     icon={icon}
-                    iconBackgroundColor={theme.widgetIconBG}
-                    iconFill={theme.widgetIconFill}
+                    iconBackgroundColor={iconBackgroundColor ?? theme.widgetIconBG}
+                    iconFill={iconFill ?? theme.widgetIconFill}
                     title={translate(translationKey, {count})}
                     ctaText={translate('homePage.forYouSection.begin')}
                     onCtaPress={handler}
-                    buttonProps={{success: true}}
+                    buttonProps={buttonProps ?? {success: true}}
                 />
             ))}
         </View>
diff --git a/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts b/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts
new file mode 100644
index 000000000000..3957511ad012
--- /dev/null
+++ b/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts
@@ -0,0 +1,51 @@
+import {useCallback} from 'react';
+import useNavigateToTransactionThread from '@hooks/useNavigateToTransactionThread';
+import useOnyx from '@hooks/useOnyx';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import {EMPTY_FLAGGED_EXPENSES_REVIEW, flaggedExpensesReviewSelector} from '@src/selectors/Todos';
+
+type ReviewFlaggedExpenses = {
+    /** Number of flagged expenses awaiting review, used to decide whether to render the review row */
+    count: number;
+
+    /** Opens the first flagged expense's transaction thread with the full set of flagged expenses as the review carousel */
+    reviewExpenses: () => void;
+};
+
+/**
+ * Encapsulates the data plumbing for the "Review X expenses" row in the For You section: it reads the
+ * flagged-expenses review summary plus the first flagged expense's report, report actions, and transaction,
+ * and exposes a bound handler that navigates to the transaction thread (single-expense RHP + review carousel).
+ */
+function useReviewFlaggedExpenses(): ReviewFlaggedExpenses {
+    const [review = EMPTY_FLAGGED_EXPENSES_REVIEW] = useOnyx(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {selector: flaggedExpensesReviewSelector});
+
+    // Load the first flagged expense's parent report, its actions, and the transaction itself so the shared
+    // navigation hook can resolve (or optimistically create) the transaction thread.
+    const [firstFlaggedReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(review.firstReportID)}`);
+    const [firstFlaggedReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(review.firstReportID)}`);
+    const [firstFlaggedTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(review.firstTransactionID)}`);
+
+    const navigateToTransactionThread = useNavigateToTransactionThread();
+
+    const reviewExpenses = useCallback(() => {
+        const {firstTransactionID, firstReportID, transactionIDs} = review;
+        if (!firstTransactionID || !firstReportID) {
+            return;
+        }
+        navigateToTransactionThread({
+            transactionID: firstTransactionID,
+            reportActions: Object.values(firstFlaggedReportActions ?? {}),
+            report: firstFlaggedReport,
+            transaction: firstFlaggedTransaction,
+            siblingTransactionIDs: transactionIDs,
+            backTo: ROUTES.HOME,
+        });
+    }, [review, firstFlaggedReportActions, firstFlaggedReport, firstFlaggedTransaction, navigateToTransactionThread]);
+
+    return {count: review.count, reviewExpenses};
+}
+
+export default useReviewFlaggedExpenses;
diff --git a/src/pages/inbox/AgentZeroStatusContext.tsx b/src/pages/inbox/AgentZeroStatusContext.tsx
index dfda44ffaf9a..50919a5afeb5 100644
--- a/src/pages/inbox/AgentZeroStatusContext.tsx
+++ b/src/pages/inbox/AgentZeroStatusContext.tsx
@@ -1,4 +1,4 @@
-import {getAgentAccountIDFlags, getReportParticipantAccountIDs} from '@selectors/AgentZeroChat';
+import {getCustomAgentParticipantAccountID, getReportParticipantAccountIDs} from '@selectors/AgentZeroChat';
 import {getReportChatType} from '@selectors/Report';
 import {agentZeroProcessingAgentIDsSelector} from '@selectors/ReportNameValuePairs';
 import {accountIDSelector} from '@selectors/Session';
@@ -41,24 +41,19 @@ const AgentZeroStatusActionsContext = createContext<AgentZeroStatusActions>(defa
  * metadata. For non-AgentZero reports (the common case), returns children directly.
  *
  * AgentZero chats include Concierge DMs, policy #admins rooms, and custom-agent chats (any
- * report with a participant — other than the current user — whose accountID has a
- * `SHARED_NVP_AGENT_PROMPT_<accountID>` entry, populated by `OpenAgentsPage` for agents the
- * current user owns).
+ * report with a participant whose personalDetails carries `isCustomAgent: true`, stamped
+ * server-side in `Account::formatNewDotPersonalDetails`).
  */
 function AgentZeroStatusProvider({reportID, children}: React.PropsWithChildren<{reportID: string | undefined}>) {
     const [chatType] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {selector: getReportChatType});
     const [participantAccountIDs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {selector: getReportParticipantAccountIDs});
-    const [agentAccountIDFlags] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT, {selector: getAgentAccountIDFlags});
+    const [agentParticipantAccountID] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: getCustomAgentParticipantAccountID(participantAccountIDs)});
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
-    const [currentUserAccountID] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector});
 
     const isConciergeChat = reportID === conciergeReportID;
     const isAdmin = chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS;
-    // A custom-agent chat has a participant — excluding the current user — whose accountID owns
-    // an agent prompt. Excluding the current user prevents a user who owns agents from turning
-    // their own DMs into agent chats.
-    const hasAgentParticipant = participantAccountIDs?.some((accountID) => accountID !== currentUserAccountID && !!agentAccountIDFlags?.[accountID]) ?? false;
-    const isAgentZeroChat = isConciergeChat || isAdmin || hasAgentParticipant;
+    const isCustomAgentChat = agentParticipantAccountID !== undefined;
+    const isAgentZeroChat = isConciergeChat || isAdmin || isCustomAgentChat;
 
     if (!reportID || !isAgentZeroChat) {
         return children;
diff --git a/src/pages/inbox/ConciergeDraftContext.tsx b/src/pages/inbox/ConciergeDraftContext.tsx
index df64adc29085..ee114c151b91 100644
--- a/src/pages/inbox/ConciergeDraftContext.tsx
+++ b/src/pages/inbox/ConciergeDraftContext.tsx
@@ -1,4 +1,4 @@
-import {getAgentAccountIDFlags, getReportParticipantAccountIDs} from '@selectors/AgentZeroChat';
+import {getCustomAgentParticipantAccountID, getReportParticipantAccountIDs} from '@selectors/AgentZeroChat';
 import {getReportChatType} from '@selectors/Report';
 import React, {createContext, useContext} from 'react';
 import useOnyx from '@hooks/useOnyx';
@@ -42,14 +42,14 @@ const ConciergeDraftActionsContext = createContext<ConciergeDraftActions>(defaul
 function ConciergeDraftProvider({reportID, children}: React.PropsWithChildren<{reportID: string | undefined}>) {
     const [chatType] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {selector: getReportChatType});
     const [participantAccountIDs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {selector: getReportParticipantAccountIDs});
-    const [agentAccountIDFlags] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT, {selector: getAgentAccountIDFlags});
+    const [agentParticipantAccountID] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: getCustomAgentParticipantAccountID(participantAccountIDs)});
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
 
     const isConciergeChat = reportID === conciergeReportID;
     const isAdmin = chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS;
-    // See AgentZeroStatusContext for the rationale: agentAccountIDFlags reflects agents the
-    // user owns (populated by `OpenAgentsPage`).
-    const isCustomAgentChat = participantAccountIDs?.some((accountID) => !!agentAccountIDFlags?.[accountID]);
+    // See AgentZeroStatusContext for the rationale: `isCustomAgent` lives on the participant's
+    // personalDetails, stamped by Auth in `Account::formatNewDotPersonalDetails`.
+    const isCustomAgentChat = agentParticipantAccountID !== undefined;
     const isAgentZeroChat = isConciergeChat || isAdmin || isCustomAgentChat;
 
     if (!reportID || !isAgentZeroChat) {
diff --git a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx
index ef9b35f0a57f..02fd2761a5af 100755
--- a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx
+++ b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx
@@ -1,4 +1,4 @@
-import {hasSeenTourSelector} from '@selectors/Onboarding';
+import {hasSeenTourSelector, isTrackIntentUserSelector} from '@selectors/Onboarding';
 import {deepEqual} from 'fast-equals';
 import type {RefObject} from 'react';
 import React, {memo, useMemo, useRef, useState} from 'react';
@@ -239,6 +239,7 @@ function BaseReportActionContextMenu({
     const {transactions} = useTransactionsAndViolationsForReport(childReport?.reportID);
     const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT);
     const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
     const [isSelfTourViewed] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector});
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
@@ -395,6 +396,7 @@ function BaseReportActionContextMenu({
                                 card,
                                 originalReport,
                                 isTryNewDotNVPDismissed,
+                                isTrackIntentUser,
                                 childReport,
                                 movedFromReport,
                                 movedToReport,
diff --git a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
index 3a3e8aab7929..ad38cba6f596 100644
--- a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
+++ b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
@@ -37,6 +37,7 @@ import {
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
     getCardIssuedMessage,
+    getCategoryTaxRateMessage,
     getChangedApproverActionMessage,
     getCompanyAddressUpdateMessage,
     getCompanyCardConnectionBrokenMessage,
@@ -187,6 +188,7 @@ import {
     isSelfDM,
     shouldDisableThread,
     shouldDisplayThreadReplies as shouldDisplayThreadRepliesReportUtils,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import {getAddExpensifyCardRuleMessage, getRemoveExpensifyCardRuleMessage, getUpdateExpensifyCardRuleMessage} from '@libs/SpendRuleChangeLogUtils';
 import {getTaskCreatedMessage, getTaskReportActionMessage} from '@libs/TaskUtils';
@@ -301,6 +303,7 @@ type ContextMenuActionPayload = {
     originalReport: OnyxEntry<ReportType>;
     isHarvestReport?: boolean;
     isTryNewDotNVPDismissed?: boolean;
+    isTrackIntentUser?: boolean;
     childReport?: OnyxEntry<ReportType>;
     movedFromReport?: OnyxEntry<ReportType>;
     movedToReport?: OnyxEntry<ReportType>;
@@ -875,6 +878,7 @@ const ContextMenuActions: ContextMenuAction[] = [
                 originalReport,
                 isHarvestReport,
                 isTryNewDotNVPDismissed,
+                isTrackIntentUser,
                 movedFromReport,
                 movedToReport,
                 childReport,
@@ -1018,6 +1022,8 @@ const ContextMenuActions: ContextMenuAction[] = [
                     Clipboard.setString(getRequireCompanyCardsEnabledMessage(translate, reportAction));
                 } else if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT) {
                     Clipboard.setString(getAutoReimbursementMessage(translate, reportAction));
+                } else if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE) {
+                    Clipboard.setString(getCategoryTaxRateMessage(translate, reportAction));
                 } else if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MCC_GROUP_CATEGORY) {
                     Clipboard.setString(getMccGroupCategoryMessage(translate, reportAction));
                 } else if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_INVOICE_COMPANY_NAME) {
@@ -1074,7 +1080,15 @@ const ContextMenuActions: ContextMenuAction[] = [
                     if (harvesting) {
                         setClipboardMessage(translate('iou.automaticallySubmitted'));
                     } else {
-                        Clipboard.setString(translate('iou.submitted', getOriginalMessage(reportAction)?.message));
+                        Clipboard.setString(
+                            shouldShowMarkAsDone({
+                                policy,
+                                isTrackIntentUser,
+                                report,
+                            })
+                                ? translate('iou.markedAsDone', getOriginalMessage(reportAction)?.message)
+                                : translate('iou.submitted', getOriginalMessage(reportAction)?.message),
+                        );
                     }
                 } else if (isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.APPROVED)) {
                     const {automaticAction} = getOriginalMessage(reportAction) ?? {};
diff --git a/src/pages/inbox/report/FloatingMessageCounter.tsx b/src/pages/inbox/report/FloatingMessageCounter.tsx
index f75fe695fab5..69722fd0f575 100644
--- a/src/pages/inbox/report/FloatingMessageCounter.tsx
+++ b/src/pages/inbox/report/FloatingMessageCounter.tsx
@@ -6,6 +6,7 @@ import type {ValueOf} from 'type-fest';
 import Button from '@components/Button';
 import Icon from '@components/Icon';
 import Text from '@components/Text';
+import getActionBadgeText from '@components/utils/getActionBadgeText';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useTheme from '@hooks/useTheme';
@@ -83,12 +84,23 @@ type FloatingMessageCounterProps = {
 
     /** Callback when the action badge pill is clicked */
     onActionBadgePress?: () => void;
+
+    /** Whether to show "Mark as done" copy instead of "Submit" copy for track-intent users */
+    isMarkAsDone?: boolean;
 };
 
 const MARKER_INACTIVE_TRANSLATE_Y = -40;
 const MARKER_ACTIVE_TRANSLATE_Y = 10;
 
-function FloatingMessageCounter({isActive = false, onClick = () => {}, hasNewMessages, actionBadge, actionBadgeBrickRoadStatus, onActionBadgePress}: FloatingMessageCounterProps) {
+function FloatingMessageCounter({
+    isActive = false,
+    onClick = () => {},
+    hasNewMessages,
+    actionBadge,
+    actionBadgeBrickRoadStatus,
+    onActionBadgePress,
+    isMarkAsDone,
+}: FloatingMessageCounterProps) {
     const icons = useMemoizedLazyExpensifyIcons(['DownArrow', 'UpArrow']);
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -123,6 +135,8 @@ function FloatingMessageCounter({isActive = false, onClick = () => {}, hasNewMes
         transform: [{translateY: translateY.get()}],
     }));
 
+    const actionBadgeText = getActionBadgeText(actionBadge, translate, isMarkAsDone);
+
     return (
         <Animated.View
             accessibilityHint={translate(shouldShowActionBadgePill ? 'accessibilityHints.scrollToActionBadgeTarget' : 'accessibilityHints.scrollToNewestMessages')}
@@ -137,7 +151,7 @@ function FloatingMessageCounter({isActive = false, onClick = () => {}, hasNewMes
                             onPress={onActionBadgePress}
                             icon={icons.UpArrow}
                             iconFill={theme.textLight}
-                            label={translate(`common.actionBadge.${actionBadge}`)}
+                            label={actionBadgeText}
                             textStyle={styles.textWhite}
                         />
                     ) : (
diff --git a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx
index 0c0bfb1416e7..8accb5cebe16 100644
--- a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx
+++ b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx
@@ -31,8 +31,8 @@ import {
     canCreateTaskInReport,
     getPayeeName,
     hasViolations as hasViolationsReportUtils,
-    isPaidGroupPolicy,
     isPolicyExpenseChat,
+    isReportInGroupPolicy,
     isReportOwner,
     temporary_getMoneyRequestOptions,
 } from '@libs/ReportUtils';
@@ -320,7 +320,7 @@ function AttachmentPickerWithMenuItems({
     ]);
 
     const createReportOption: PopoverMenuItem[] = useMemo(() => {
-        if (!isPolicyExpenseChat(report) || !isPaidGroupPolicy(report) || !isReportOwner(report)) {
+        if (!isPolicyExpenseChat(report) || !isReportInGroupPolicy(report) || !isReportOwner(report)) {
             return [];
         }
 
diff --git a/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts b/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts
index f7cdaac0c877..059293fa2ab3 100644
--- a/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts
+++ b/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts
@@ -15,6 +15,7 @@ import {rand64} from '@libs/NumberUtils';
 import {addDomainToShortMention} from '@libs/ParsingUtils';
 import {startSpan} from '@libs/telemetry/activeSpans';
 import {generateAccountID} from '@libs/UserUtils';
+import {useAgentZeroStatusActions} from '@pages/inbox/AgentZeroStatusContext';
 import {ActionListContext} from '@pages/inbox/ReportScreenContext';
 import {setIsComposerFullSize} from '@userActions/Report';
 import CONST from '@src/CONST';
@@ -33,6 +34,7 @@ function useComposerSubmit(reportID: string) {
     const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE);
     const [isComposerFullSize = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportID}`);
     const delegateAccountID = useDelegateAccountID();
+    const {kickoffWaitingIndicator} = useAgentZeroStatusActions();
 
     const {composerRef, attachmentFileRef, textRef} = useComposerMeta();
     const {clearComposer} = useComposerActions();
@@ -66,6 +68,7 @@ function useComposerSubmit(reportID: string) {
         }
 
         if (attachmentFileRef.current) {
+            kickoffWaitingIndicator();
             addAttachmentWithComment({
                 report: targetReport,
                 notifyReportID: reportID,
@@ -148,6 +151,7 @@ function useComposerSubmit(reportID: string) {
                 },
             });
         }
+        kickoffWaitingIndicator();
         addComment({
             report: targetReport,
             notifyReportID: reportID,
diff --git a/src/pages/inbox/report/ReportActionItem.tsx b/src/pages/inbox/report/ReportActionItem.tsx
index b5155383d4ba..f79a659220a5 100644
--- a/src/pages/inbox/report/ReportActionItem.tsx
+++ b/src/pages/inbox/report/ReportActionItem.tsx
@@ -1,4 +1,5 @@
 import {useNavigation} from '@react-navigation/native';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import {personalDetailsDisplayNameSelector} from '@selectors/PersonalDetails';
 import {deepEqual} from 'fast-equals';
 import mapValues from 'lodash/mapValues';
@@ -173,6 +174,7 @@ function ReportActionItem({
     const [originalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${originalReportID}`, {selector: getStableReportSelector});
     const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getIOUReportIDFromReportActionPreview(action)}`);
 
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
     const transactionsOnIOUReport = useReportTransactions(iouReport?.reportID);
     const transactionID = isMoneyRequestAction(action) && getOriginalMessage(action)?.IOUTransactionID;
 
@@ -602,6 +604,7 @@ function ReportActionItem({
                                                                 isHidden={isHidden}
                                                                 updateHiddenState={updateHiddenState}
                                                                 isClosedExpenseReportWithNoExpenses={isClosedExpenseReportWithNoExpenses}
+                                                                isTrackIntentUser={isTrackIntentUser}
                                                                 isHarvestCreatedExpenseReport={isHarvestCreatedExpenseReport}
                                                                 shouldShowBorder={shouldShowBorder}
                                                                 isOnSearch={isOnSearch}
diff --git a/src/pages/inbox/report/ReportActionsList.tsx b/src/pages/inbox/report/ReportActionsList.tsx
index 0d3c6e578a33..4bb59cd2d6e7 100644
--- a/src/pages/inbox/report/ReportActionsList.tsx
+++ b/src/pages/inbox/report/ReportActionsList.tsx
@@ -1,4 +1,5 @@
 import {useRoute} from '@react-navigation/native';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import type {ListRenderItemInfo} from '@shopify/flash-list';
 import React, {memo, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
 import type {LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
@@ -23,6 +24,7 @@ import useUnreadMarker from '@hooks/useUnreadMarker';
 import useWindowDimensions from '@hooks/useWindowDimensions';
 import {isSafari} from '@libs/Browser';
 import {isConsecutiveChronosAutomaticTimerAction} from '@libs/ChronosUtils';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import durationHighlightItem from '@libs/Navigation/helpers/getDurationHighlightItem';
 import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
 import Navigation from '@libs/Navigation/Navigation';
@@ -50,6 +52,7 @@ import {
     isIOUReport,
     isMoneyRequestReport,
     isTaskReport,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import type {ReportsSplitNavigatorParamList} from '@navigation/types';
 import {useConciergeDraft, useConciergeDraftActions} from '@pages/inbox/ConciergeDraftContext';
@@ -189,6 +192,9 @@ function ReportActionsList({
     const [reportLoadingState] = useOnyx(`${ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE}${report.reportID}`);
     const prevIsLoadingInitialReportActions = usePrevious(reportLoadingState?.isLoadingInitialReportActions);
     const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+    const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(report?.policyID)}`);
+
     const reportAttributesSelector = useCallback(
         (value: OnyxEntry<OnyxTypes.ReportAttributesDerivedValue>) => {
             const attrs = value?.reports?.[report.reportID];
@@ -688,6 +694,12 @@ function ReportActionsList({
         requestAnimationFrame(() => setShouldAutoscrollToBottom(false));
     }, [shouldFocusToTopOnMount, shouldAutoscrollToBottom, prevHasOnceLoadedReportActions, reportLoadingState?.hasOnceLoadedReportActions]);
 
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report,
+        isTrackIntentUser,
+    });
+
     return (
         <>
             <FloatingMessageCounter
@@ -697,6 +709,7 @@ function ReportActionsList({
                 actionBadge={!isProduction && isActionBadgeAboveViewport ? reportAttributes?.actionBadge : undefined}
                 actionBadgeBrickRoadStatus={!isProduction && isActionBadgeAboveViewport ? reportAttributes?.brickRoadStatus : undefined}
                 onActionBadgePress={scrollToActionBadgeTarget}
+                isMarkAsDone={shouldUseMarkAsDoneCopy}
             />
             <ReportActionsListPaddingView
                 report={report}
diff --git a/src/pages/inbox/report/actionContents/ActionContentRouter.tsx b/src/pages/inbox/report/actionContents/ActionContentRouter.tsx
index f02171af9cfd..fd4845368f0e 100644
--- a/src/pages/inbox/report/actionContents/ActionContentRouter.tsx
+++ b/src/pages/inbox/report/actionContents/ActionContentRouter.tsx
@@ -50,6 +50,7 @@ import ApprovalFlowContent, {isApprovalFlowAction} from './ApprovalFlowContent';
 import CardBrokenConnectionContent from './CardBrokenConnectionContent';
 import ChatMessageContent from './ChatMessageContent';
 import ChatTransactionPreview from './ChatTransactionPreview';
+import ConciergeAutoMatchVendorContent from './ConciergeAutoMatchVendorContent';
 import ConfirmWhisperContent from './ConfirmWhisperContent';
 import FraudAlertContent from './FraudAlertContent';
 import IntegrationSyncFailedMessage from './IntegrationSyncFailedMessage';
@@ -116,6 +117,9 @@ type ActionContentRouterProps = {
 
     /** Toggle whether the payment method popover is active */
     setIsPaymentMethodPopoverActive: (value: boolean) => void;
+
+    /** Whether the user is a track intent user */
+    isTrackIntentUser?: boolean;
 };
 
 function ActionContentRouter({
@@ -136,6 +140,7 @@ function ActionContentRouter({
     shouldShowBorder,
     isOnSearch,
     setIsPaymentMethodPopoverActive,
+    isTrackIntentUser,
 }: ActionContentRouterProps): React.JSX.Element | null {
     const {translate, formatTravelDate} = useLocalize();
     const styles = useThemeStyles();
@@ -251,6 +256,14 @@ function ActionContentRouter({
             />
         );
     }
+    if (action.actionName === CONST.REPORT.ACTIONS.TYPE.CONCIERGE_AUTO_MATCH_VENDOR) {
+        return (
+            <ConciergeAutoMatchVendorContent
+                action={action}
+                originalReport={originalReport}
+            />
+        );
+    }
     if (isApprovalFlowAction(action)) {
         return (
             <ApprovalFlowContent
@@ -258,6 +271,7 @@ function ActionContentRouter({
                 policyID={policyID}
                 reportID={reportID}
                 originalReport={originalReport}
+                isTrackIntentUser={isTrackIntentUser ?? false}
             />
         );
     }
diff --git a/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx b/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
index 53004ed49dcf..bdeb121b976f 100644
--- a/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
+++ b/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
@@ -6,6 +6,7 @@ import useOnyx from '@hooks/useOnyx';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {hasDynamicExternalWorkflow} from '@libs/PolicyUtils';
 import {getForwardedReportActionMessage, getOriginalMessage, hasPendingDEWApprove, hasPendingDEWSubmit, isActionOfType, isMarkAsClosedAction} from '@libs/ReportActionsUtils';
+import {shouldShowMarkAsDone} from '@libs/ReportUtils';
 import ReportActionItemBasicMessage from '@pages/inbox/report/ReportActionItemBasicMessage';
 import ReportActionItemMessageWithExplain from '@pages/inbox/report/ReportActionItemMessageWithExplain';
 import CONST from '@src/CONST';
@@ -17,6 +18,7 @@ type ApprovalFlowContentProps = {
     policyID: string | undefined;
     reportID: string | undefined;
     originalReport: OnyxEntry<OnyxTypes.Report>;
+    isTrackIntentUser: boolean;
 };
 
 function isApprovalFlowAction(action: OnyxTypes.ReportAction): boolean {
@@ -29,7 +31,7 @@ function isApprovalFlowAction(action: OnyxTypes.ReportAction): boolean {
     );
 }
 
-function ApprovalFlowContent({action, policyID, reportID, originalReport}: ApprovalFlowContentProps) {
+function ApprovalFlowContent({action, policyID, reportID, originalReport, isTrackIntentUser}: ApprovalFlowContentProps) {
     const {translate} = useLocalize();
     const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`);
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);
@@ -60,6 +62,16 @@ function ApprovalFlowContent({action, policyID, reportID, originalReport}: Appro
             return <ReportActionItemBasicMessage message={translate('iou.submitted')} />;
         }
 
+        if (
+            shouldShowMarkAsDone({
+                isTrackIntentUser,
+                policy,
+                report: originalReport,
+            })
+        ) {
+            return <ReportActionItemBasicMessage message={translate('iou.markedAsDone', getOriginalMessage(action)?.message)} />;
+        }
+
         return <ReportActionItemBasicMessage message={translate('iou.submitted', getOriginalMessage(action)?.message)} />;
     }
 
@@ -81,6 +93,16 @@ function ApprovalFlowContent({action, policyID, reportID, originalReport}: Appro
             return <ReportActionItemBasicMessage message={translate('iou.queuedToApproveViaDEW')} />;
         }
 
+        if (
+            shouldShowMarkAsDone({
+                isTrackIntentUser,
+                policy,
+                report: originalReport,
+            })
+        ) {
+            return <ReportActionItemBasicMessage message={translate('iou.markedAsDone')} />;
+        }
+
         return <ReportActionItemBasicMessage message={translate('iou.approvedMessage')} />;
     }
 
diff --git a/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx b/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
new file mode 100644
index 000000000000..b01b92338b2e
--- /dev/null
+++ b/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
@@ -0,0 +1,40 @@
+import {Str} from 'expensify-common';
+import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
+import {getOriginalMessage} from '@libs/ReportActionsUtils';
+import ReportActionItemMessageWithExplain from '@pages/inbox/report/ReportActionItemMessageWithExplain';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report, ReportAction} from '@src/types/onyx';
+
+type ConciergeAutoMatchVendorContentProps = {
+    action: ReportAction;
+    originalReport: OnyxEntry<Report>;
+};
+
+function ConciergeAutoMatchVendorContent({action, originalReport}: ConciergeAutoMatchVendorContentProps) {
+    const {translate} = useLocalize();
+    const [childReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(action.childReportID)}`);
+
+    const originalMessage = getOriginalMessage(action);
+    const rawVendorName = originalMessage && typeof originalMessage === 'object' && 'vendorName' in originalMessage ? (originalMessage.vendorName ?? '') : '';
+
+    // vendorName is interpolated into an HTML translation rendered via RenderHTML, so encode it to prevent QBO vendor names containing HTML from being parsed as markup.
+    const vendorName = Str.htmlEncode(rawVendorName);
+    const message = translate('iou.conciergeAutoMatchedVendor', {vendorName});
+
+    return (
+        <ReportActionItemMessageWithExplain
+            message={message}
+            action={action}
+            childReport={childReport}
+            originalReport={originalReport}
+        />
+    );
+}
+
+ConciergeAutoMatchVendorContent.displayName = 'ConciergeAutoMatchVendorContent';
+
+export default ConciergeAutoMatchVendorContent;
diff --git a/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx b/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx
index b41ee768ec11..65bddc209903 100644
--- a/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx
+++ b/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx
@@ -13,6 +13,7 @@ import {
     getAssignedCompanyCardMessage,
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
+    getCategoryTaxRateMessage,
     getCompanyAddressUpdateMessage,
     getCurrencyDefaultTaxUpdateMessage,
     getCustomTaxNameUpdateMessage,
@@ -145,6 +146,7 @@ const POLICY_CHANGE_LOG_RESOLVERS: Record<string, ResolverFn> = {
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_FORWARDS_TO]: (translate, action) => getForwardsToUpdateMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_PAY_APPROVED_REPORTS_ENABLED]: (translate, action) => getAutoPayApprovedReportsEnabledMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT]: (translate, action) => getAutoReimbursementMessage(translate, action),
+    [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE]: (translate, action) => getCategoryTaxRateMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MCC_GROUP_CATEGORY]: (translate, action) => getMccGroupCategoryMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_INVOICE_COMPANY_NAME]: (translate, action) => getInvoiceCompanyNameUpdateMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_INVOICE_COMPANY_WEBSITE]: (translate, action) => getInvoiceCompanyWebsiteUpdateMessage(translate, action),
diff --git a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
index 1c26ec9a423a..916ff22e97b7 100644
--- a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
+++ b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
@@ -14,6 +14,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {isMobile} from '@libs/Browser';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import ONYXKEYS from '@src/ONYXKEYS';
+import InboxTabSelector from './InboxTabSelector';
 import SidebarLinksData from './SidebarLinksData';
 
 // Once the app finishes loading for the first time, we never show the skeleton again
@@ -57,6 +58,7 @@ function BaseSidebarScreen() {
                         shouldDisplaySearch={shouldUseNarrowLayout}
                         shouldDisplayHelpButton={shouldUseNarrowLayout}
                     />
+                    {!shouldShowSkeleton && <InboxTabSelector />}
                     <View style={[styles.flex1]}>
                         {shouldShowSkeleton ? (
                             <OptionsListSkeletonView
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
new file mode 100644
index 000000000000..a675df7900eb
--- /dev/null
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -0,0 +1,62 @@
+import React from 'react';
+import {View} from 'react-native';
+import TabSelectorBase from '@components/TabSelector/TabSelectorBase';
+import TabSelectorContextProvider from '@components/TabSelector/TabSelectorContext';
+import type {TabSelectorBaseItem} from '@components/TabSelector/types';
+import useLocalize from '@hooks/useLocalize';
+import {useSidebarOrderedReportsActions, useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
+import useThemeStyles from '@hooks/useThemeStyles';
+import CONST from '@src/CONST';
+
+function InboxTabSelector() {
+    const {translate} = useLocalize();
+    const styles = useThemeStyles();
+    const {activeTab, inboxTabCounts} = useSidebarOrderedReportsState();
+    const {setActiveTab} = useSidebarOrderedReportsActions();
+
+    const getBadgeText = (count: number) => (count > 0 ? count.toString() : undefined);
+
+    const tabs: TabSelectorBaseItem[] = [
+        {
+            key: CONST.INBOX_TAB.ALL,
+            title: translate('inboxTabs.all'),
+        },
+        {
+            key: CONST.INBOX_TAB.UNREAD,
+            title: translate('inboxTabs.unread'),
+            badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.UNREAD]),
+            isBadgeCondensed: true,
+            badgeStyles: styles.inboxTabBadge,
+        },
+        {
+            key: CONST.INBOX_TAB.TODO,
+            title: translate('inboxTabs.todo'),
+            badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.TODO]),
+            isBadgeCondensed: true,
+            badgeStyles: styles.inboxTabBadge,
+        },
+    ];
+
+    return (
+        <TabSelectorContextProvider activeTabKey={activeTab}>
+            <View style={styles.pt1}>
+                <TabSelectorBase
+                    tabs={tabs}
+                    activeTabKey={activeTab}
+                    onTabPress={(key) => {
+                        if (key !== CONST.INBOX_TAB.ALL && key !== CONST.INBOX_TAB.UNREAD && key !== CONST.INBOX_TAB.TODO) {
+                            return;
+                        }
+                        setActiveTab(key);
+                    }}
+                    equalWidth
+                    contentContainerStyles={styles.pb1}
+                />
+            </View>
+        </TabSelectorContextProvider>
+    );
+}
+
+InboxTabSelector.displayName = 'InboxTabSelector';
+
+export default InboxTabSelector;
diff --git a/src/pages/inbox/sidebar/SidebarLinks.tsx b/src/pages/inbox/sidebar/SidebarLinks.tsx
index a367a114ca02..46e379148e9d 100644
--- a/src/pages/inbox/sidebar/SidebarLinks.tsx
+++ b/src/pages/inbox/sidebar/SidebarLinks.tsx
@@ -8,6 +8,7 @@ import LHNOptionsList from '@components/LHNOptionsList/LHNOptionsList';
 import OptionsListSkeletonView from '@components/OptionsListSkeletonView';
 import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import {useSidebarOrderedReportsActions} from '@hooks/useSidebarOrderedReports';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {setSidebarLoaded} from '@libs/actions/App';
@@ -39,6 +40,7 @@ function SidebarLinks({insets, optionListItems, priorityMode = CONST.PRIORITY_MO
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
+    const {setStickyReportID} = useSidebarOrderedReportsActions();
     const [isLoadingReportData = true] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA);
 
     useEffect(() => {
@@ -69,9 +71,11 @@ function SidebarLinks({insets, optionListItems, priorityMode = CONST.PRIORITY_MO
                 cancelSpan(`${CONST.TELEMETRY.SPAN_OPEN_REPORT}_${option.reportID}`);
                 return;
             }
+            // Keep this report visible in the active To-do/Unread tab even after opening it marks it read.
+            setStickyReportID(option.reportID);
             Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(option.reportID, actionTargetReportActionID));
         },
-        [shouldUseNarrowLayout, isActiveReport],
+        [shouldUseNarrowLayout, isActiveReport, setStickyReportID],
     );
 
     const viewMode = priorityMode === CONST.PRIORITY_MODE.GSD ? CONST.OPTION_MODE.COMPACT : CONST.OPTION_MODE.DEFAULT;
diff --git a/src/pages/inbox/sidebar/SidebarLinksData.tsx b/src/pages/inbox/sidebar/SidebarLinksData.tsx
index 1c4879c15884..8007f08fa91f 100644
--- a/src/pages/inbox/sidebar/SidebarLinksData.tsx
+++ b/src/pages/inbox/sidebar/SidebarLinksData.tsx
@@ -1,13 +1,13 @@
-import {useFocusEffect, useIsFocused} from '@react-navigation/native';
+import {useIsFocused} from '@react-navigation/native';
 import * as Sentry from '@sentry/react-native';
-import React, {useCallback, useEffect, useRef} from 'react';
+import React, {useCallback, useRef} from 'react';
 import {View} from 'react-native';
 import type {EdgeInsets} from 'react-native-safe-area-context';
+import useInboxTabSpanLifecycle from '@hooks/useInboxTabSpanLifecycle';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import {useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {cancelSpan, endSpan, getSpan} from '@libs/telemetry/activeSpans';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import SidebarLinks from './SidebarLinks';
@@ -23,48 +23,13 @@ function SidebarLinksData({insets}: SidebarLinksDataProps) {
     const {translate} = useLocalize();
     const [priorityMode = CONST.PRIORITY_MODE.DEFAULT] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
 
-    const {orderedReports, currentReportID} = useSidebarOrderedReportsState('SidebarLinksData');
+    const {filteredReports, currentReportID} = useSidebarOrderedReportsState('SidebarLinksData');
 
     const currentReportIDRef = useRef(currentReportID);
     currentReportIDRef.current = currentReportID;
     const isActiveReport = useCallback((reportID: string): boolean => currentReportIDRef.current === reportID, []);
 
-    const hasHadFirstLayout = useRef(false);
-    const spanOnMount = useRef(getSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB));
-
-    const onLayout = useCallback(() => {
-        hasHadFirstLayout.current = true;
-        endSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-        spanOnMount.current = undefined;
-    }, []);
-
-    // Focus: ends span on re-visits (react-freeze cached layout, onLayout won't fire again).
-    // Blur cleanup: cancels orphaned span when user navigates away before onLayout fires.
-    useFocusEffect(
-        useCallback(() => {
-            if (hasHadFirstLayout.current) {
-                endSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-            }
-            return () => cancelSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-        }, []),
-    );
-
-    // Unmount: cancel only if layout never completed AND the active span is
-    // the same one that existed when this instance mounted (avoids canceling
-    // a newer span started by a subsequent tab click).
-    useEffect(
-        () => () => {
-            if (hasHadFirstLayout.current) {
-                return;
-            }
-            const activeSpan = getSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-            if (activeSpan !== spanOnMount.current) {
-                return;
-            }
-            cancelSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-        },
-        [],
-    );
+    const onLayout = useInboxTabSpanLifecycle();
 
     return (
         <View
@@ -80,7 +45,7 @@ function SidebarLinksData({insets}: SidebarLinksDataProps) {
                 priorityMode={priorityMode ?? CONST.PRIORITY_MODE.DEFAULT}
                 // Data props:
                 isActiveReport={isActiveReport}
-                optionListItems={orderedReports}
+                optionListItems={filteredReports}
             />
         </View>
     );
diff --git a/src/pages/inbox/usePusherDraftPacing.ts b/src/pages/inbox/usePusherDraftPacing.ts
index 81c1d3860fa3..3ee5da4e84b5 100644
--- a/src/pages/inbox/usePusherDraftPacing.ts
+++ b/src/pages/inbox/usePusherDraftPacing.ts
@@ -7,6 +7,7 @@ import Pusher from '@libs/Pusher';
 import type {ConciergeDraftEvent, ConciergeDraftEventsEvent} from '@libs/Pusher/types';
 import tokenizeForReveal from '@libs/ReportActionFollowupUtils/tokenizeForReveal';
 import {getReportActionHtml} from '@libs/ReportActionsUtils';
+import Visibility from '@libs/Visibility';
 import type {ConciergeDraft} from './conciergeDraftState';
 import {applyConciergeDraftEvent, CONCIERGE_DRAFT_STATUS, getCachedDraft, getNextVisibleConciergeDraftMarkdown, setCachedDraft} from './conciergeDraftState';
 
@@ -20,6 +21,7 @@ type PusherDraftPaceRefs = {
     finalRenderedHTMLRevealLastStageRef: MutableRef<number>;
     finalRenderedHTMLRevealStartedAtRef: MutableRef<number>;
     finalRenderedHTMLRevealTokensRef: MutableRef<string[]>;
+    lastPaceTickTimeRef: MutableRef<number>;
     latestPusherDraftEventRef: MutableRef<ConciergeDraftEvent | null>;
     pusherPaceIntervalRef: MutableRef<ReturnType<typeof setInterval> | null>;
     queuedPusherDraftEventsRef: MutableRef<ConciergeDraftEvent[]>;
@@ -94,6 +96,7 @@ function resetPusherDraftPace(runtime: PusherDraftPaceRefs) {
         finalRenderedHTMLRevealLastStageRef,
         finalRenderedHTMLRevealStartedAtRef,
         finalRenderedHTMLRevealTokensRef,
+        lastPaceTickTimeRef,
         latestPusherDraftEventRef,
         queuedPusherDraftEventsRef,
         visibleBodyMarkdownRef,
@@ -112,6 +115,7 @@ function resetPusherDraftPace(runtime: PusherDraftPaceRefs) {
     visibleBodyMarkdownRef.current = '';
     visibleSourceMarkdownRef.current = '';
     visibleSourceOffsetRef.current = 0;
+    lastPaceTickTimeRef.current = 0;
 }
 
 function clearCachedPusherDraft(runtime: PusherDraftPacingRuntime) {
@@ -201,8 +205,24 @@ function publishVisibleEvent(
     });
 }
 
+function getNextLastPaceTickTime(now: number, paceStartTime: number, elapsedIntervals: number, revealedUnits: number, shouldPreserveElapsedDebt: boolean): number {
+    if (!shouldPreserveElapsedDebt || elapsedIntervals === 0 || revealedUnits === 0) {
+        return now;
+    }
+
+    return Math.min(now, paceStartTime + revealedUnits * PUSHER_DRAFT_PACE_INTERVAL_MS);
+}
+
 function tickPacing(runtime: PusherDraftPacingRuntime) {
-    const {completedPusherDraftEventRef, latestPusherDraftEventRef, queuedPusherDraftEventsRef, visibleBodyMarkdownRef, visibleSourceMarkdownRef, visibleSourceOffsetRef} = runtime;
+    const {
+        completedPusherDraftEventRef,
+        lastPaceTickTimeRef,
+        latestPusherDraftEventRef,
+        queuedPusherDraftEventsRef,
+        visibleBodyMarkdownRef,
+        visibleSourceMarkdownRef,
+        visibleSourceOffsetRef,
+    } = runtime;
     const latestEvent = latestPusherDraftEventRef.current;
     const targetBodyMarkdown = latestEvent?.bodyMarkdown ?? '';
 
@@ -213,10 +233,41 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
 
     const completedEvent = completedPusherDraftEventRef.current;
     const hasQueuedTarget = queuedPusherDraftEventsRef.current.length > 0;
-    const nextVisibleMarkdown = getNextVisibleConciergeDraftMarkdown(visibleBodyMarkdownRef.current, targetBodyMarkdown, visibleSourceOffsetRef.current, visibleSourceMarkdownRef.current);
+    const now = Date.now();
+    const elapsed = lastPaceTickTimeRef.current ? Math.max(0, now - lastPaceTickTimeRef.current) : PUSHER_DRAFT_PACE_INTERVAL_MS;
+    const elapsedIntervals = Math.floor(elapsed / PUSHER_DRAFT_PACE_INTERVAL_MS);
+    const unitsToReveal = Math.max(1, elapsedIntervals);
+    const paceStartTime = lastPaceTickTimeRef.current || now - elapsedIntervals * PUSHER_DRAFT_PACE_INTERVAL_MS;
+    let revealedUnits = 0;
+    let nextVisibleMarkdown = {
+        bodyMarkdown: visibleBodyMarkdownRef.current,
+        sourceMarkdown: visibleSourceMarkdownRef.current,
+        sourceOffset: visibleSourceOffsetRef.current,
+    };
+
+    while (revealedUnits < unitsToReveal && nextVisibleMarkdown.sourceOffset < targetBodyMarkdown.length) {
+        const advancedVisibleMarkdown = getNextVisibleConciergeDraftMarkdown(
+            nextVisibleMarkdown.bodyMarkdown,
+            targetBodyMarkdown,
+            nextVisibleMarkdown.sourceOffset,
+            nextVisibleMarkdown.sourceMarkdown,
+        );
+
+        if (advancedVisibleMarkdown.sourceOffset <= nextVisibleMarkdown.sourceOffset) {
+            nextVisibleMarkdown = advancedVisibleMarkdown;
+            break;
+        }
+
+        nextVisibleMarkdown = advancedVisibleMarkdown;
+        revealedUnits += 1;
+    }
 
     if (nextVisibleMarkdown.bodyMarkdown !== visibleBodyMarkdownRef.current || nextVisibleMarkdown.sourceOffset !== visibleSourceOffsetRef.current) {
         const isTargetFullyVisible = nextVisibleMarkdown.sourceOffset >= targetBodyMarkdown.length;
+        const shouldPreserveElapsedDebt = (isTargetFullyVisible && hasQueuedTarget) || (!isTargetFullyVisible && revealedUnits >= elapsedIntervals);
+
+        // Only consume time for the units we actually revealed; keep the rest for the next target.
+        lastPaceTickTimeRef.current = getNextLastPaceTickTime(now, paceStartTime, elapsedIntervals, revealedUnits, shouldPreserveElapsedDebt);
         if (completedEvent?.finalRenderedHTML && !completedEvent.bodyMarkdown && completedEvent.status !== CONCIERGE_DRAFT_STATUS.COMPLETED && !hasQueuedTarget && isTargetFullyVisible) {
             completedPusherDraftEventRef.current = null;
             publishVisibleEvent(runtime, latestEvent, nextVisibleMarkdown, CONCIERGE_DRAFT_STATUS.UPDATED);
@@ -231,14 +282,26 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
             completedPusherDraftEventRef.current = null;
             stopPusherDraftPace(runtime);
         }
+
+        if (isTargetFullyVisible && hasQueuedTarget && revealedUnits < unitsToReveal && promoteQueuedPusherDraftTarget(runtime)) {
+            tickPacing(runtime);
+        }
         return;
     }
 
     if (promoteQueuedPusherDraftTarget(runtime)) {
+        if (elapsedIntervals > 0) {
+            tickPacing(runtime);
+            return;
+        }
+
+        lastPaceTickTimeRef.current = now;
         startPusherDraftPace(runtime);
         return;
     }
 
+    lastPaceTickTimeRef.current = now;
+
     if (completedEvent) {
         completedPusherDraftEventRef.current = null;
         if (completedEvent.finalRenderedHTML && !completedEvent.bodyMarkdown && completedEvent.status !== CONCIERGE_DRAFT_STATUS.COMPLETED) {
@@ -257,12 +320,13 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
 }
 
 function startPusherDraftPace(runtime: PusherDraftPacingRuntime) {
-    const {pusherPaceIntervalRef} = runtime;
+    const {lastPaceTickTimeRef, pusherPaceIntervalRef} = runtime;
 
     if (pusherPaceIntervalRef.current) {
         return;
     }
 
+    lastPaceTickTimeRef.current = Date.now();
     pusherPaceIntervalRef.current = setInterval(() => tickPacing(runtime), PUSHER_DRAFT_PACE_INTERVAL_MS);
 }
 
@@ -381,6 +445,54 @@ function getNewestPusherDraftTarget(runtime: PusherDraftPacingRuntime): Concierg
     return runtime.queuedPusherDraftEventsRef.current.at(-1) ?? runtime.latestPusherDraftEventRef.current;
 }
 
+function revealFullPusherDraftTarget(runtime: PusherDraftPacingRuntime) {
+    const {completedPusherDraftEventRef, lastPaceTickTimeRef, latestPusherDraftEventRef, queuedPusherDraftEventsRef} = runtime;
+    const newestTarget = getNewestPusherDraftTarget(runtime);
+    const completedEvent = completedPusherDraftEventRef.current;
+
+    lastPaceTickTimeRef.current = Date.now();
+    stopPusherDraftPace(runtime);
+
+    if (!newestTarget?.bodyMarkdown) {
+        if (completedEvent) {
+            completedPusherDraftEventRef.current = null;
+            if (completedEvent.finalRenderedHTML && !completedEvent.bodyMarkdown && completedEvent.status !== CONCIERGE_DRAFT_STATUS.COMPLETED) {
+                startFinalRenderedHTMLReveal(runtime, completedEvent);
+                return;
+            }
+            publishVisibleEvent(runtime, completedEvent, undefined, CONCIERGE_DRAFT_STATUS.COMPLETED);
+        }
+        return;
+    }
+
+    const targetBodyMarkdown = newestTarget.bodyMarkdown;
+    latestPusherDraftEventRef.current = newestTarget;
+    queuedPusherDraftEventsRef.current = [];
+
+    if (completedEvent?.finalRenderedHTML && !completedEvent.bodyMarkdown && completedEvent.status !== CONCIERGE_DRAFT_STATUS.COMPLETED) {
+        completedPusherDraftEventRef.current = null;
+        publishVisibleEvent(
+            runtime,
+            newestTarget,
+            {bodyMarkdown: targetBodyMarkdown, sourceMarkdown: targetBodyMarkdown, sourceOffset: targetBodyMarkdown.length},
+            CONCIERGE_DRAFT_STATUS.UPDATED,
+        );
+        startFinalRenderedHTMLReveal(runtime, completedEvent);
+        return;
+    }
+
+    publishVisibleEvent(
+        runtime,
+        completedEvent ?? newestTarget,
+        {bodyMarkdown: targetBodyMarkdown, sourceMarkdown: targetBodyMarkdown, sourceOffset: targetBodyMarkdown.length},
+        completedEvent ? CONCIERGE_DRAFT_STATUS.COMPLETED : CONCIERGE_DRAFT_STATUS.UPDATED,
+    );
+
+    if (completedEvent) {
+        completedPusherDraftEventRef.current = null;
+    }
+}
+
 function queuePusherDraftTargets(runtime: PusherDraftPacingRuntime, events: ConciergeDraftEvent[]) {
     const {queuedPusherDraftEventsRef} = runtime;
     let newestTarget = getNewestPusherDraftTarget(runtime);
@@ -667,6 +779,7 @@ function usePusherDraftPacing(reportID: string) {
     const latestPusherDraftEventRef = useRef<ConciergeDraftEvent | null>(buildPusherDraftEventFromCachedDraft(reportID, draft));
     const queuedPusherDraftEventsRef = useRef<ConciergeDraftEvent[]>(draft?.pusherQueuedTargetEvents ?? []);
     const completedPusherDraftEventRef = useRef<ConciergeDraftEvent | null>(draft?.pusherPendingCompletionEvent ?? null);
+    const lastPaceTickTimeRef = useRef(0);
     const pusherPaceIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
     const finalRenderedHTMLRevealIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
     const finalRenderedHTMLRevealTokensRef = useRef<string[]>([]);
@@ -681,6 +794,7 @@ function usePusherDraftPacing(reportID: string) {
             finalRenderedHTMLRevealLastStageRef,
             finalRenderedHTMLRevealStartedAtRef,
             finalRenderedHTMLRevealTokensRef,
+            lastPaceTickTimeRef,
             latestPusherDraftEventRef,
             pusherPaceIntervalRef,
             queuedPusherDraftEventsRef,
@@ -700,6 +814,7 @@ function usePusherDraftPacing(reportID: string) {
             finalRenderedHTMLRevealLastStageRef,
             finalRenderedHTMLRevealStartedAtRef,
             finalRenderedHTMLRevealTokensRef,
+            lastPaceTickTimeRef,
             latestPusherDraftEventRef,
             pusherPaceIntervalRef,
             queuedPusherDraftEventsRef,
@@ -723,6 +838,7 @@ function usePusherDraftPacing(reportID: string) {
             finalRenderedHTMLRevealLastStageRef,
             finalRenderedHTMLRevealStartedAtRef,
             finalRenderedHTMLRevealTokensRef,
+            lastPaceTickTimeRef,
             latestPusherDraftEventRef,
             pusherPaceIntervalRef,
             queuedPusherDraftEventsRef,
@@ -738,24 +854,32 @@ function usePusherDraftPacing(reportID: string) {
             clearCachedPusherDraft(runtime);
         };
 
-        const draftEventSubscriptions: Array<[string, (eventData: unknown) => void]> = [
-            [
-                Pusher.TYPE.CONCIERGE_DRAFT_EVENTS,
-                (eventData) => {
-                    handlePusherDraftEvents(runtime, eventData as ConciergeDraftEventsEvent);
-                },
-            ],
-            ...PUSHER_DRAFT_EVENT_TYPES.map<[string, (eventData: unknown) => void]>((eventType) => [
+        const draftEventSubscriptions = [
+            {
+                eventType: Pusher.TYPE.CONCIERGE_DRAFT_EVENTS,
+                listener: Pusher.subscribe(
+                    channelName,
+                    Pusher.TYPE.CONCIERGE_DRAFT_EVENTS,
+                    (eventData: ConciergeDraftEventsEvent) => {
+                        handlePusherDraftEvents(runtime, eventData);
+                    },
+                    handleResubscribe,
+                ),
+            },
+            ...PUSHER_DRAFT_EVENT_TYPES.map((eventType) => ({
                 eventType,
-                (eventData) => {
-                    handlePusherDraftEvent(runtime, eventData as ConciergeDraftEvent);
-                },
-            ]),
+                listener: Pusher.subscribe(
+                    channelName,
+                    eventType,
+                    (eventData: ConciergeDraftEvent) => {
+                        handlePusherDraftEvent(runtime, eventData);
+                    },
+                    handleResubscribe,
+                ),
+            })),
         ];
 
-        const subscriptions = draftEventSubscriptions.map(([eventType, eventCallback]) => {
-            const listener = Pusher.subscribe(channelName, eventType, eventCallback, handleResubscribe);
-
+        const subscriptions = draftEventSubscriptions.map(({eventType, listener}) => {
             listener.catch((error: unknown) => {
                 Log.hmmm('Failed to subscribe to Pusher concierge draft events', {eventType, reportID, error});
             });
@@ -764,8 +888,32 @@ function usePusherDraftPacing(reportID: string) {
         });
 
         resumeCachedPusherDraftPace(runtime);
+        const unsubscribeVisibility = Visibility.onVisibilityChange(() => {
+            if (!Visibility.isVisible()) {
+                return;
+            }
+
+            if (completedPusherDraftEventRef.current) {
+                // Completion may arrive while the tab is hidden. Reveal the full target on visibility return
+                // so final HTML is not delayed by throttled timers.
+                revealFullPusherDraftTarget(runtime);
+                return;
+            }
+
+            if (finalRenderedHTMLRevealIntervalRef.current) {
+                tickFinalRenderedHTMLReveal(runtime);
+                return;
+            }
+
+            if (!pusherPaceIntervalRef.current) {
+                return;
+            }
+
+            tickPacing(runtime);
+        });
 
         return () => {
+            unsubscribeVisibility();
             stopPusherDraftPace(runtime);
             stopFinalRenderedHTMLReveal(runtime);
             for (const subscription of subscriptions) {
diff --git a/src/pages/iou/SplitExpenseEditPage.tsx b/src/pages/iou/SplitExpenseEditPage.tsx
index b71687aaed46..a1aab1bf4f9b 100644
--- a/src/pages/iou/SplitExpenseEditPage.tsx
+++ b/src/pages/iou/SplitExpenseEditPage.tsx
@@ -30,7 +30,6 @@ import {openPolicyTagsPage} from '@libs/actions/Policy/Tag';
 import {getDecodedLeafCategoryName, isCategoryDescriptionRequired, isCategoryMissing} from '@libs/CategoryUtils';
 import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SplitExpenseParamList} from '@libs/Navigation/types';
@@ -45,7 +44,7 @@ import {getTagVisibility, hasEnabledTags} from '@libs/TagsOptionsListUtils';
 import {getDistanceInMeters, getRateID, getTag, getTagForDisplay, isDistanceRequest, isManualDistanceRequest, isOdometerDistanceRequest} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
 
@@ -271,15 +270,13 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) {
                     // up the same SPLIT_TRANSACTION_DRAFT this screen reads from (see line 57 above).
                     if (isSelfDMSplit && !effectivePolicy && !hasAnyPaidWorkspace && reportID) {
                         Navigation.navigate(
-                            createDynamicRoute(
-                                DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                    action: CONST.IOU.ACTION.EDIT,
-                                    iouType: CONST.IOU.TYPE.SPLIT_EXPENSE,
-                                    transactionID: CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
-                                    reportID,
-                                    upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
-                                }),
-                            ),
+                            ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                action: CONST.IOU.ACTION.EDIT,
+                                iouType: CONST.IOU.TYPE.SPLIT_EXPENSE,
+                                transactionID: CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
+                                reportID,
+                                upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
+                            }),
                         );
                         return;
                     }
@@ -338,25 +335,23 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) {
                                 numberOfLinesTitle={2}
                                 rightLabel={isCategoryRequired ? translate('common.required') : ''}
                                 onPress={() => {
-                                    const categoryRoute = createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
-                                            CONST.IOU.ACTION.EDIT,
-                                            CONST.IOU.TYPE.SPLIT_EXPENSE,
-                                            CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
-                                            reportID,
-                                        ),
+                                    const categoryRoute = ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
+                                        CONST.IOU.ACTION.EDIT,
+                                        CONST.IOU.TYPE.SPLIT_EXPENSE,
+                                        CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
+                                        reportID,
+                                        Navigation.getActiveRoute(),
                                     );
                                     if (shouldNavigateToUpgradePath) {
                                         Navigation.navigate(
-                                            createDynamicRoute(
-                                                DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                                    action: CONST.IOU.ACTION.EDIT,
-                                                    iouType: CONST.IOU.TYPE.SPLIT_EXPENSE,
-                                                    transactionID: CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
-                                                    reportID,
-                                                    upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                                                }),
-                                            ),
+                                            ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                                action: CONST.IOU.ACTION.EDIT,
+                                                iouType: CONST.IOU.TYPE.SPLIT_EXPENSE,
+                                                transactionID: CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
+                                                reportID,
+                                                upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                                                backTo: categoryRoute,
+                                            }),
                                         );
                                         return;
                                     }
diff --git a/src/pages/iou/request/ParticipantSearchResults.tsx b/src/pages/iou/request/ParticipantSearchResults.tsx
index bcb001870a61..e32d2eb8874f 100644
--- a/src/pages/iou/request/ParticipantSearchResults.tsx
+++ b/src/pages/iou/request/ParticipantSearchResults.tsx
@@ -31,7 +31,7 @@ import {formatSectionsFromSearchTerm, getHeaderMessage, getParticipantsOption, g
 import type {Option} from '@libs/OptionsListUtils';
 import {doesPersonalDetailMatchSearchTerm} from '@libs/OptionsListUtils/searchMatchUtils';
 import type {OptionWithKey} from '@libs/OptionsListUtils/types';
-import {getActiveAdminWorkspaces, isPaidGroupPolicy as isPaidGroupPolicyUtil} from '@libs/PolicyUtils';
+import {getActiveAdminWorkspaces, isGroupPolicy as isGroupPolicyUtil} from '@libs/PolicyUtils';
 import type {OptionData} from '@libs/ReportUtils';
 import {isInvoiceRoom} from '@libs/ReportUtils';
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
@@ -158,7 +158,7 @@ function ParticipantSearchResults({
 
     const {isDismissed: isDismissedReferralBanner} = useDismissedReferralBanners({referralContentType: CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE});
 
-    const isPaidGroupPolicy = isPaidGroupPolicyUtil(policy);
+    const isGroupPolicy = isGroupPolicyUtil(policy);
     const activeAdminWorkspaces = getActiveAdminWorkspaces(allPolicies, currentUserLogin);
 
     const getValidOptionsConfig = {
@@ -175,7 +175,7 @@ function ParticipantSearchResults({
         isPerDiemRequest,
         isTimeRequest,
         showRBR: false,
-        preferPolicyExpenseChat: isPaidGroupPolicy,
+        preferPolicyExpenseChat: isGroupPolicy,
         preferRecentExpenseReports: action === CONST.IOU.ACTION.CREATE,
         isRestrictedToPreferredPolicy,
         preferredPolicyID,
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepAccountantPage.tsx b/src/pages/iou/request/step/IOURequestStepAccountant.tsx
similarity index 82%
rename from src/pages/iou/request/step/DynamicIOURequestStepAccountantPage.tsx
rename to src/pages/iou/request/step/IOURequestStepAccountant.tsx
index a944b4ec531f..b5cc69def42a 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepAccountantPage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepAccountant.tsx
@@ -2,7 +2,6 @@ import {activeAdminPoliciesSelector} from '@selectors/Policy';
 import React from 'react';
 import type {OnyxCollection} from 'react-native-onyx';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useLastWorkspaceNumber from '@hooks/useLastWorkspaceNumber';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
@@ -13,7 +12,7 @@ import {createDraftWorkspaceAndNavigateToConfirmationScreen} from '@libs/ReportU
 import MoneyRequestAccountantSelector from '@pages/iou/request/MoneyRequestAccountantSelector';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Policy} from '@src/types/onyx';
 import type {Accountant} from '@src/types/onyx/IOU';
@@ -21,20 +20,19 @@ import StepScreenWrapper from './StepScreenWrapper';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 
-type DynamicIOURequestStepAccountantPageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT>;
+type IOURequestStepAccountantProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT>;
 
-function DynamicIOURequestStepAccountantPage({
+function IOURequestStepAccountant({
     route: {
-        params: {transactionID, reportID, iouType, action},
+        params: {transactionID, reportID, iouType, backTo, action},
     },
-}: DynamicIOURequestStepAccountantPageProps) {
+}: IOURequestStepAccountantProps) {
     const {translate} = useLocalize();
     const {accountID, login, email = '', localCurrencyCode} = useCurrentUserPersonalDetails();
     const selector = (policies: OnyxCollection<Policy>) => activeAdminPoliciesSelector(policies, login ?? '');
     const [adminPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector});
     const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
     const lastWorkspaceNumber = useLastWorkspaceNumber();
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_ACCOUNTANT.path);
 
     const setAccountant = (accountant: Accountant) => {
         setMoneyRequestAccountant(transactionID, accountant, true);
@@ -60,7 +58,7 @@ function DynamicIOURequestStepAccountantPage({
     };
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     return (
@@ -68,7 +66,7 @@ function DynamicIOURequestStepAccountantPage({
             headerTitle={translate('iou.whoIsYourAccountant')}
             onBackButtonPress={navigateBack}
             shouldShowWrapper
-            testID="DynamicIOURequestStepAccountantPage"
+            testID="IOURequestStepAccountant"
         >
             <MoneyRequestAccountantSelector
                 onFinish={navigateToNextStep}
@@ -79,4 +77,4 @@ function DynamicIOURequestStepAccountantPage({
     );
 }
 
-export default withWritableReportOrNotFound(DynamicIOURequestStepAccountantPage);
+export default withWritableReportOrNotFound(IOURequestStepAccountant);
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepAttendeesPage.tsx b/src/pages/iou/request/step/IOURequestStepAttendees.tsx
similarity index 90%
rename from src/pages/iou/request/step/DynamicIOURequestStepAttendeesPage.tsx
rename to src/pages/iou/request/step/IOURequestStepAttendees.tsx
index 4b5e2f516d33..b09435894918 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepAttendeesPage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepAttendees.tsx
@@ -2,7 +2,6 @@ import {deepEqual} from 'fast-equals';
 import React, {useCallback, useState} from 'react';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
@@ -19,18 +18,17 @@ import {getOriginalAttendees} from '@libs/TransactionUtils';
 import MoneyRequestAttendeeSelector from '@pages/iou/request/MoneyRequestAttendeeSelector';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {DYNAMIC_ROUTES} from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Attendee} from '@src/types/onyx/IOU';
 import StepScreenWrapper from './StepScreenWrapper';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 
-type IOURequestStepAttendeesProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES>;
+type IOURequestStepAttendeesProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_ATTENDEES>;
 
-function DynamicIOURequestStepAttendeesPage({
+function IOURequestStepAttendees({
     route: {
-        params: {transactionID, reportID, iouType, action},
+        params: {transactionID, reportID, iouType, backTo, action},
     },
 }: IOURequestStepAttendeesProps) {
     const currentUserPersonalDetails = useCurrentUserPersonalDetails();
@@ -55,7 +53,6 @@ function DynamicIOURequestStepAttendeesPage({
     const delegateAccountID = useDelegateAccountID();
     const {isBetaEnabled} = usePermissions();
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_ATTENDEE.path);
     const {isOffline} = useNetwork();
 
     const saveAttendees = useCallback(() => {
@@ -85,10 +82,11 @@ function DynamicIOURequestStepAttendeesPage({
             }
         }
 
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     }, [
         attendees,
         previousAttendees,
+        backTo,
         transactionID,
         isEditing,
         report,
@@ -103,11 +101,10 @@ function DynamicIOURequestStepAttendeesPage({
         parentReportNextStep,
         isOffline,
         delegateAccountID,
-        backPath,
     ]);
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     return (
@@ -115,7 +112,7 @@ function DynamicIOURequestStepAttendeesPage({
             headerTitle={translate('iou.attendees')}
             onBackButtonPress={navigateBack}
             shouldShowWrapper
-            testID="DynamicIOURequestStepAttendeesPage"
+            testID="IOURequestStepAttendees"
         >
             <MoneyRequestAttendeeSelector
                 onFinish={saveAttendees}
@@ -128,4 +125,4 @@ function DynamicIOURequestStepAttendeesPage({
     );
 }
 
-export default withWritableReportOrNotFound(DynamicIOURequestStepAttendeesPage);
+export default withWritableReportOrNotFound(IOURequestStepAttendees);
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepCategoryPage.tsx b/src/pages/iou/request/step/IOURequestStepCategory.tsx
similarity index 90%
rename from src/pages/iou/request/step/DynamicIOURequestStepCategoryPage.tsx
rename to src/pages/iou/request/step/IOURequestStepCategory.tsx
index f532394d851e..ec838d8580bb 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepCategoryPage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepCategory.tsx
@@ -12,7 +12,6 @@ import type {ListItem} from '@components/SelectionList/types';
 import WorkspaceEmptyStateSection from '@components/WorkspaceEmptyStateSection';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
@@ -39,7 +38,7 @@ import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan
 import {getRequestType} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import StepScreenWrapper from './StepScreenWrapper';
 import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound';
@@ -47,14 +46,17 @@ import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 
-type IOURequestStepCategoryProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY> &
-    WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY>;
-
-function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, route, transaction}: IOURequestStepCategoryProps) {
-    const {
-        params: {transactionID, action, iouType, reportActionID, reportID: routeReportID},
-    } = route;
+type IOURequestStepCategoryProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY> &
+    WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY>;
 
+function IOURequestStepCategory({
+    report: reportReal,
+    reportDraft,
+    route: {
+        params: {transactionID, backTo, action, iouType, reportActionID, reportID: routeReportID},
+    },
+    transaction,
+}: IOURequestStepCategoryProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const illustrations = useMemoizedLazyIllustrations(['EmptyStateExpenses']);
@@ -95,8 +97,6 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
 
     const categoryForDisplay = isCategoryMissing(transactionCategory) ? '' : transactionCategory;
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.path);
-    const shouldReturnToPreviousScreen = backPath !== ROUTES.HOME;
 
     const canCreateCategoryInSitu = isPolicyAdmin(policy) && !hasAccountingConnections(policy) && !!policy?.areCategoriesEnabled;
 
@@ -110,7 +110,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
                       if (!policyID || !reportID) {
                           return;
                       }
-                      Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY_CREATE.getRoute(action, iouType, transactionID, reportID, reportActionID, Navigation.getActiveRoute()));
+                      Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY_CREATE.getRoute(action, iouType, transactionID, reportID, reportActionID, backTo));
                   },
               },
           ]
@@ -147,7 +147,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
     }, [policyID]);
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     const updateCategory = (category: ListItem) => {
@@ -187,7 +187,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
 
         setMoneyRequestCategory(transactionID, updatedCategory, policy);
 
-        if (action === CONST.IOU.ACTION.CATEGORIZE && !shouldReturnToPreviousScreen) {
+        if (action === CONST.IOU.ACTION.CATEGORIZE && !backTo) {
             if (report?.reportID) {
                 Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, report.reportID));
             }
@@ -204,7 +204,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
             shouldShowWrapper
             shouldShowNotFoundPage={shouldShowNotFoundPage}
             shouldShowOfflineIndicator={policyCategories !== undefined}
-            testID="DynamicIOURequestStepCategoryPage"
+            testID="IOURequestStepCategory"
             shouldEnableKeyboardAvoidingView={false}
             threeDotsMenuItems={createCategoryMenuItems}
             shouldMinimizeMenuButton
@@ -241,7 +241,12 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
                                         enablePolicyCategories({...policyData, categories: policyCategories}, true, false);
                                     }
                                     InteractionManager.runAfterInteractions(() => {
-                                        Navigation.navigate(ROUTES.SETTINGS_CATEGORIES_ROOT.getRoute(policyID, Navigation.getActiveRoute()));
+                                        Navigation.navigate(
+                                            ROUTES.SETTINGS_CATEGORIES_ROOT.getRoute(
+                                                policyID,
+                                                ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, report.reportID, backTo, reportActionID),
+                                            ),
+                                        );
                                     });
                                 }}
                                 text={translate('workspace.categories.editCategories')}
@@ -263,6 +268,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
     );
 }
 
-const DynamicIOURequestStepCategoryPageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(DynamicIOURequestStepCategoryPage);
-const DynamicIOURequestStepCategoryPageWithWritableReportOrNotFound = withWritableReportOrNotFound(DynamicIOURequestStepCategoryPageWithFullTransactionOrNotFound);
-export default DynamicIOURequestStepCategoryPageWithWritableReportOrNotFound;
+const IOURequestStepCategoryWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepCategory);
+
+const IOURequestStepCategoryWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepCategoryWithFullTransactionOrNotFound);
+export default IOURequestStepCategoryWithWritableReportOrNotFound;
diff --git a/src/pages/iou/request/step/IOURequestStepCategoryCreate.tsx b/src/pages/iou/request/step/IOURequestStepCategoryCreate.tsx
index 9e6f7ee5ed29..b9cb603d444b 100644
--- a/src/pages/iou/request/step/IOURequestStepCategoryCreate.tsx
+++ b/src/pages/iou/request/step/IOURequestStepCategoryCreate.tsx
@@ -35,7 +35,7 @@ function IOURequestStepCategoryCreate({
     report: reportReal,
     reportDraft,
     route: {
-        params: {transactionID, action, iouType, reportID, backTo},
+        params: {transactionID, action, iouType, reportID, reportActionID, backTo},
     },
     transaction,
 }: IOURequestStepCategoryCreateProps) {
@@ -163,7 +163,7 @@ function IOURequestStepCategoryCreate({
         >
             <StepScreenWrapper
                 headerTitle={translate('workspace.categories.addCategory')}
-                onBackButtonPress={() => Navigation.goBack(backTo)}
+                onBackButtonPress={() => Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, backTo, reportActionID))}
                 shouldShowWrapper
                 testID="IOURequestStepCategoryCreate"
             >
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepTaxAmountPage.tsx b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx
similarity index 88%
rename from src/pages/iou/request/step/DynamicIOURequestStepTaxAmountPage.tsx
rename to src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx
index 476f7e12658c..a9aa927413d5 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepTaxAmountPage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx
@@ -4,7 +4,6 @@ import type {OnyxEntry} from 'react-native-onyx';
 import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import usePermissions from '@hooks/usePermissions';
@@ -22,7 +21,7 @@ import type {CurrentMoney} from '@pages/iou/MoneyRequestAmountForm';
 import MoneyRequestAmountForm from '@pages/iou/MoneyRequestAmountForm';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Policy, Transaction} from '@src/types/onyx';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
@@ -31,7 +30,7 @@ import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 
-type IOURequestStepTaxAmountPageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT> & {
+type IOURequestStepTaxAmountPageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT> & {
     transaction: OnyxEntry<Transaction>;
 };
 
@@ -52,7 +51,7 @@ function getTaxAmount(transaction: OnyxEntry<Transaction>, policy: OnyxEntry<Pol
 
 function IOURequestStepTaxAmountPage({
     route: {
-        params: {action, iouType, reportID, transactionID},
+        params: {action, iouType, reportID, transactionID, backTo},
     },
     transaction,
     report,
@@ -77,9 +76,6 @@ function IOURequestStepTaxAmountPage({
     const delegateAccountID = useDelegateAccountID();
     const {isBetaEnabled} = usePermissions();
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.path);
-    const shouldReturnToPreviousScreen = backPath !== ROUTES.HOME;
-    const isEditingOrReturning = isEditing || shouldReturnToPreviousScreen;
 
     const currentTransaction = isEditingSplitBill && !isEmptyObject(splitDraftTransaction) ? splitDraftTransaction : transaction;
     const transactionDetails = getTransactionDetails(currentTransaction);
@@ -99,7 +95,7 @@ function IOURequestStepTaxAmountPage({
     );
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     const updateTaxAmount = (currentAmount: CurrentMoney) => {
@@ -139,8 +135,8 @@ function IOURequestStepTaxAmountPage({
         // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
         setMoneyRequestCurrency(transactionID, currency || CONST.CURRENCY.USD);
 
-        if (shouldReturnToPreviousScreen) {
-            navigateBack();
+        if (backTo) {
+            Navigation.goBack(backTo);
             return;
         }
 
@@ -163,15 +159,15 @@ function IOURequestStepTaxAmountPage({
         <StepScreenWrapper
             headerTitle={translate('iou.taxAmount')}
             onBackButtonPress={navigateBack}
-            testID="DynamicIOURequestStepTaxAmountPage"
-            shouldShowWrapper={isEditingOrReturning}
+            testID="IOURequestStepTaxAmountPage"
+            shouldShowWrapper={!!(backTo || isEditing)}
             includeSafeAreaPaddingBottom
         >
             <MoneyRequestAmountForm
-                isEditing={isEditingOrReturning}
+                isEditing={!!(backTo || isEditing)}
                 currency={currency}
                 amount={Math.abs(transactionDetails?.taxAmount ?? 0)}
-                taxAmount={getTaxAmount(currentTransaction, policy, currency, decimals, isEditingOrReturning)}
+                taxAmount={getTaxAmount(currentTransaction, policy, currency, decimals, !!(backTo || isEditing))}
                 ref={(e) => {
                     textInput.current = e;
                 }}
@@ -185,8 +181,8 @@ function IOURequestStepTaxAmountPage({
     );
 }
 
-const DynamicIOURequestStepTaxAmountPageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxAmountPage);
+const IOURequestStepTaxAmountPageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxAmountPage);
 
-const DynamicIOURequestStepTaxAmountPageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(DynamicIOURequestStepTaxAmountPageWithWritableReportOrNotFound);
+const IOURequestStepTaxAmountPageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepTaxAmountPageWithWritableReportOrNotFound);
 
-export default DynamicIOURequestStepTaxAmountPageWithFullTransactionOrNotFound;
+export default IOURequestStepTaxAmountPageWithFullTransactionOrNotFound;
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepTaxRatePage.tsx b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx
similarity index 90%
rename from src/pages/iou/request/step/DynamicIOURequestStepTaxRatePage.tsx
rename to src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx
index 8d954a6f1399..0c464308f063 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepTaxRatePage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx
@@ -4,7 +4,6 @@ import TaxPicker from '@components/TaxPicker';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import usePermissions from '@hooks/usePermissions';
@@ -22,7 +21,6 @@ import {setDraftSplitTransaction} from '@userActions/IOU/Split';
 import {updateMoneyRequestTaxRate} from '@userActions/IOU/UpdateMoneyRequest';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {DYNAMIC_ROUTES} from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Policy, Transaction} from '@src/types/onyx';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
@@ -31,7 +29,7 @@ import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 
-type IOURequestStepTaxRatePageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE> & {
+type IOURequestStepTaxRatePageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_TAX_RATE> & {
     transaction: OnyxEntry<Transaction>;
 };
 
@@ -44,7 +42,7 @@ function getTaxAmount(policy: OnyxEntry<Policy>, transaction: OnyxEntry<Transact
 
 function IOURequestStepTaxRatePage({
     route: {
-        params: {action, iouType, transactionID, reportID: reportIDFromRoute},
+        params: {action, backTo, iouType, transactionID, reportID: reportIDFromRoute},
     },
     transaction,
     report,
@@ -74,10 +72,9 @@ function IOURequestStepTaxRatePage({
     const {policyForMovingExpenses} = usePolicyForMovingExpenses();
     const {isBetaEnabled} = usePermissions();
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_RATE.path);
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     const taxRateTitle = getTaxRateTitle(policy, currentTransaction, isMovingTransactionFromTrackExpense(action), policyForMovingExpenses);
@@ -148,7 +145,7 @@ function IOURequestStepTaxRatePage({
             headerTitle={translate('iou.taxRate')}
             onBackButtonPress={navigateBack}
             shouldShowWrapper
-            testID="DynamicIOURequestStepTaxRatePage"
+            testID="IOURequestStepTaxRatePage"
         >
             <TaxPicker
                 selectedTaxRate={taxRateTitle}
@@ -163,8 +160,8 @@ function IOURequestStepTaxRatePage({
     );
 }
 
-const DynamicIOURequestStepTaxRatePageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxRatePage);
+const IOURequestStepTaxRatePageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxRatePage);
 
-const DynamicIOURequestStepTaxRatePageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(DynamicIOURequestStepTaxRatePageWithWritableReportOrNotFound);
+const IOURequestStepTaxRatePageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepTaxRatePageWithWritableReportOrNotFound);
 
-export default DynamicIOURequestStepTaxRatePageWithFullTransactionOrNotFound;
+export default IOURequestStepTaxRatePageWithFullTransactionOrNotFound;
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx b/src/pages/iou/request/step/IOURequestStepUpgrade.tsx
similarity index 93%
rename from src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx
rename to src/pages/iou/request/step/IOURequestStepUpgrade.tsx
index 1b932707b101..2614106b1ea3 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepUpgrade.tsx
@@ -12,7 +12,6 @@ import type {WorkspaceConfirmationSubmitFunctionParams} from '@components/Worksp
 import useActivePolicy from '@hooks/useActivePolicy';
 import useCreateNewReport from '@hooks/useCreateNewReport';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useHasActiveAdminPolicies from '@hooks/useHasActiveAdminPolicies';
 import useLastWorkspaceNumber from '@hooks/useLastWorkspaceNumber';
 import useLocalize from '@hooks/useLocalize';
@@ -25,7 +24,6 @@ import {createNewReport} from '@libs/actions/Report';
 import {changeTransactionsReport, setTransactionReport} from '@libs/actions/Transaction';
 import type CreateWorkspaceParams from '@libs/API/parameters/CreateWorkspaceParams';
 import getPlatform from '@libs/getPlatform';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import {navigateToCreatedReportInReports} from '@libs/Navigation/helpers/getCreateReportRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
@@ -39,17 +37,17 @@ import CONST from '@src/CONST';
 import * as Policy from '@src/libs/actions/Policy/Policy';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Route} from '@src/ROUTES';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {PersonalDetails, Transaction} from '@src/types/onyx';
 
-type DynamicIOURequestStepUpgradePageProps = PlatformStackScreenProps<MoneyRequestNavigatorParamList, typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE>;
+type IOURequestStepUpgradeProps = PlatformStackScreenProps<MoneyRequestNavigatorParamList, typeof SCREENS.MONEY_REQUEST.STEP_UPGRADE>;
 
-function DynamicIOURequestStepUpgradePage({
+function IOURequestStepUpgrade({
     route: {
-        params: {transactionID, action, reportID, shouldSubmitExpense, upgradePath, iouType},
+        params: {transactionID, action, reportID, shouldSubmitExpense, upgradePath, iouType, backTo},
     },
-}: DynamicIOURequestStepUpgradePageProps) {
+}: IOURequestStepUpgradeProps) {
     const styles = useThemeStyles();
 
     const {translate} = useLocalize();
@@ -59,7 +57,6 @@ function DynamicIOURequestStepUpgradePage({
     const activePolicy = useActivePolicy();
     const hasActiveAdminPolicies = useHasActiveAdminPolicies();
     const lastWorkspaceNumber = useLastWorkspaceNumber();
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.path);
 
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`);
     const [selectedReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
@@ -179,13 +176,13 @@ function DynamicIOURequestStepUpgradePage({
         switch (upgradePath) {
             case CONST.UPGRADE_PATHS.DISTANCE_RATES: {
                 if (!policyID || !reportID) {
-                    Navigation.goBack(backPath);
+                    Navigation.goBack();
                     return;
                 }
 
                 // In case we get here from /:action/track/... route we need to navigate to
                 // /:action/submit/... when shouldSubmitExpense === true as transaction is not selfDM anymore
-                const backToRoute = shouldSubmitExpense ? ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID) : backPath;
+                const backToRoute = shouldSubmitExpense ? ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID) : undefined;
 
                 Navigation.goBack(backToRoute, {compareParams: false});
 
@@ -208,28 +205,28 @@ function DynamicIOURequestStepUpgradePage({
             case CONST.UPGRADE_PATHS.REPORTS:
                 if (action === CONST.IOU.ACTION.CREATE && policyID) {
                     const {reportID: newReportID} = createReportForCurrentUser(policyID);
-                    Navigation.goBack(backPath);
+                    Navigation.goBack();
                     // Wait until the upgrade RHP is closed before opening the created report from Reports.
                     Navigation.setNavigationActionToMicrotaskQueue(() => {
                         navigateToCreatedReportInReports(newReportID);
                     });
                 } else {
-                    Navigation.goBack(backPath);
+                    Navigation.goBack();
                     navigateWithMicrotask(ROUTES.MONEY_REQUEST_STEP_REPORT.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID));
                 }
 
                 break;
             case CONST.UPGRADE_PATHS.CATEGORIES:
-                Navigation.goBack(backPath);
-                navigateWithMicrotask(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID)));
+                Navigation.goBack();
+                navigateWithMicrotask(backTo ?? ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID));
 
                 break;
             default:
-                Navigation.goBack(backPath);
+                Navigation.goBack();
         }
     }, [
         action,
-        backPath,
+        backTo,
         navigateWithMicrotask,
         reportID,
         shouldSubmitExpense,
@@ -334,7 +331,7 @@ function DynamicIOURequestStepUpgradePage({
             {(!!isUpgraded || !showConfirmationForm) && (
                 <HeaderWithBackButton
                     title={translate('common.upgrade')}
-                    onBackButtonPress={() => Navigation.goBack(backPath)}
+                    onBackButtonPress={() => Navigation.goBack()}
                 />
             )}
             {!showConfirmationForm && (
@@ -382,4 +379,4 @@ function DynamicIOURequestStepUpgradePage({
     );
 }
 
-export default DynamicIOURequestStepUpgradePage;
+export default IOURequestStepUpgrade;
diff --git a/src/pages/iou/request/step/IOURequestStepVendor.tsx b/src/pages/iou/request/step/IOURequestStepVendor.tsx
new file mode 100644
index 000000000000..8a8db9f95426
--- /dev/null
+++ b/src/pages/iou/request/step/IOURequestStepVendor.tsx
@@ -0,0 +1,155 @@
+import React, {useState} from 'react';
+import BlockingView from '@components/BlockingViews/BlockingView';
+import SelectionList from '@components/SelectionList';
+import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem';
+import type {ListItem} from '@components/SelectionList/types';
+import useDelegateAccountID from '@hooks/useDelegateAccountID';
+import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import usePermissions from '@hooks/usePermissions';
+import usePolicyForTransaction from '@hooks/usePolicyForTransaction';
+import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {updateMoneyRequestVendor} from '@libs/actions/IOU/UpdateMoneyRequest';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
+import Navigation from '@libs/Navigation/Navigation';
+import {getQBOVendors, hasVendorFeature} from '@libs/PolicyUtils';
+import {isPerDiemRequest} from '@libs/TransactionUtils';
+import variables from '@styles/variables';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type SCREENS from '@src/SCREENS';
+import StepScreenWrapper from './StepScreenWrapper';
+import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound';
+import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
+import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
+import withWritableReportOrNotFound from './withWritableReportOrNotFound';
+
+type VendorListItem = ListItem & {
+    value: string;
+};
+
+type IOURequestStepVendorProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_VENDOR> & WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_VENDOR>;
+
+function IOURequestStepVendor({
+    report,
+    route: {
+        params: {action, iouType, transactionID, reportActionID},
+    },
+    transaction,
+}: IOURequestStepVendorProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const {isBetaEnabled} = usePermissions();
+    const illustrations = useMemoizedLazyIllustrations(['Telescope']);
+    const [searchValue, setSearchValue] = useState('');
+
+    const {policy} = usePolicyForTransaction({
+        transaction,
+        reportPolicyID: report?.policyID,
+        action,
+        iouType,
+        isPerDiemRequest: isPerDiemRequest(transaction),
+    });
+    const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`);
+    const delegateAccountID = useDelegateAccountID();
+
+    const isFeatureAvailable = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING));
+
+    // Vendor is scoped to non-reimbursable expenses on a policy expense chat; block deep-link / stale-open access if the transaction is reimbursable or is an invoice (invoices are non-reimbursable but don't route through the QBO CC vendor-matching flow).
+    const isReimbursable = !!transaction?.reimbursable;
+    const isInvoice = iouType === CONST.IOU.TYPE.INVOICE;
+    const vendors = getQBOVendors(policy);
+    const currentVendorID = transaction?.comment?.vendor?.externalID;
+
+    const trimmedSearch = searchValue.trim().toLowerCase();
+    const vendorRows: VendorListItem[] = vendors
+        .filter((vendor) => !trimmedSearch || vendor.name.toLowerCase().includes(trimmedSearch))
+        .map((vendor) => ({
+            value: vendor.id,
+            text: vendor.name,
+            keyForList: vendor.id,
+            isSelected: vendor.id === currentVendorID,
+            searchText: vendor.name,
+        }));
+
+    // When a vendor is currently set, offer a "None" row so the user can clear a stale (e.g. removed-from-QBO) vendor without picking a replacement, which resolves an inactiveVendor violation. Hidden during search to keep results clean.
+    const data: VendorListItem[] =
+        !currentVendorID || trimmedSearch
+            ? vendorRows
+            : [
+                  {
+                      value: '',
+                      text: translate('common.none'),
+                      keyForList: 'clear-vendor',
+                      isSelected: false,
+                      searchText: '',
+                  },
+                  ...vendorRows,
+              ];
+
+    const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction) || !isFeatureAvailable || isReimbursable || isInvoice;
+
+    const navigateBack = () => {
+        Navigation.goBack();
+    };
+
+    const selectVendor = (item: VendorListItem) => {
+        if (item.value !== currentVendorID) {
+            updateMoneyRequestVendor({
+                transactionID,
+                vendorID: item.value,
+                transaction,
+                transactionThreadReport: report,
+                parentReport,
+                policy,
+                delegateAccountID,
+            });
+        }
+        navigateBack();
+    };
+
+    const headerMessage = searchValue && data.length === 0 ? translate('common.noResultsFound') : '';
+
+    const listEmptyContent =
+        vendors.length === 0 ? (
+            <BlockingView
+                icon={illustrations.Telescope}
+                iconWidth={variables.emptyListIconWidth}
+                iconHeight={variables.emptyListIconHeight}
+                title={translate('workspace.qbo.noAccountsFound')}
+                subtitle={translate('workspace.qbo.noAccountsFoundDescription')}
+                containerStyle={styles.pb10}
+            />
+        ) : null;
+
+    return (
+        <StepScreenWrapper
+            headerTitle={translate('common.vendor')}
+            onBackButtonPress={navigateBack}
+            shouldShowWrapper
+            shouldShowNotFoundPage={shouldShowNotFoundPage}
+            testID="IOURequestStepVendor"
+            includeSafeAreaPaddingBottom
+        >
+            <SelectionList
+                data={data}
+                onSelectRow={selectVendor}
+                textInputOptions={{
+                    label: translate('common.search'),
+                    value: searchValue,
+                    onChangeText: setSearchValue,
+                    headerMessage,
+                }}
+                initiallyFocusedItemKey={data.find((item) => item.isSelected)?.keyForList}
+                ListItem={SingleSelectListItem}
+                shouldShowLoadingPlaceholder={!policy}
+                listEmptyContent={listEmptyContent}
+                shouldSingleExecuteRowSelect
+            />
+        </StepScreenWrapper>
+    );
+}
+
+export default withWritableReportOrNotFound(withFullTransactionOrNotFound(IOURequestStepVendor));
diff --git a/src/pages/iou/request/step/confirmation/ExpenseDefaultsSetter.tsx b/src/pages/iou/request/step/confirmation/ExpenseDefaultsSetter.tsx
index 681da6bd0192..429a4c8c3446 100644
--- a/src/pages/iou/request/step/confirmation/ExpenseDefaultsSetter.tsx
+++ b/src/pages/iou/request/step/confirmation/ExpenseDefaultsSetter.tsx
@@ -1,6 +1,6 @@
 import {useEffect} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
-import {isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {isGroupPolicy} from '@libs/PolicyUtils';
 import {setMoneyRequestBillable, setMoneyRequestReimbursable} from '@userActions/IOU/MoneyRequest';
 import type {Policy} from '@src/types/onyx';
 
@@ -32,7 +32,7 @@ function ExpenseDefaultsSetter({transactionIDs, policy, isPolicyExpenseChat, isM
         if (isMovingTransactionFromTrackExpense) {
             return;
         }
-        const defaultReimbursable = (isPolicyExpenseChat && isPaidGroupPolicy(policy)) || isCreatingTrackExpense ? (policy?.defaultReimbursable ?? true) : true;
+        const defaultReimbursable = (isPolicyExpenseChat && isGroupPolicy(policy)) || isCreatingTrackExpense ? (policy?.defaultReimbursable ?? true) : true;
         for (const transactionID of transactionIDs) {
             setMoneyRequestReimbursable(transactionID, defaultReimbursable);
         }
diff --git a/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts b/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
index 00432c571896..5afb112531b5 100644
--- a/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
+++ b/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
@@ -948,7 +948,7 @@ function useExpenseSubmission(params: UseExpenseSubmissionParams) {
             return;
         }
 
-        if (isPerDiemRequest) {
+        if (isPerDiemRequest && action !== CONST.IOU.ACTION.SUBMIT) {
             submitPerDiemExpense(trimmedComment, shouldHandleNavigation, policyRecentlyUsedCategories);
             markSubmitExpenseEnd();
             return;
diff --git a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx
index 8d72efbdf76e..f15d9426d247 100644
--- a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx
+++ b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx
@@ -32,14 +32,15 @@ type MoneyRequestRouteName =
     | typeof SCREENS.MONEY_REQUEST.STEP_WAYPOINT
     | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION
     | typeof SCREENS.MONEY_REQUEST.STEP_DATE
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT
+    | typeof SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT
     | typeof SCREENS.MONEY_REQUEST.STEP_PARTICIPANTS
     | typeof SCREENS.MONEY_REQUEST.STEP_MERCHANT
     | typeof SCREENS.MONEY_REQUEST.STEP_TAG
     | typeof SCREENS.MONEY_REQUEST.STEP_DISTANCE_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_CONFIRMATION
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE
+    | typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY
+    | typeof SCREENS.MONEY_REQUEST.STEP_TAX_RATE
+    | typeof SCREENS.MONEY_REQUEST.STEP_VENDOR
     | typeof SCREENS.MONEY_REQUEST.STEP_SCAN
     | typeof SCREENS.MONEY_REQUEST.STEP_SEND_FROM
     | typeof SCREENS.MONEY_REQUEST.STEP_REPORT
diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx
index c506e864272e..9b25511beb50 100644
--- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx
+++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx
@@ -28,10 +28,11 @@ type MoneyRequestRouteName =
     | typeof SCREENS.MONEY_REQUEST.STEP_WAYPOINT
     | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION
     | typeof SCREENS.MONEY_REQUEST.STEP_DATE
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY
+    | typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY
+    | typeof SCREENS.MONEY_REQUEST.STEP_VENDOR
     | typeof SCREENS.MONEY_REQUEST.STEP_DISTANCE_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_CONFIRMATION
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE
+    | typeof SCREENS.MONEY_REQUEST.STEP_TAX_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_AMOUNT
     | typeof SCREENS.MONEY_REQUEST.STEP_DISTANCE
     | typeof SCREENS.MONEY_REQUEST.CREATE
@@ -39,14 +40,14 @@ type MoneyRequestRouteName =
     | typeof SCREENS.MONEY_REQUEST.STEP_TAG
     | typeof SCREENS.MONEY_REQUEST.STEP_PARTICIPANTS
     | typeof SCREENS.MONEY_REQUEST.STEP_MERCHANT
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT
+    | typeof SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT
     | typeof SCREENS.MONEY_REQUEST.STEP_SCAN
     | typeof SCREENS.MONEY_REQUEST.STEP_SEND_FROM
     | typeof SCREENS.MONEY_REQUEST.STEP_REPORT
     | typeof SCREENS.MONEY_REQUEST.STEP_COMPANY_INFO
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE
+    | typeof SCREENS.MONEY_REQUEST.STEP_ATTENDEES
+    | typeof SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT
+    | typeof SCREENS.MONEY_REQUEST.STEP_UPGRADE
     | typeof SCREENS.MONEY_REQUEST.STEP_DESTINATION
     | typeof SCREENS.MONEY_REQUEST.STEP_TIME
     | typeof SCREENS.MONEY_REQUEST.STEP_TIME_EDIT
diff --git a/src/pages/settings/Agents/AddAgentPage.tsx b/src/pages/settings/Agents/AddAgentPage.tsx
index 312c6fcd250a..a5d0762418a1 100644
--- a/src/pages/settings/Agents/AddAgentPage.tsx
+++ b/src/pages/settings/Agents/AddAgentPage.tsx
@@ -20,7 +20,7 @@ import {isMobile} from '@libs/Browser';
 import type {CustomRNImageManipulatorResult} from '@libs/cropOrRotateImage/types';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList, WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
+import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import type {AvatarSource} from '@libs/UserAvatarUtils';
 import {createAgent} from '@userActions/Agent';
 import CONST from '@src/CONST';
@@ -31,14 +31,10 @@ import INPUT_IDS from '@src/types/form/AddAgentForm';
 import type {Errors} from '@src/types/onyx/OnyxCommon';
 import {clearPendingAvatar, getPendingAvatar, setInitialPresetID, setNavigationToken, setReturnRoute} from './pendingAgentAvatarStore';
 
-type AddAgentPageProps =
-    | PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.SETTINGS.AGENTS.ADD>
-    | PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT>;
+type AddAgentPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.SETTINGS.AGENTS.ADD>;
 
 function AddAgentPage({route}: AddAgentPageProps) {
     const policyID = route.params?.policyID;
-    const workflowApproverEmail = route.params?.workflowApproverEmail;
-    const isWorkflowSeedFlow = !!policyID && !!workflowApproverEmail;
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const {windowWidth, windowHeight} = useWindowDimensions();
@@ -77,7 +73,7 @@ function AddAgentPage({route}: AddAgentPageProps) {
     const handleAvatarPress = () => {
         setInitialPresetID(selectedPresetID ?? undefined);
         setNavigationToken();
-        setReturnRoute(isWorkflowSeedFlow ? ROUTES.WORKSPACE_WORKFLOWS_ADD_AGENT.getRoute({policyID, workflowApproverEmail}) : ROUTES.SETTINGS_AGENTS_ADD.getRoute());
+        setReturnRoute(ROUTES.SETTINGS_AGENTS_ADD.getRoute());
         Navigation.navigate(ROUTES.SETTINGS_AGENTS_ADD_AVATAR);
     };
 
@@ -97,18 +93,10 @@ function AddAgentPage({route}: AddAgentPageProps) {
         // Pure optimistic flow — no waiting on the server, online or offline. `createAgent`
         // returns the optimistic accountID it wrote into Onyx so we can hand it to the next
         // screen and let it render the agent with opacity until CREATE_AGENT resolves.
-        const {optimisticAccountID} = pendingFile
-            ? createAgent(firstName, prompt, undefined, pendingFile.file, pendingFile.uri, policyID)
-            : createAgent(firstName, prompt, selectedPresetID ?? undefined, undefined, undefined, policyID);
-
-        if (isWorkflowSeedFlow && policyID && workflowApproverEmail) {
-            // Drop the user on the Edit Approvers screen for the workflow they came from, with
-            // the optimistic agent already seeded as approver[0]. The Edit Approvers page reads
-            // the optimistic personal detail by accountID, renders it with reduced opacity
-            // (via `pendingAction`), and reconciles the email/accountID once CREATE_AGENT lands.
-            Navigation.goBack();
-            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, workflowApproverEmail, undefined, Number(optimisticAccountID)));
-            return;
+        if (pendingFile) {
+            createAgent(firstName, prompt, undefined, pendingFile.file, pendingFile.uri, policyID);
+        } else {
+            createAgent(firstName, prompt, selectedPresetID ?? undefined, undefined, undefined, policyID);
         }
 
         Navigation.goBack();
diff --git a/src/pages/settings/Copilot/CopilotPage.tsx b/src/pages/settings/Copilot/CopilotPage.tsx
index fcf9918d0c4b..f92d288e62d4 100644
--- a/src/pages/settings/Copilot/CopilotPage.tsx
+++ b/src/pages/settings/Copilot/CopilotPage.tsx
@@ -4,7 +4,6 @@ import type {RefObject} from 'react';
 import {Dimensions, View} from 'react-native';
 import type {GestureResponderEvent} from 'react-native';
 import Badge from '@components/Badge';
-import Button from '@components/Button';
 import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import {useLockedAccountActions, useLockedAccountState} from '@components/LockedAccountModalProvider';
@@ -28,7 +27,7 @@ import usePersonalDetailsByLogin from '@hooks/usePersonalDetailsByLogin';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useSwitchToDelegator from '@hooks/useSwitchToDelegator';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {clearDelegateErrorsByField, clearDelegatorErrors, openSecuritySettingsPage, removeDelegate} from '@libs/actions/Delegate';
+import {clearDelegateErrorsByField, openSecuritySettingsPage, removeDelegate, removeDelegator} from '@libs/actions/Delegate';
 import {getLatestError} from '@libs/ErrorUtils';
 import getClickedTargetLocation from '@libs/getClickedTargetLocation';
 import Navigation from '@libs/Navigation/Navigation';
@@ -51,7 +50,7 @@ const accountDelegationSelector = (accountValue: Account | undefined) => ({
 });
 
 function CopilotPage() {
-    const icons = useMemoizedLazyExpensifyIcons(['Pencil', 'ThreeDots', 'Trashcan', 'UserPlus']);
+    const icons = useMemoizedLazyExpensifyIcons(['ArrowCircleClockwise', 'CircleSlash', 'Pencil', 'ThreeDots', 'UserPlus']);
     const illustrations = useMemoizedLazyIllustrations(['Copilots', 'Members']);
     const styles = useThemeStyles();
     const {localeCompare, translate, formatPhoneNumber} = useLocalize();
@@ -69,6 +68,8 @@ function CopilotPage() {
     const [shouldShowDelegatePopoverMenu, setShouldShowDelegatePopoverMenu] = useState(false);
     const [selectedDelegate, setSelectedDelegate] = useState<Delegate | undefined>();
     const [selectedEmail, setSelectedEmail] = useState<string | undefined>();
+    const [shouldShowDelegatorPopoverMenu, setShouldShowDelegatorPopoverMenu] = useState(false);
+    const [selectedDelegator, setSelectedDelegator] = useState<Delegate | undefined>();
 
     const {showConfirmModal} = useConfirmModal();
     const showRemoveCopilotModal = useCallback(() => {
@@ -82,6 +83,20 @@ function CopilotPage() {
         });
     }, [showConfirmModal, translate]);
 
+    const showRemoveDelegatorModal = (delegatorEmail: string) => {
+        const personalDetail = personalDetailsByLogin[delegatorEmail.toLowerCase()];
+        const delegatorName = personalDetail?.displayName ?? formatPhoneNumber(delegatorEmail);
+
+        return showConfirmModal({
+            title: translate('delegate.removeCopilotAccessTitle'),
+            prompt: translate('delegate.removeCopilotAccessConfirmation', {delegatorName}),
+            confirmText: translate('delegate.removeCopilotAccessConfirm'),
+            cancelText: translate('common.cancel'),
+            shouldShowCancelButton: true,
+            danger: true,
+        });
+    };
+
     const errorFields = account?.delegatedAccess?.errorFields ?? {};
 
     const [anchorPosition, setAnchorPosition] = useState<AnchorPosition>({
@@ -111,15 +126,19 @@ function CopilotPage() {
         });
     }, [delegateButtonRef]);
 
+    const captureDelegateButtonRef = useCallback((nativeEvent: GestureResponderEvent | KeyboardEvent) => {
+        delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
+    }, []);
+
     const showPopoverMenu = useCallback(
         (nativeEvent: GestureResponderEvent | KeyboardEvent, delegate: Delegate) => {
-            delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
+            captureDelegateButtonRef(nativeEvent);
             setMenuPosition();
             setShouldShowDelegatePopoverMenu(true);
             setSelectedDelegate(delegate);
             setSelectedEmail(delegate.email);
         },
-        [setMenuPosition],
+        [captureDelegateButtonRef, setMenuPosition],
     );
 
     useLayoutEffect(() => {
@@ -135,6 +154,14 @@ function CopilotPage() {
         };
     }, [setMenuPosition]);
 
+    const showDelegatorPopoverMenu = (nativeEvent: GestureResponderEvent | KeyboardEvent, delegator: Delegate) => {
+        captureDelegateButtonRef(nativeEvent);
+        setMenuPosition();
+        setShouldShowDelegatorPopoverMenu(true);
+        setSelectedDelegator(delegator);
+        setSelectedEmail(delegator.email);
+    };
+
     const renderTitleWithRole = useCallback(
         (titleText: string, descriptionText: string, role: DelegateRole | undefined) => (
             <View style={[styles.flexShrink1, styles.ml3]}>
@@ -233,61 +260,46 @@ function CopilotPage() {
         actingDelegateEmail,
     ]);
 
-    const delegatorMenuItems: MenuItemProps[] = useMemo(() => {
-        const sortedDelegators = sortAlphabetically(
-            delegators.map((d) => ({...d, sortKey: personalDetailsByLogin[d.email.toLowerCase()]?.displayName ?? formatPhoneNumber(d.email)})),
-            'sortKey',
-            localeCompare,
-        );
-        return sortedDelegators.map(({email, role, pendingAction}) => {
-            const personalDetail = personalDetailsByLogin[email.toLowerCase()];
-            const formattedEmail = formatPhoneNumber(email);
-            const connectError = getLatestError(errorFields?.connect?.[email]);
-            const isCurrentUser = email === session?.email;
-            const isPending = !!pendingAction;
-            const titleText = personalDetail?.displayName ?? formattedEmail;
-            const descriptionText = personalDetail?.displayName ? formattedEmail : '';
-
-            return {
-                key: email,
-                titleComponent: renderTitleWithRole(titleText, descriptionText, role),
-                avatarID: personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID,
-                icon: personalDetail?.avatar ?? (personalDetail ? getDefaultAvatarURL({accountID: personalDetail.accountID, accountEmail: email}) : undefined),
-                iconType: CONST.ICON_TYPE_AVATAR,
-                wrapperStyle: [styles.sectionMenuItemTopDescription],
-                disabled: isPending || isCurrentUser,
-                onPress: () => switchToDelegator(email),
-                role: CONST.ROLE.LINK,
-                error: connectError,
-                onPendingActionDismiss: () => clearDelegatorErrors({delegatedAccess: account?.delegatedAccess}),
-                shouldShowRightComponent: true,
-                rightComponent: (
-                    <View style={[styles.ml2, styles.alignSelfCenter]}>
-                        <Button
-                            small
-                            success
-                            text={translate('delegate.switch')}
-                            isDisabled={isPending || isCurrentUser}
-                            onPress={() => switchToDelegator(email)}
-                            sentryLabel={CONST.SENTRY_LABEL.ACCOUNT_SWITCHER.SHOW_ACCOUNTS}
-                        />
-                    </View>
-                ),
-            };
-        });
-    }, [
-        delegators,
-        styles,
-        translate,
-        formatPhoneNumber,
-        account?.delegatedAccess,
-        personalDetailsByLogin,
+    const sortedDelegators = sortAlphabetically(
+        delegators.map((d) => ({...d, sortKey: personalDetailsByLogin[d.email.toLowerCase()]?.displayName ?? formatPhoneNumber(d.email)})),
+        'sortKey',
         localeCompare,
-        session?.email,
-        errorFields,
-        switchToDelegator,
-        renderTitleWithRole,
-    ]);
+    );
+    const delegatorMenuItems: MenuItemProps[] = sortedDelegators.map(({email, role, pendingAction}) => {
+        const personalDetail = personalDetailsByLogin[email.toLowerCase()];
+        const formattedEmail = formatPhoneNumber(email);
+        const connectError = getLatestError(errorFields?.connect?.[email]);
+        const removeDelegatorError = getLatestError(errorFields?.removeDelegator?.[email]);
+        const error = getLatestError({...connectError, ...removeDelegatorError});
+        const isCurrentUser = email === session?.email;
+        const isPending = !!pendingAction;
+        const titleText = personalDetail?.displayName ?? formattedEmail;
+        const descriptionText = personalDetail?.displayName ? formattedEmail : '';
+
+        return {
+            key: email,
+            titleComponent: renderTitleWithRole(titleText, descriptionText, role),
+            avatarID: personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID,
+            icon: personalDetail?.avatar ?? (personalDetail ? getDefaultAvatarURL({accountID: personalDetail.accountID, accountEmail: email}) : undefined),
+            iconType: CONST.ICON_TYPE_AVATAR,
+            wrapperStyle: [styles.sectionMenuItemTopDescription],
+            disabled: isPending || isCurrentUser,
+            onPress: (e: GestureResponderEvent | KeyboardEvent) => {
+                showDelegatorPopoverMenu(e, {email, role});
+            },
+            pendingAction,
+            shouldForceOpacity: !!pendingAction,
+            error,
+            onPendingActionDismiss: () => {
+                clearDelegateErrorsByField({email, fieldName: 'connect', delegatedAccess: account?.delegatedAccess});
+                clearDelegateErrorsByField({email, fieldName: 'removeDelegator', delegatedAccess: account?.delegatedAccess});
+            },
+            iconRight: icons.ThreeDots,
+            shouldShowRightIcon: !isCurrentUser,
+            success: selectedEmail === email,
+            sentryLabel: CONST.SENTRY_LABEL.SETTINGS_SECURITY.DELEGATOR_ITEM,
+        };
+    });
 
     const delegatePopoverMenuItems: PopoverMenuItem[] = [
         {
@@ -311,7 +323,7 @@ function CopilotPage() {
         },
         {
             text: translate('delegate.removeCopilot'),
-            icon: icons.Trashcan,
+            icon: icons.CircleSlash,
             sentryLabel: CONST.SENTRY_LABEL.SETTINGS_SECURITY.DELEGATE_REMOVE,
             onPress: () => {
                 if (selectedDelegate?.email !== account?.delegatedAccess?.delegate && isActingAsDelegate) {
@@ -342,10 +354,45 @@ function CopilotPage() {
         },
     ];
 
+    const delegatorPopoverMenuItems: PopoverMenuItem[] = [
+        {
+            text: translate('delegate.switch'),
+            icon: icons.ArrowCircleClockwise,
+            sentryLabel: CONST.SENTRY_LABEL.ACCOUNT_SWITCHER.SHOW_ACCOUNTS,
+            onPress: () => {
+                setShouldShowDelegatorPopoverMenu(false);
+                setSelectedDelegator(undefined);
+                setSelectedEmail(undefined);
+                switchToDelegator(selectedDelegator?.email ?? '');
+            },
+        },
+        {
+            text: translate('delegate.removeCopilotAccess'),
+            icon: icons.CircleSlash,
+            sentryLabel: CONST.SENTRY_LABEL.SETTINGS_SECURITY.DELEGATOR_REMOVE,
+            onPress: () => {
+                modalClose(() => {
+                    setShouldShowDelegatorPopoverMenu(false);
+                    setSelectedEmail(undefined);
+                    showRemoveDelegatorModal(selectedDelegator?.email ?? '').then((result) => {
+                        if (result.action === ModalActions.CLOSE) {
+                            setSelectedDelegator(undefined);
+                        } else {
+                            removeDelegator({email: selectedDelegator?.email ?? '', delegatedAccess: account?.delegatedAccess});
+                            setSelectedDelegator(undefined);
+                        }
+                    });
+                });
+            },
+        },
+    ];
+
     useEffect(() => {
         openSecuritySettingsPage();
     }, []);
 
+    const delegateAnchorRef = delegateButtonRef as RefObject<View | null>;
+
     return (
         <ScreenWrapper
             testID="CopilotPage"
@@ -428,7 +475,7 @@ function CopilotPage() {
                             </Section>
                             <PopoverMenu
                                 isVisible={shouldShowDelegatePopoverMenu}
-                                anchorRef={delegateButtonRef as RefObject<View | null>}
+                                anchorRef={delegateAnchorRef}
                                 anchorPosition={anchorPosition}
                                 anchorAlignment={{
                                     horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT,
@@ -440,6 +487,20 @@ function CopilotPage() {
                                     setSelectedEmail(undefined);
                                 }}
                             />
+                            <PopoverMenu
+                                isVisible={shouldShowDelegatorPopoverMenu}
+                                anchorRef={delegateAnchorRef}
+                                anchorPosition={anchorPosition}
+                                anchorAlignment={{
+                                    horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT,
+                                    vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP,
+                                }}
+                                menuItems={delegatorPopoverMenuItems}
+                                onClose={() => {
+                                    setShouldShowDelegatorPopoverMenu(false);
+                                    setSelectedEmail(undefined);
+                                }}
+                            />
                         </View>
                     </ScrollView>
                 </>
diff --git a/src/pages/settings/Security/LockAccount/LockAccountPage.tsx b/src/pages/settings/Security/LockAccount/LockAccountPage.tsx
index 8bfee04743fd..459c8bb349d9 100644
--- a/src/pages/settings/Security/LockAccount/LockAccountPage.tsx
+++ b/src/pages/settings/Security/LockAccount/LockAccountPage.tsx
@@ -1,4 +1,6 @@
 import React from 'react';
+import {View} from 'react-native';
+import RenderHTML from '@components/RenderHTML';
 import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -31,10 +33,20 @@ function LockAccountPage() {
     );
 
     const lockAccountPagePrompt = (
-        <>
-            <Text>{translate('lockAccountPage.compromisedDescription')}</Text>
-            <Text>{translate('lockAccountPage.domainAdminsDescription')}</Text>
-        </>
+        <View style={[styles.renderHTML, styles.gap4]}>
+            <View>
+                <RenderHTML html={translate('lockAccountPage.findYourSituation')} />
+            </View>
+            <View>
+                <RenderHTML html={translate('lockAccountPage.lostCardOrCharges')} />
+            </View>
+            <View>
+                <RenderHTML html={translate('lockAccountPage.unauthorizedAccess')} />
+            </View>
+            <View>
+                <RenderHTML html={translate('lockAccountPage.securityTeamFollowUp')} />
+            </View>
+        </View>
     );
 
     return (
@@ -43,6 +55,7 @@ function LockAccountPage() {
             onBackButtonPress={() => Navigation.goBack()}
             confirmModalPrompt={confirmModalPrompt}
             lockAccountPagePrompt={lockAccountPagePrompt}
+            lockButtonText={translate('lockAccountPage.lockMyAccount')}
             handleLockRequestFinish={handleLockRequestFinish}
         />
     );
diff --git a/src/pages/settings/Security/LockAccount/LockAccountPageBase.tsx b/src/pages/settings/Security/LockAccount/LockAccountPageBase.tsx
index 517746ad183a..bcd062ee8060 100644
--- a/src/pages/settings/Security/LockAccount/LockAccountPageBase.tsx
+++ b/src/pages/settings/Security/LockAccount/LockAccountPageBase.tsx
@@ -21,6 +21,7 @@ type BaseLockAccountComponentProps = {
     domainAccountID?: number;
     domainName?: string;
     accountID?: number;
+    lockButtonText?: string;
 };
 function LockAccountPageBase({
     confirmModalPrompt,
@@ -31,6 +32,7 @@ function LockAccountPageBase({
     domainAccountID,
     domainName,
     accountID,
+    lockButtonText,
 }: BaseLockAccountComponentProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
@@ -72,7 +74,7 @@ function LockAccountPageBase({
             isLoading={isLoading}
             isDisabled={isOffline}
             large
-            text={translate('lockAccountPage.reportSuspiciousActivity')}
+            text={lockButtonText ?? translate('lockAccountPage.reportSuspiciousActivity')}
             style={styles.mt6}
             pressOnEnter
             onPress={handleReportSuspiciousActivity}
diff --git a/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx b/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
index 7935ea811a28..76ec108f8d55 100644
--- a/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
+++ b/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
@@ -22,7 +22,6 @@ import ScrollView from '@components/ScrollView';
 import Text from '@components/Text';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
-import useEnvironment from '@hooks/useEnvironment';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
@@ -90,7 +89,6 @@ function getLimitTypeTranslationKeys(limitType: ValueOf<typeof CONST.EXPENSIFY_C
 }
 
 function ExpensifyCardPage({route}: ExpensifyCardPageProps) {
-    const {isProduction} = useEnvironment();
     const {cardID} = route.params;
     const {convertToDisplayString} = useCurrencyListActions();
     const [account] = useOnyx(ONYXKEYS.ACCOUNT);
@@ -211,8 +209,8 @@ function ExpensifyCardPage({route}: ExpensifyCardPageProps) {
     );
     const shouldShowReportVirtualCardFraudRows = !isSignedInAsDelegate && virtualCards.length > 0;
     const shouldShowReportTravelCardFraudRows = !isSignedInAsDelegate && isTravelCard(cardList?.[cardID]) && travelCards.length > 0;
-    const shouldShowSpendRulesSummary = !isProduction && isWorkspaceAdmin && spendRulesSummary.length > 0;
-    const shouldShowEditSpendRules = !isProduction && isWorkspaceAdmin;
+    const shouldShowEditSpendRules = isWorkspaceAdmin;
+    const shouldShowSpendRulesSummary = isWorkspaceAdmin && spendRulesSummary.length > 0;
     const shouldShowActionRows =
         shouldShowReportVirtualCardFraudRows || shouldShowReportTravelCardFraudRows || shouldShowReportLostCardButton || shouldShowSpendRulesSummary || shouldShowEditSpendRules;
     const shouldShowPhysicalCardFooterButton =
diff --git a/src/pages/workspace/AccessOrNotFoundWrapper.tsx b/src/pages/workspace/AccessOrNotFoundWrapper.tsx
index 0fa296a87b49..7284fc46f81f 100644
--- a/src/pages/workspace/AccessOrNotFoundWrapper.tsx
+++ b/src/pages/workspace/AccessOrNotFoundWrapper.tsx
@@ -18,13 +18,14 @@ import Navigation from '@libs/Navigation/Navigation';
 import {
     canEditWorkspaceSettings,
     canMemberRead,
+    canMemberWrite,
     canSendInvoice,
     isControlPolicy,
     isGroupPolicy,
     isPolicyAccessible,
     isPolicyFeatureEnabled as isPolicyFeatureEnabledUtil,
 } from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
+import type {PolicyFeature, PolicyFeatureAccess} from '@libs/PolicyUtils';
 import {canCreateRequest} from '@libs/ReportUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
@@ -105,6 +106,9 @@ type AccessOrNotFoundWrapperProps = {
     /** Policy feature permission needed to access the page */
     policyFeature?: PolicyFeature;
 
+    /** Required policy feature access level */
+    policyFeatureAccess?: PolicyFeatureAccess;
+
     /** Props for customizing fallback pages */
     fullPageNotFoundViewProps?: FullPageNotFoundViewProps;
 
@@ -154,6 +158,7 @@ function AccessOrNotFoundWrapper({
     allPolicies,
     featureName,
     policyFeature,
+    policyFeatureAccess = CONST.POLICY.POLICY_FEATURE_ACCESS.READ,
     ...props
 }: AccessOrNotFoundWrapperProps) {
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
@@ -197,7 +202,8 @@ function AccessOrNotFoundWrapper({
     }, true);
     let hasAccessToPolicyFeature = true;
     if (policyFeature) {
-        hasAccessToPolicyFeature = canMemberRead(policy, login, policyFeature);
+        hasAccessToPolicyFeature =
+            policyFeatureAccess === CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE ? canMemberWrite(policy, login, policyFeature) : canMemberRead(policy, login, policyFeature);
     }
 
     const isPolicyNotAccessible = !isPolicyAccessible(policy, login);
@@ -206,6 +212,7 @@ function AccessOrNotFoundWrapper({
     //  - workspace central-pane usages where an RHP overlay makes `isFocused` false but the Workspaces tab is still active.
     const shouldShowNotFoundPage =
         (isFocused || isWorkspacesTabFocused) && ((!isMoneyRequest && !isFromGlobalCreate && isPolicyNotAccessible) || !isPageAccessible || !hasAccessToPolicyFeature || shouldBeBlocked);
+
     // We only update the feature state if it isn't pending.
     // This is because the feature state changes several times during the creation of a workspace, while we are waiting for a response from the backend.
     // Without this, we can be unexpectedly navigated to the More Features page.
diff --git a/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx
index ab01c80178b9..9481aba9e13d 100644
--- a/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx
+++ b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx
@@ -9,6 +9,8 @@ import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {isBankAccountPartiallySetup} from '@libs/BankAccountUtils';
+import {REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
+import {appendParam} from '@libs/Url';
 import Navigation from '@navigation/Navigation';
 import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
 import type {ConnectExistingBankAccountNavigatorParamList} from '@navigation/types';
@@ -19,6 +21,7 @@ import {setWorkspaceReimbursement} from '@userActions/Policy/Policy';
 import {navigateToBankAccountRoute} from '@userActions/ReimbursementAccount';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 
 type ConnectExistingBusinessBankAccountPageProps = PlatformStackScreenProps<ConnectExistingBankAccountNavigatorParamList, typeof SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT>;
@@ -38,7 +41,10 @@ function ConnectExistingBusinessBankAccountPage({route}: ConnectExistingBusiness
     const {translate} = useLocalize();
 
     const handleAddBankAccountPress = () => {
-        navigateToBankAccountRoute({policyID, backTo});
+        setReimbursementAccountLoading(true);
+        Navigation.setNavigationActionToMicrotaskQueue(() => {
+            Navigation.navigate(appendParam(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID, backTo}), 'stepToOpen', REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW));
+        });
     };
 
     const handleItemPress = ({methodID, accountData}: PaymentMethodPressHandlerParams) => {
diff --git a/src/pages/workspace/MemberRightIcon.tsx b/src/pages/workspace/MemberRightIcon.tsx
index 6c9971182ffd..18e5b480f54a 100644
--- a/src/pages/workspace/MemberRightIcon.tsx
+++ b/src/pages/workspace/MemberRightIcon.tsx
@@ -5,7 +5,6 @@ import {useListItemFocus} from '@components/SelectionList/ListItemFocusContext';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import CONST from '@src/CONST';
-import type {TranslationPaths} from '@src/languages/types';
 
 type MemberRightIconProps = {
     owner?: string;
@@ -19,20 +18,18 @@ export default function MemberRightIcon({role, owner, login, badgeStyles}: Membe
     const styles = useThemeStyles();
     const {isFocused} = useListItemFocus();
 
-    let badgeText: TranslationPaths | undefined;
+    let badgeText = '';
     if (owner && owner === login) {
-        badgeText = 'common.owner';
-    } else if (role === CONST.POLICY.ROLE.ADMIN) {
-        badgeText = 'common.admin';
-    } else if (role === CONST.POLICY.ROLE.AUDITOR) {
-        badgeText = 'common.auditor';
+        badgeText = translate('common.owner');
+    } else if (role === CONST.POLICY.ROLE.ADMIN || role === CONST.POLICY.ROLE.AUDITOR || role === CONST.POLICY.ROLE.CARD_ADMIN) {
+        badgeText = translate('workspace.common.roleName', role);
     } else if (role === CONST.POLICY.ROLE.EDITOR) {
-        badgeText = 'common.editor';
+        badgeText = translate('common.editor');
     }
     if (badgeText) {
         return (
             <Badge
-                text={translate(badgeText)}
+                text={badgeText}
                 badgeStyles={[isFocused && styles.badgeDefaultActive, badgeStyles]}
             />
         );
diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx
index 76f45353a2b6..fe7cf1381ef8 100644
--- a/src/pages/workspace/WorkspaceMembersPage.tsx
+++ b/src/pages/workspace/WorkspaceMembersPage.tsx
@@ -68,6 +68,7 @@ import {isPersonalDetailsReady, sortAlphabetically} from '@libs/OptionsListUtils
 import {getDisplayNameOrDefault, getPersonalDetailsByID} from '@libs/PersonalDetailsUtils';
 import {
     canEditWorkspaceSettings,
+    canMemberWrite,
     getConnectionExporters,
     getMemberAccountIDsForWorkspace,
     isControlPolicy,
@@ -116,6 +117,7 @@ type MemberOption = Omit<ListItem, 'accountID' | 'login'> & {
 const WORKSPACE_MEMBER_FILTER_VALUES = {
     ALL: 'all',
     ADMINS: 'admins',
+    CARD_ADMINS: 'cardAdmins',
     APPROVERS: 'approvers',
     AUDITORS: 'auditors',
 } as const;
@@ -414,6 +416,7 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
 
     const policyOwner = policy?.owner;
     const currentUserLogin = currentUserPersonalDetails.login;
+    const canAssignElevatedRoles = canMemberWrite(policy, currentUserLogin ?? '', CONST.POLICY.POLICY_FEATURE.ASSIGN_ELEVATED_ROLES);
     const invitedPrimaryToSecondaryLogins = useMemo(() => invertObject(policy?.primaryLoginsInvited ?? {}), [policy?.primaryLoginsInvited]);
     const isControlPolicyWithWideLayout = !shouldUseNarrowLayout && isControlPolicy(policy);
 
@@ -459,10 +462,8 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
             let roleBadgeText = '';
             if (policy?.owner === details.login) {
                 roleBadgeText = translate('common.owner');
-            } else if (policyEmployee.role === CONST.POLICY.ROLE.ADMIN) {
-                roleBadgeText = translate('common.admin');
-            } else if (policyEmployee.role === CONST.POLICY.ROLE.AUDITOR) {
-                roleBadgeText = translate('common.auditor');
+            } else if (policyEmployee.role === CONST.POLICY.ROLE.ADMIN || policyEmployee.role === CONST.POLICY.ROLE.AUDITOR || policyEmployee.role === CONST.POLICY.ROLE.CARD_ADMIN) {
+                roleBadgeText = translate('workspace.common.roleName', policyEmployee.role);
             } else if (policyEmployee.role === CONST.POLICY.ROLE.EDITOR) {
                 roleBadgeText = translate('common.editor');
             }
@@ -568,6 +569,11 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
     ];
 
     if (isControlPolicy(policy)) {
+        roleFilterOptions.push({
+            text: translate('workspace.people.cardAdmins'),
+            value: WORKSPACE_MEMBER_FILTER_VALUES.CARD_ADMINS,
+        });
+
         roleFilterOptions.push({
             text: translate('workspace.people.auditors'),
             value: WORKSPACE_MEMBER_FILTER_VALUES.AUDITORS,
@@ -597,6 +603,8 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
                 return member.login === policy?.owner || employee?.role === CONST.POLICY.ROLE.ADMIN;
             case WORKSPACE_MEMBER_FILTER_VALUES.APPROVERS:
                 return isPolicyApprover(policy, member.login);
+            case WORKSPACE_MEMBER_FILTER_VALUES.CARD_ADMINS:
+                return employee?.role === CONST.POLICY.ROLE.CARD_ADMIN;
             case WORKSPACE_MEMBER_FILTER_VALUES.AUDITORS:
                 return employee?.role === CONST.POLICY.ROLE.AUDITOR;
             default:
@@ -828,8 +836,15 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
             icon: icons.UserEye,
             onSelected: () => changeUserRole(CONST.POLICY.ROLE.AUDITOR),
         };
+        const cardAdminOption = {
+            text: translate('workspace.people.makeCardAdmin', {count: selectedEmployees.length}),
+            value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_CARD_ADMIN,
+            icon: icons.MakeAdmin,
+            onSelected: () => changeUserRole(CONST.POLICY.ROLE.CARD_ADMIN),
+        };
 
         const hasAtLeastOneNonAuditorRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.AUDITOR);
+        const hasAtLeastOneNonCardAdminRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.CARD_ADMIN);
         const hasAtLeastOneNonMemberRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.USER);
         const hasAtLeastOneNonAdminRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.ADMIN);
         const isReimbursementEnabled = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES;
@@ -839,14 +854,18 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
             options.push(memberOption);
         }
 
-        if (hasAtLeastOneNonAdminRole) {
+        if (hasAtLeastOneNonAdminRole && canAssignElevatedRoles) {
             options.push(adminOption);
         }
 
-        if (hasAtLeastOneNonAuditorRole && isControlPolicy(policy) && !hasAtLeastOnePayer) {
+        if (hasAtLeastOneNonAuditorRole && isControlPolicy(policy) && !hasAtLeastOnePayer && canAssignElevatedRoles) {
             options.push(auditorOption);
         }
 
+        if (hasAtLeastOneNonCardAdminRole && isControlPolicy(policy) && !hasAtLeastOnePayer && canAssignElevatedRoles) {
+            options.push(cardAdminOption);
+        }
+
         return options;
     };
 
diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx
index 25c7633b29d0..cc656814e44e 100644
--- a/src/pages/workspace/WorkspacePageWithSections.tsx
+++ b/src/pages/workspace/WorkspacePageWithSections.tsx
@@ -1,5 +1,4 @@
 import {useIsFocused} from '@react-navigation/native';
-import {emailSelector} from '@selectors/Session';
 import type {ReactNode} from 'react';
 import React, {useEffect, useMemo} from 'react';
 import {View} from 'react-native';
@@ -11,6 +10,7 @@ import type HeaderWithBackButtonProps from '@components/HeaderWithBackButton/typ
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollViewWithContext from '@components/ScrollViewWithContext';
 import useAndroidBackButtonHandler from '@hooks/useAndroidBackButtonHandler';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useIsWorkspacesTabFocused from '@hooks/useIsWorkspacesTabFocused';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
@@ -146,9 +146,7 @@ function WorkspacePageWithSections({
 
     const [account] = useOnyx(ONYXKEYS.ACCOUNT);
     const [reimbursementAccount = CONST.REIMBURSEMENT_ACCOUNT.DEFAULT_DATA] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
-    const [currentUserLogin] = useOnyx(ONYXKEYS.SESSION, {
-        selector: emailSelector,
-    });
+    const {login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
 
     const isLoading = isPageLoading ? true : !shouldSkipVBBACall && (reimbursementAccount?.isLoading ?? false);
     const isUsingECard = account?.isUsingExpensifyCard ?? false;
@@ -188,7 +186,8 @@ function WorkspacePageWithSections({
         // We check isPendingDelete and prevIsPendingDelete to prevent the NotFound view from showing right after we delete the workspace
         const canShowPage = hasAccessToPolicyFeature ?? (canEditWorkspaceSettings(policy, currentUserLogin) || shouldShowNonAdmin);
 
-        return (!isEmptyObject(policy) && !canShowPage) || (!shouldShowPolicy && !(isPendingDelete && !prevIsPendingDelete));
+        const shouldShowPolicyOrFeature = hasAccessToPolicyFeature ?? shouldShowPolicy;
+        return (!isEmptyObject(policy) && !canShowPage) || (!shouldShowPolicyOrFeature && !(isPendingDelete && !prevIsPendingDelete));
         // eslint-disable-next-line react-hooks/exhaustive-deps
     }, [currentUserLogin, hasAccessToPolicyFeature, isWorkspacesTabFocused, policy, shouldShowNonAdmin, shouldShowPolicy]);
 
diff --git a/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx b/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx
new file mode 100644
index 000000000000..ba5040f385ab
--- /dev/null
+++ b/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+
+// Scaffolding placeholder for Release 2 (SRP). The full Company selector UI is implemented in a follow-up issue.
+function CertiniaCompanySelectorPage() {
+    return <NotFoundPage />;
+}
+
+CertiniaCompanySelectorPage.displayName = 'CertiniaCompanySelectorPage';
+
+export default CertiniaCompanySelectorPage;
diff --git a/src/pages/workspace/accounting/certinia/CertiniaPrerequisitesPage.tsx b/src/pages/workspace/accounting/certinia/CertiniaPrerequisitesPage.tsx
index 25dec349ecf4..e450a9aee963 100644
--- a/src/pages/workspace/accounting/certinia/CertiniaPrerequisitesPage.tsx
+++ b/src/pages/workspace/accounting/certinia/CertiniaPrerequisitesPage.tsx
@@ -3,6 +3,7 @@ import {View} from 'react-native';
 import ConnectionLayout from '@components/ConnectionLayout';
 import InteractiveStepSubPageHeader from '@components/InteractiveStepSubPageHeader';
 import useEnvironment from '@hooks/useEnvironment';
+import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useSubPage from '@hooks/useSubPage';
 import type {SubPageProps} from '@hooks/useSubPage/types';
@@ -32,6 +33,7 @@ const pages = [
 
 function CertiniaPrerequisitesPage({route}: CertiniaPrerequisitesPageProps) {
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const {environmentURL} = useEnvironment();
     const policyID: string = route.params.policyID;
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);
@@ -76,6 +78,7 @@ function CertiniaPrerequisitesPage({route}: CertiniaPrerequisitesPageProps) {
                 <InteractiveStepSubPageHeader
                     currentStepIndex={pageIndex}
                     stepNames={CONST.CERTINIA_PREREQUISITES.STEP_INDEX_LIST}
+                    currentStepAccessibilityDescription={translate('workspace.certinia.prerequisites.title')}
                     onStepSelected={moveTo}
                 />
             </View>
diff --git a/src/pages/workspace/accounting/certinia/export/CertiniaReportExportStatusPage.tsx b/src/pages/workspace/accounting/certinia/export/CertiniaReportExportStatusPage.tsx
new file mode 100644
index 000000000000..a9b696741dad
--- /dev/null
+++ b/src/pages/workspace/accounting/certinia/export/CertiniaReportExportStatusPage.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+
+// Scaffolding placeholder for Release 2 (PSA). The full Expense Report Status selection UI is implemented in a follow-up issue.
+function CertiniaReportExportStatusPage() {
+    return <NotFoundPage />;
+}
+
+CertiniaReportExportStatusPage.displayName = 'CertiniaReportExportStatusPage';
+
+export default CertiniaReportExportStatusPage;
diff --git a/src/pages/workspace/accounting/certinia/import/CertiniaTagsMappingPage.tsx b/src/pages/workspace/accounting/certinia/import/CertiniaTagsMappingPage.tsx
new file mode 100644
index 000000000000..be1ca996d4d7
--- /dev/null
+++ b/src/pages/workspace/accounting/certinia/import/CertiniaTagsMappingPage.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+
+// Scaffolding placeholder for Release 2 (PSA). The full Tags Mapping selection UI is implemented in a follow-up issue.
+function CertiniaTagsMappingPage() {
+    return <NotFoundPage />;
+}
+
+CertiniaTagsMappingPage.displayName = 'CertiniaTagsMappingPage';
+
+export default CertiniaTagsMappingPage;
diff --git a/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/NetSuiteTokenInputPage.tsx b/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/NetSuiteTokenInputPage.tsx
index d07b29ebea61..0171a70b653f 100644
--- a/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/NetSuiteTokenInputPage.tsx
+++ b/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/NetSuiteTokenInputPage.tsx
@@ -2,6 +2,7 @@ import React from 'react';
 import {View} from 'react-native';
 import ConnectionLayout from '@components/ConnectionLayout';
 import InteractiveStepSubPageHeader from '@components/InteractiveStepSubPageHeader';
+import useLocalize from '@hooks/useLocalize';
 import useSubPage from '@hooks/useSubPage';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {isAuthenticationError} from '@libs/actions/connections';
@@ -26,6 +27,7 @@ const pages = [
 function NetSuiteTokenInputPage({policy, route}: WithPolicyConnectionsProps) {
     const policyID = policy?.id;
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
 
     const hasAuthError = isAuthenticationError(policy, CONST.POLICY.CONNECTIONS.NAME.NETSUITE);
 
@@ -68,6 +70,7 @@ function NetSuiteTokenInputPage({policy, route}: WithPolicyConnectionsProps) {
                 <InteractiveStepSubPageHeader
                     currentStepIndex={pageIndex}
                     stepNames={CONST.NETSUITE_CONFIG.TOKEN_INPUT.STEP_INDEX_LIST}
+                    currentStepAccessibilityDescription={translate('workspace.netsuite.tokenInput.title')}
                     onStepSelected={moveTo}
                 />
             </View>
diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListContent.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListContent.tsx
index 36e506de2158..a2d43329f30c 100644
--- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListContent.tsx
+++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListContent.tsx
@@ -6,6 +6,7 @@ import type {FormRef} from '@components/Form/types';
 import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import InteractiveStepSubPageHeader from '@components/InteractiveStepSubPageHeader';
 import ScreenWrapper from '@components/ScreenWrapper';
+import useLocalize from '@hooks/useLocalize';
 import useSubPage from '@hooks/useSubPage';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
@@ -41,6 +42,7 @@ const pages = [
 function NetSuiteImportAddCustomListContent({policy, draftValues, policyIDParam}: NetSuiteImportAddCustomListContentProps) {
     const policyID = policy?.id;
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const formRef = useRef<FormRef | null>(null);
 
     const values = useMemo(() => getSubstepValues(draftValues), [draftValues]);
@@ -129,6 +131,7 @@ function NetSuiteImportAddCustomListContent({policy, draftValues, policyIDParam}
                 <InteractiveStepSubPageHeader
                     currentStepIndex={pageIndex}
                     stepNames={CONST.NETSUITE_CONFIG.NETSUITE_ADD_CUSTOM_LIST.STEP_INDEX_LIST}
+                    currentStepAccessibilityDescription={translate('workspace.netsuite.import.importCustomFields.customLists.addText')}
                 />
             </View>
             <View style={[styles.flexGrow1, styles.mt3]}>
diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomSegmentContent.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomSegmentContent.tsx
index e6043b41daf3..3e926d684768 100644
--- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomSegmentContent.tsx
+++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomSegmentContent.tsx
@@ -7,6 +7,7 @@ import type {FormRef} from '@components/Form/types';
 import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import InteractiveStepSubPageHeader from '@components/InteractiveStepSubPageHeader';
 import ScreenWrapper from '@components/ScreenWrapper';
+import useLocalize from '@hooks/useLocalize';
 import useSubPage from '@hooks/useSubPage';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
@@ -46,6 +47,7 @@ const pages = [
 function NetSuiteImportAddCustomSegmentContent({policy, policyIDParam, draftValues}: NetSuiteImportAddCustomSegmentContentProps) {
     const policyID = policy?.id;
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const formRef = useRef<FormRef | null>(null);
 
     const config = policy?.connections?.netsuite?.options?.config;
@@ -117,10 +119,12 @@ function NetSuiteImportAddCustomSegmentContent({policy, policyIDParam, draftValu
         );
     }
 
+    const headerTitle = `workspace.netsuite.import.importCustomFields.customSegments.${customSegmentType ? `addForm.${customSegmentType}AddTitle` : 'addText'}` as TranslationPaths;
+
     return (
         <ConnectionLayout
             displayName="NetSuiteImportAddCustomSegmentContent"
-            headerTitle={`workspace.netsuite.import.importCustomFields.customSegments.${customSegmentType ? `addForm.${customSegmentType}AddTitle` : 'addText'}` as TranslationPaths}
+            headerTitle={headerTitle}
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED}
@@ -134,6 +138,7 @@ function NetSuiteImportAddCustomSegmentContent({policy, policyIDParam, draftValu
                 <InteractiveStepSubPageHeader
                     currentStepIndex={pageIndex}
                     stepNames={CONST.NETSUITE_CONFIG.NETSUITE_ADD_CUSTOM_SEGMENT.STEP_INDEX_LIST}
+                    currentStepAccessibilityDescription={translate(headerTitle)}
                 />
             </View>
             <View style={[styles.flex1, styles.mt3]}>
diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx
index 3e5e4626d8a8..c0a611a302f3 100644
--- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx
+++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx
@@ -564,14 +564,6 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) {
     const isLoading = !isOffline && policyCategories === undefined;
     const reasonAttributes: SkeletonSpanReasonAttributes = {context: 'WorkspaceCategoriesPage', isOffline, isPolicyCategoriesUndefined: policyCategories === undefined};
 
-    useEffect(() => {
-        if (isMobileSelectionModeEnabled) {
-            return;
-        }
-
-        clearTableSelection();
-    }, [clearTableSelection, isMobileSelectionModeEnabled]);
-
     const selectionModeHeader = isMobileSelectionModeEnabled && shouldUseNarrowLayout;
 
     const headerContent = (
diff --git a/src/pages/workspace/companyCards/BrokenCardFeedConnectionPage.tsx b/src/pages/workspace/companyCards/BrokenCardFeedConnectionPage.tsx
index 9f0521319dbb..07cd89160dcc 100644
--- a/src/pages/workspace/companyCards/BrokenCardFeedConnectionPage.tsx
+++ b/src/pages/workspace/companyCards/BrokenCardFeedConnectionPage.tsx
@@ -4,6 +4,7 @@ import useOnyx from '@hooks/useOnyx';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import LoadingPage from '@pages/LoadingPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import {clearAssignCardStepAndData} from '@userActions/CompanyCards';
@@ -31,24 +32,38 @@ function BrokenCardFeedConnectionPage({route, policy}: BrokenCardFeedConnectionP
         };
     }, []);
 
+    let content: React.ReactNode;
     switch (currentStep) {
         case CONST.COMPANY_CARD.STEP.BANK_CONNECTION:
-            return (
+            content = (
                 <BankConnection
                     policyID={policyID}
                     feed={feed}
                 />
             );
+            break;
         case CONST.COMPANY_CARD.STEP.PLAID_CONNECTION:
-            return (
+            content = (
                 <PlaidConnectionStep
                     feed={feed}
                     policyID={policyID}
                 />
             );
+            break;
         default:
-            return <LoadingPage title={translate('workspace.companyCards.assignCard')} />;
+            content = <LoadingPage title={translate('workspace.companyCards.assignCard')} />;
     }
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            {content}
+        </AccessOrNotFoundWrapper>
+    );
 }
 
 export default withPolicyAndFullscreenLoading(BrokenCardFeedConnectionPage);
diff --git a/src/pages/workspace/companyCards/RefreshCardFeedConnectionPage.tsx b/src/pages/workspace/companyCards/RefreshCardFeedConnectionPage.tsx
index 057600c27d6d..6d9420875626 100644
--- a/src/pages/workspace/companyCards/RefreshCardFeedConnectionPage.tsx
+++ b/src/pages/workspace/companyCards/RefreshCardFeedConnectionPage.tsx
@@ -9,6 +9,7 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
 import LoadingPage from '@pages/LoadingPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import {clearAssignCardStepAndData} from '@userActions/CompanyCards';
@@ -63,26 +64,40 @@ function RefreshCardFeedConnectionPage({route, policy}: RefreshCardFeedConnectio
         return <NotFoundPage />;
     }
 
+    let content: React.ReactNode;
     switch (currentStep) {
         case CONST.COMPANY_CARD.STEP.BANK_CONNECTION:
-            return (
+            content = (
                 <BankConnection
                     policyID={policyID}
                     feed={feed}
                     title={title}
                 />
             );
+            break;
         case CONST.COMPANY_CARD.STEP.PLAID_CONNECTION:
-            return (
+            content = (
                 <PlaidConnectionStep
                     feed={feed}
                     policyID={policyID}
                     title={title}
                 />
             );
+            break;
         default:
-            return <LoadingPage title={title} />;
+            content = <LoadingPage title={title} />;
     }
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            {content}
+        </AccessOrNotFoundWrapper>
+    );
 }
 
 export default withPolicyAndFullscreenLoading(RefreshCardFeedConnectionPage);
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx
index abb505728f62..b3b7ca054585 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx
@@ -19,6 +19,7 @@ import {getConnectedIntegration, getCurrentConnectionName} from '@libs/PolicyUti
 import tokenizedSearch from '@libs/tokenizedSearch';
 import Navigation from '@navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import ROUTES from '@src/ROUTES';
@@ -80,44 +81,51 @@ function WorkspaceCompanyCardAccountSelectCardPage({route}: WorkspaceCompanyCard
     };
 
     return (
-        <SelectionScreen
+        <AccessOrNotFoundWrapper
             policyID={policyID}
-            headerContent={
-                <View style={[styles.mh5, styles.mb3]}>
-                    {!!exportMenuItem?.description && (
-                        <View style={[styles.renderHTML, styles.flexRow]}>
-                            <RenderHTML
-                                html={
-                                    isXeroConnection
-                                        ? translate('workspace.moreFeatures.companyCards.integrationExportTitleXero', exportMenuItem.description)
-                                        : translate(
-                                              'workspace.moreFeatures.companyCards.integrationExportTitle',
-                                              exportMenuItem.description,
-                                              `${environmentURL}/${exportMenuItem.exportPageLink}`,
-                                          )
-                                }
-                            />
-                        </View>
-                    )}
-                </View>
-            }
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
-            displayName="WorkspaceCompanyCardAccountSelectCardPage"
-            data={searchedListOptions ?? []}
-            textInputOptions={{
-                label: translate('common.search'),
-                value: searchText,
-                onChangeText: setSearchText,
-            }}
-            onSelectRow={updateExportAccount}
-            initiallyFocusedOptionKey={exportMenuItem?.data?.find((mode) => mode.isSelected)?.keyForList}
-            onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_COMPANY_CARD_DETAILS.getRoute(policyID, feed, cardID, backTo))}
-            headerTitleAlreadyTranslated={exportMenuItem?.description}
-            listEmptyContent={listEmptyContent}
-            connectionName={connectedIntegration}
-            shouldShowTextInput={shouldShowTextInput}
-            isRowMultilineSupported
-        />
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SelectionScreen
+                policyID={policyID}
+                headerContent={
+                    <View style={[styles.mh5, styles.mb3]}>
+                        {!!exportMenuItem?.description && (
+                            <View style={[styles.renderHTML, styles.flexRow]}>
+                                <RenderHTML
+                                    html={
+                                        isXeroConnection
+                                            ? translate('workspace.moreFeatures.companyCards.integrationExportTitleXero', exportMenuItem.description)
+                                            : translate(
+                                                  'workspace.moreFeatures.companyCards.integrationExportTitle',
+                                                  exportMenuItem.description,
+                                                  `${environmentURL}/${exportMenuItem.exportPageLink}`,
+                                              )
+                                    }
+                                />
+                            </View>
+                        )}
+                    </View>
+                }
+                featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+                displayName="WorkspaceCompanyCardAccountSelectCardPage"
+                data={searchedListOptions ?? []}
+                textInputOptions={{
+                    label: translate('common.search'),
+                    value: searchText,
+                    onChangeText: setSearchText,
+                }}
+                onSelectRow={updateExportAccount}
+                initiallyFocusedOptionKey={exportMenuItem?.data?.find((mode) => mode.isSelected)?.keyForList}
+                onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_COMPANY_CARD_DETAILS.getRoute(policyID, feed, cardID, backTo))}
+                headerTitleAlreadyTranslated={exportMenuItem?.description}
+                listEmptyContent={listEmptyContent}
+                connectionName={connectedIntegration}
+                shouldShowTextInput={shouldShowTextInput}
+                isRowMultilineSupported
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx
index 9b8f9151a787..692a3eebd80c 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx
@@ -132,6 +132,8 @@ function WorkspaceCompanyCardAddWorkEmailPage({route}: WorkspaceCompanyCardAddWo
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardAddWorkEmailPage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardEditCardNamePage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardEditCardNamePage.tsx
index ce47ff93d8c9..293d4aac3f07 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardEditCardNamePage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardEditCardNamePage.tsx
@@ -67,6 +67,8 @@ function WorkspaceCompanyCardEditCardNamePage({route}: WorkspaceCompanyCardEditC
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardEditCardNamePage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardEditTransactionStartDatePage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardEditTransactionStartDatePage.tsx
index f34586778f38..d52a671534de 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardEditTransactionStartDatePage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardEditTransactionStartDatePage.tsx
@@ -103,6 +103,8 @@ function WorkspaceCompanyCardEditTransactionStartDatePage({route}: WorkspaceComp
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardEditTransactionStartDatePage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
index 375b4b2ba096..583c353cd599 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
@@ -206,6 +206,7 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardFeedSelectorPage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardStatementCloseDatePage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardStatementCloseDatePage.tsx
index 1f2b82456a83..fa6685bcde00 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardStatementCloseDatePage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardStatementCloseDatePage.tsx
@@ -87,6 +87,8 @@ function WorkspaceCompanyCardStatementCloseDatePage({
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <WorkspaceCompanyCardStatementCloseDateSelectionList
                 confirmText={translate('common.apply')}
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
index 044a1a613957..c071ae83d01f 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
@@ -95,6 +95,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) {
         <AccessOrNotFoundWrapper
             policyID={route.params.policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
         >
             <WorkspacePageWithSections
                 icon={memoizedIllustrations.CompanyCard}
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsFeedNamePage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsFeedNamePage.tsx
index ab0c42e05133..87eaa44385de 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsFeedNamePage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsFeedNamePage.tsx
@@ -87,6 +87,8 @@ function WorkspaceCompanyCardsSettingsFeedNamePage({
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 enableEdgeToEdgeBottomSafeAreaPadding
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsPage.tsx
index a6732e803c67..f24112ad1715 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsPage.tsx
@@ -129,6 +129,8 @@ function WorkspaceCompanyCardsSettingsPage({
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardsSettingsPage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage.tsx
index aed9124e79ff..7b93829c536d 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage.tsx
@@ -6,7 +6,9 @@ import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/crea
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import VerifyAccountPageBase from '@pages/settings/VerifyAccountPageBase';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {clearAddNewCardFlow, seedCardFeedRefresh} from '@userActions/CompanyCards';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
@@ -29,23 +31,30 @@ function WorkspaceCompanyCardsVerifyAccountPage({route}: WorkspaceCompanyCardsVe
         seedCardFeedRefresh(feed, policy?.outputCurrency, currencyList, countryByIp);
     };
 
-    if (feed) {
-        return (
-            <VerifyAccountPageBase
-                navigateBackTo={companyCardsRoute}
-                navigateForwardTo={ROUTES.WORKSPACE_COMPANY_CARDS_REFRESH_CARD_FEED_CONNECTION.getRoute(policyID, feed)}
-                onValidationSuccess={onRefreshValidationSuccess}
-            />
-        );
-    }
-
-    return (
+    const content = feed ? (
+        <VerifyAccountPageBase
+            navigateBackTo={companyCardsRoute}
+            navigateForwardTo={ROUTES.WORKSPACE_COMPANY_CARDS_REFRESH_CARD_FEED_CONNECTION.getRoute(policyID, feed)}
+            onValidationSuccess={onRefreshValidationSuccess}
+        />
+    ) : (
         <VerifyAccountPageBase
             navigateBackTo={companyCardsRoute}
             navigateForwardTo={createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_COMPANY_CARDS_ADD_NEW.path, companyCardsRoute)}
             onValidationSuccess={clearAddNewCardFlow}
         />
     );
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            {content}
+        </AccessOrNotFoundWrapper>
+    );
 }
 
 export default WorkspaceCompanyCardsVerifyAccountPage;
diff --git a/src/pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage.tsx b/src/pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage.tsx
index 8a1203796704..2636616ad2e0 100644
--- a/src/pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage.tsx
@@ -11,6 +11,7 @@ import {expensifyLoginsSelector} from '@libs/UserUtils';
 import Navigation from '@navigation/Navigation';
 import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {updateSelectedFeed} from '@userActions/Card';
 import {linkCardFeedToPolicy} from '@userActions/CompanyCards';
 import {clearGetAccessiblePoliciesErrors, getAccessiblePolicies} from '@userActions/Policy/Policy';
@@ -24,7 +25,9 @@ import type {Errors} from '@src/types/onyx/OnyxCommon';
 
 type WorkspaceVerifyWorkAccountPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.COMPANY_CARD_VERIFY_WORK_EMAIL>;
 
-function WorkspaceVerifyWorkAccountPage({route}: WorkspaceVerifyWorkAccountPageProps) {
+type WorkspaceVerifyWorkAccountPageContentProps = Pick<WorkspaceVerifyWorkAccountPageProps, 'route'>;
+
+function WorkspaceVerifyWorkAccountPageContent({route}: WorkspaceVerifyWorkAccountPageContentProps) {
     const {policyID, feed} = route.params;
     const {translate} = useLocalize();
     const [loginList] = useOnyx(ONYXKEYS.LOGINS, {selector: expensifyLoginsSelector});
@@ -92,4 +95,19 @@ function WorkspaceVerifyWorkAccountPage({route}: WorkspaceVerifyWorkAccountPageP
     );
 }
 
+function WorkspaceVerifyWorkAccountPage({route}: WorkspaceVerifyWorkAccountPageProps) {
+    const {policyID} = route.params;
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <WorkspaceVerifyWorkAccountPageContent route={route} />
+        </AccessOrNotFoundWrapper>
+    );
+}
+
 export default WorkspaceVerifyWorkAccountPage;
diff --git a/src/pages/workspace/companyCards/addNew/CompanyCardLayoutNamePage.tsx b/src/pages/workspace/companyCards/addNew/CompanyCardLayoutNamePage.tsx
index 8b9a9ac66b9b..cca766cf9543 100644
--- a/src/pages/workspace/companyCards/addNew/CompanyCardLayoutNamePage.tsx
+++ b/src/pages/workspace/companyCards/addNew/CompanyCardLayoutNamePage.tsx
@@ -57,6 +57,8 @@ function CompanyCardLayoutNamePage({route}: CompanyCardLayoutNamePageProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="CompanyCardLayoutNamePage"
diff --git a/src/pages/workspace/companyCards/addNew/CompanyCardsImportSpreadsheetPage.tsx b/src/pages/workspace/companyCards/addNew/CompanyCardsImportSpreadsheetPage.tsx
index f4c1162e02a8..24b014264d59 100644
--- a/src/pages/workspace/companyCards/addNew/CompanyCardsImportSpreadsheetPage.tsx
+++ b/src/pages/workspace/companyCards/addNew/CompanyCardsImportSpreadsheetPage.tsx
@@ -29,6 +29,8 @@ function CompanyCardsImportSpreadsheetPage({route}: CompanyCardsImportSpreadshee
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
             fullPageNotFoundViewProps={{subtitleKey: isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized', onLinkPress: goBackFromInvalidPolicy}}
         >
             <ImportSpreadsheet
diff --git a/src/pages/workspace/companyCards/addNew/CompanyCardsImportedPage.tsx b/src/pages/workspace/companyCards/addNew/CompanyCardsImportedPage.tsx
index ea2bee8bca0c..6ebd47e10c25 100644
--- a/src/pages/workspace/companyCards/addNew/CompanyCardsImportedPage.tsx
+++ b/src/pages/workspace/companyCards/addNew/CompanyCardsImportedPage.tsx
@@ -168,6 +168,8 @@ function CompanyCardsImportedPage({route}: CompanyCardsImportedPageProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
             fullPageNotFoundViewProps={{subtitleKey: isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized', onLinkPress: goBackFromInvalidPolicy}}
         >
             <ScreenWrapper
diff --git a/src/pages/workspace/companyCards/addNew/DynamicAddNewCardPage.tsx b/src/pages/workspace/companyCards/addNew/DynamicAddNewCardPage.tsx
index e64232757587..15655931ad8f 100644
--- a/src/pages/workspace/companyCards/addNew/DynamicAddNewCardPage.tsx
+++ b/src/pages/workspace/companyCards/addNew/DynamicAddNewCardPage.tsx
@@ -144,6 +144,8 @@ function DynamicAddNewCardPage({policy}: WithPolicyAndFullscreenLoadingProps) {
             policyID={policyID}
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <View style={styles.flex1}>{CurrentStep}</View>
             <ConfirmModal
diff --git a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx
index 6b13e8083f65..1aa3a995a767 100644
--- a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx
@@ -24,6 +24,7 @@ import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils';
 import {filterGuideAndAccountManager, getGuideAndAccountManagerInfo, getIneligibleInvitees, isDeletedPolicyEmployee} from '@libs/PolicyUtils';
 import tokenizedSearch from '@libs/tokenizedSearch';
 import Navigation from '@navigation/Navigation';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {setAssignCardStepAndData} from '@userActions/CompanyCards';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -223,27 +224,34 @@ function AssigneeStep({route}: AssigneeStepProps) {
     };
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="AssigneeStep"
-            handleBackButtonPress={handleBackButtonPress}
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            enableEdgeToEdgeBottomSafeAreaPadding
-            onEntryTransitionEnd={() => setDidScreenTransitionEnd(true)}
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.chooseTheCardholder')}</Text>
-            <SelectionList
-                data={assignees}
-                onSelectRow={submit}
-                ListItem={UserListItem}
-                textInputOptions={textInputOptions}
-                initiallyFocusedItemKey={assignCard?.cardToAssign?.email}
-                shouldShowLoadingPlaceholder={!areOptionsInitialized}
-                isLoadingNewOptions={!!isSearchingForReports}
-                disableMaintainingScrollPosition
-                shouldUpdateFocusedIndex
-                addBottomSafeAreaPadding
-            />
-        </InteractiveStepWrapper>
+            <InteractiveStepWrapper
+                wrapperID="AssigneeStep"
+                handleBackButtonPress={handleBackButtonPress}
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                enableEdgeToEdgeBottomSafeAreaPadding
+                onEntryTransitionEnd={() => setDidScreenTransitionEnd(true)}
+            >
+                <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.chooseTheCardholder')}</Text>
+                <SelectionList
+                    data={assignees}
+                    onSelectRow={submit}
+                    ListItem={UserListItem}
+                    textInputOptions={textInputOptions}
+                    initiallyFocusedItemKey={assignCard?.cardToAssign?.email}
+                    shouldShowLoadingPlaceholder={!areOptionsInitialized}
+                    isLoadingNewOptions={!!isSearchingForReports}
+                    disableMaintainingScrollPosition
+                    shouldUpdateFocusedIndex
+                    addBottomSafeAreaPadding
+                />
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx b/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
index bf887fdb72d1..e51e31590196 100644
--- a/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
@@ -59,6 +59,8 @@ function CardNameStep({route}: CardNameStepProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="CardNameStep"
diff --git a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
index 39317e2e5612..48f48563b1dd 100644
--- a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
@@ -26,6 +26,7 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils';
 import tokenizedSearch from '@libs/tokenizedSearch';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -142,6 +143,7 @@ function CardSelectionStep({route}: CardSelectionStepProps) {
                 <InteractiveStepSubHeader
                     startStepIndex={1}
                     stepNames={CONST.COMPANY_CARD.STEP_NAMES}
+                    currentStepAccessibilityDescription={translate('workspace.companyCards.chooseCard')}
                 />
             </View>
             <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mt3]}>{translate('workspace.companyCards.chooseCard')}</Text>
@@ -152,49 +154,56 @@ function CardSelectionStep({route}: CardSelectionStepProps) {
     );
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="CardSelectionStep"
-            handleBackButtonPress={handleBackButtonPress}
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            headerSubtitle={assigneeDisplayName}
-            enableEdgeToEdgeBottomSafeAreaPadding
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            {!cardListOptions.length ? (
-                <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter, styles.ph5, styles.mb9, safeAreaPaddingBottomStyle]}>
-                    <Icon
-                        src={lazyIllustrations.BrokenMagnifyingGlass}
-                        width={116}
-                        height={168}
-                    />
-                    <Text style={[styles.textHeadlineLineHeightXXL, styles.mt3]}>{translate('workspace.companyCards.noActiveCards')}</Text>
-                    <View style={[styles.renderHTML, styles.flexRow, styles.ph5, styles.mv3]}>
-                        <RenderHTML html={translate('workspace.companyCards.somethingMightBeBroken')} />
-                    </View>
-                </View>
-            ) : (
-                <SelectionList
-                    data={searchedListOptions}
-                    ListItem={SingleSelectListItem}
-                    onSelectRow={({value}) => handleSelectCard(value)}
-                    initiallyFocusedItemKey={cardSelected}
-                    textInputOptions={textInputOptions}
-                    customListHeaderContent={customListHeader}
-                    shouldScrollToFocusedIndex={false}
-                    shouldShowListEmptyContent={false}
-                    addBottomSafeAreaPadding
-                    shouldUpdateFocusedIndex
-                    footerContent={
-                        <FormAlertWithSubmitButton
-                            buttonText={translate(isEditing ? 'common.confirm' : 'common.next')}
-                            onSubmit={submit}
-                            isAlertVisible={shouldShowError}
-                            containerStyles={[!shouldShowError && styles.mt5]}
-                            message={translate('common.error.pleaseSelectOne')}
+            <InteractiveStepWrapper
+                wrapperID="CardSelectionStep"
+                handleBackButtonPress={handleBackButtonPress}
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                headerSubtitle={assigneeDisplayName}
+                enableEdgeToEdgeBottomSafeAreaPadding
+            >
+                {!cardListOptions.length ? (
+                    <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter, styles.ph5, styles.mb9, safeAreaPaddingBottomStyle]}>
+                        <Icon
+                            src={lazyIllustrations.BrokenMagnifyingGlass}
+                            width={116}
+                            height={168}
                         />
-                    }
-                />
-            )}
-        </InteractiveStepWrapper>
+                        <Text style={[styles.textHeadlineLineHeightXXL, styles.mt3]}>{translate('workspace.companyCards.noActiveCards')}</Text>
+                        <View style={[styles.renderHTML, styles.flexRow, styles.ph5, styles.mv3]}>
+                            <RenderHTML html={translate('workspace.companyCards.somethingMightBeBroken')} />
+                        </View>
+                    </View>
+                ) : (
+                    <SelectionList
+                        data={searchedListOptions}
+                        ListItem={SingleSelectListItem}
+                        onSelectRow={({value}) => handleSelectCard(value)}
+                        initiallyFocusedItemKey={cardSelected}
+                        textInputOptions={textInputOptions}
+                        customListHeaderContent={customListHeader}
+                        shouldScrollToFocusedIndex={false}
+                        shouldShowListEmptyContent={false}
+                        addBottomSafeAreaPadding
+                        shouldUpdateFocusedIndex
+                        footerContent={
+                            <FormAlertWithSubmitButton
+                                buttonText={translate(isEditing ? 'common.confirm' : 'common.next')}
+                                onSubmit={submit}
+                                isAlertVisible={shouldShowError}
+                                containerStyles={[!shouldShowError && styles.mt5]}
+                                message={translate('common.error.pleaseSelectOne')}
+                            />
+                        }
+                    />
+                )}
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx b/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx
index 7cdf71fe12e2..54fa8a39625b 100644
--- a/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx
@@ -24,6 +24,7 @@ import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils';
 import {getDefaultAvatarURL} from '@libs/UserAvatarUtils';
 import Navigation from '@navigation/Navigation';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {
     assignWorkspaceCompanyCard,
     clearAssignCardErrors as clearAssignCardErrorsAction,
@@ -156,73 +157,80 @@ function ConfirmationStep({route}: ConfirmationStepProps) {
     };
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="ConfirmationStep"
-            handleBackButtonPress={handleBackButtonPress}
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            enableEdgeToEdgeBottomSafeAreaPadding
-            shouldShowOfflineIndicatorInWideScreen
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            <ScrollView
-                style={styles.pt0}
-                contentContainerStyle={styles.flexGrow1}
-                addBottomSafeAreaPadding
+            <InteractiveStepWrapper
+                wrapperID="ConfirmationStep"
+                handleBackButtonPress={handleBackButtonPress}
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                enableEdgeToEdgeBottomSafeAreaPadding
+                shouldShowOfflineIndicatorInWideScreen
             >
-                <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mt3]}>{translate('workspace.companyCards.letsDoubleCheck')}</Text>
-                <Text style={[styles.textSupporting, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.confirmationDescription')}</Text>
-                <MenuItemWithTopDescription
-                    description={translate('workspace.companyCards.card')}
-                    title={maskCardNumber(cardToAssign?.cardName ?? '', cardToAssign?.bankName)}
-                    interactive={false}
-                />
-                <View style={[styles.optionsListSectionHeader, styles.justifyContentCenter]}>
-                    <Text style={[styles.ph5, styles.textLabelSupporting]}>{translate('common.to')}</Text>
-                </View>
-                <MenuItem
-                    title={cardholderName}
-                    description={cardholderEmail}
-                    icon={cardholder?.avatar ?? getDefaultAvatarURL({accountID: cardholderAccountID ?? CONST.DEFAULT_NUMBER_ID})}
-                    iconType={CONST.ICON_TYPE_AVATAR}
-                    shouldShowRightIcon
-                    onPress={() => editStep(CONST.COMPANY_CARD.STEP.ASSIGNEE)}
-                />
-                <MenuItemWithTopDescription
-                    description={translate('workspace.moreFeatures.companyCards.transactionStartDate')}
-                    title={
-                        cardToAssign?.dateOption === CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.FROM_BEGINNING
-                            ? translate('workspace.companyCards.fromTheBeginning')
-                            : cardToAssign?.startDate
-                    }
-                    shouldShowRightIcon
-                    onPress={() => editStep(CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE)}
-                />
-                <MenuItemWithTopDescription
-                    description={translate('workspace.companyCards.cardName')}
-                    title={cardToAssign?.customCardName}
-                    shouldShowRightIcon
-                    onPress={() => editStep(CONST.COMPANY_CARD.STEP.CARD_NAME)}
-                />
-                <View style={[styles.mh5, styles.pb5, styles.mt3, styles.flexGrow1, styles.justifyContentEnd]}>
-                    <OfflineWithFeedback
-                        shouldDisplayErrorAbove
-                        errors={assignCard?.errors ?? cardError}
-                        onClose={clearAssignCardErrors}
-                        errorRowStyles={styles.mv2}
-                    >
-                        <Button
-                            isDisabled={isOffline}
-                            success
-                            large
-                            isLoading={assignCard?.isAssigning}
-                            style={styles.w100}
-                            onPress={submit}
-                            testID={CONST.ASSIGN_CARD_BUTTON_TEST_ID}
-                            text={translate('workspace.companyCards.assignCard')}
-                        />
-                    </OfflineWithFeedback>
-                </View>
-            </ScrollView>
-        </InteractiveStepWrapper>
+                <ScrollView
+                    style={styles.pt0}
+                    contentContainerStyle={styles.flexGrow1}
+                    addBottomSafeAreaPadding
+                >
+                    <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mt3]}>{translate('workspace.companyCards.letsDoubleCheck')}</Text>
+                    <Text style={[styles.textSupporting, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.confirmationDescription')}</Text>
+                    <MenuItemWithTopDescription
+                        description={translate('workspace.companyCards.card')}
+                        title={maskCardNumber(cardToAssign?.cardName ?? '', cardToAssign?.bankName)}
+                        interactive={false}
+                    />
+                    <View style={[styles.optionsListSectionHeader, styles.justifyContentCenter]}>
+                        <Text style={[styles.ph5, styles.textLabelSupporting]}>{translate('common.to')}</Text>
+                    </View>
+                    <MenuItem
+                        title={cardholderName}
+                        description={cardholderEmail}
+                        icon={cardholder?.avatar ?? getDefaultAvatarURL({accountID: cardholderAccountID ?? CONST.DEFAULT_NUMBER_ID})}
+                        iconType={CONST.ICON_TYPE_AVATAR}
+                        shouldShowRightIcon
+                        onPress={() => editStep(CONST.COMPANY_CARD.STEP.ASSIGNEE)}
+                    />
+                    <MenuItemWithTopDescription
+                        description={translate('workspace.moreFeatures.companyCards.transactionStartDate')}
+                        title={
+                            cardToAssign?.dateOption === CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.FROM_BEGINNING
+                                ? translate('workspace.companyCards.fromTheBeginning')
+                                : cardToAssign?.startDate
+                        }
+                        shouldShowRightIcon
+                        onPress={() => editStep(CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE)}
+                    />
+                    <MenuItemWithTopDescription
+                        description={translate('workspace.companyCards.cardName')}
+                        title={cardToAssign?.customCardName}
+                        shouldShowRightIcon
+                        onPress={() => editStep(CONST.COMPANY_CARD.STEP.CARD_NAME)}
+                    />
+                    <View style={[styles.mh5, styles.pb5, styles.mt3, styles.flexGrow1, styles.justifyContentEnd]}>
+                        <OfflineWithFeedback
+                            shouldDisplayErrorAbove
+                            errors={assignCard?.errors ?? cardError}
+                            onClose={clearAssignCardErrors}
+                            errorRowStyles={styles.mv2}
+                        >
+                            <Button
+                                isDisabled={isOffline}
+                                success
+                                large
+                                isLoading={assignCard?.isAssigning}
+                                style={styles.w100}
+                                onPress={submit}
+                                testID={CONST.ASSIGN_CARD_BUTTON_TEST_ID}
+                                text={translate('workspace.companyCards.assignCard')}
+                            />
+                        </OfflineWithFeedback>
+                    </View>
+                </ScrollView>
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx b/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx
index d1165da8a869..928b2a3836dc 100644
--- a/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx
@@ -11,6 +11,7 @@ import {getCardAssignmentDateOption, getCardAssignmentStartDate, getDefaultCardN
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import Navigation from '@navigation/Navigation';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import WorkspaceInviteMessageComponent from '@pages/workspace/members/WorkspaceInviteMessageComponent';
 import {setAssignCardStepAndData} from '@userActions/CompanyCards';
 import {clearInviteDraft} from '@userActions/Policy/Member';
@@ -104,26 +105,33 @@ function InviteNewMemberStep({route, currentUserPersonalDetails}: InviteeNewMemb
     }, [assignCard?.cardToAssign?.invitingMemberEmail, policy?.employeeList, goToNextStep, assignCard?.cardToAssign?.invitingMemberAccountID, policyID]);
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="InviteNewMemberStep"
-            shouldEnablePickerAvoiding={false}
-            shouldEnableMaxHeight
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            handleBackButtonPress={handleBackButtonPress}
-            enableEdgeToEdgeBottomSafeAreaPadding
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            <WorkspaceInviteMessageComponent
-                policy={policy}
-                policyID={policyID}
-                backTo={undefined}
-                currentUserPersonalDetails={currentUserPersonalDetails}
-                shouldShowBackButton={false}
-                isInviteNewMemberStep
-                goToNextStep={goToNextStep}
-                shouldShowTooltip={false}
-                shouldShowMemberNames={false}
-            />
-        </InteractiveStepWrapper>
+            <InteractiveStepWrapper
+                wrapperID="InviteNewMemberStep"
+                shouldEnablePickerAvoiding={false}
+                shouldEnableMaxHeight
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                handleBackButtonPress={handleBackButtonPress}
+                enableEdgeToEdgeBottomSafeAreaPadding
+            >
+                <WorkspaceInviteMessageComponent
+                    policy={policy}
+                    policyID={policyID}
+                    backTo={undefined}
+                    currentUserPersonalDetails={currentUserPersonalDetails}
+                    shouldShowBackButton={false}
+                    isInviteNewMemberStep
+                    goToNextStep={goToNextStep}
+                    shouldShowTooltip={false}
+                    shouldShowMemberNames={false}
+                />
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx b/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx
index 62a0ed9646c0..aca7c2ada910 100644
--- a/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx
@@ -11,15 +11,22 @@ import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
+import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {isRequiredFulfilled} from '@libs/ValidationUtils';
 import Navigation from '@navigation/Navigation';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {setAssignCardStepAndData} from '@userActions/CompanyCards';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import type SCREENS from '@src/SCREENS';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 
-function TransactionStartDateStep() {
+type TransactionStartDateStepProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_TRANSACTION_START_DATE>;
+
+function TransactionStartDateStep({route}: TransactionStartDateStepProps) {
+    const policyID = route.params.policyID;
     const {translate} = useLocalize();
     const styles = useThemeStyles();
 
@@ -90,66 +97,73 @@ function TransactionStartDateStep() {
     };
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="TransactionStartDateStep"
-            handleBackButtonPress={handleBackButtonPress}
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            enableEdgeToEdgeBottomSafeAreaPadding
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            {isLoading ? (
-                <ActivityIndicator
-                    size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
-                    style={styles.h100}
-                    reasonAttributes={activityReasonAttributes}
-                />
-            ) : (
-                <>
-                    <Text style={[styles.textSupporting, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.startDateDescription')}</Text>
-                    <View style={styles.flex1}>
-                        <SelectionList
-                            ListItem={SingleSelectListItem}
-                            onSelectRow={({value}) => handleSelectDateOption(value)}
-                            data={dateOptions}
-                            shouldSingleExecuteRowSelect
-                            initiallyFocusedItemKey={dateOptionSelected}
-                            shouldUpdateFocusedIndex
-                            addBottomSafeAreaPadding
-                            footerContent={
-                                <Button
-                                    success
-                                    large
-                                    pressOnEnter
-                                    text={translate(isEditing ? 'common.save' : 'common.next')}
-                                    onPress={submit}
-                                />
-                            }
-                            listFooterContent={
-                                dateOptionSelected === CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.CUSTOM ? (
-                                    <View style={[styles.ph5]}>
-                                        <DatePicker
-                                            inputID=""
-                                            value={startDate}
-                                            label={translate('iou.startDate')}
-                                            onInputChange={(value) => {
-                                                if (!isRequiredFulfilled(value)) {
-                                                    setErrorText(translate('common.error.fieldRequired'));
-                                                } else {
-                                                    setErrorText('');
-                                                }
-                                                setLocalStartDate(value);
-                                            }}
-                                            minDate={CONST.CALENDAR_PICKER.MIN_DATE}
-                                            maxDate={new Date()}
-                                            errorText={errorText}
-                                        />
-                                    </View>
-                                ) : null
-                            }
-                        />
-                    </View>
-                </>
-            )}
-        </InteractiveStepWrapper>
+            <InteractiveStepWrapper
+                wrapperID="TransactionStartDateStep"
+                handleBackButtonPress={handleBackButtonPress}
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                enableEdgeToEdgeBottomSafeAreaPadding
+            >
+                {isLoading ? (
+                    <ActivityIndicator
+                        size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
+                        style={styles.h100}
+                        reasonAttributes={activityReasonAttributes}
+                    />
+                ) : (
+                    <>
+                        <Text style={[styles.textSupporting, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.startDateDescription')}</Text>
+                        <View style={styles.flex1}>
+                            <SelectionList
+                                ListItem={SingleSelectListItem}
+                                onSelectRow={({value}) => handleSelectDateOption(value)}
+                                data={dateOptions}
+                                shouldSingleExecuteRowSelect
+                                initiallyFocusedItemKey={dateOptionSelected}
+                                shouldUpdateFocusedIndex
+                                addBottomSafeAreaPadding
+                                footerContent={
+                                    <Button
+                                        success
+                                        large
+                                        pressOnEnter
+                                        text={translate(isEditing ? 'common.save' : 'common.next')}
+                                        onPress={submit}
+                                    />
+                                }
+                                listFooterContent={
+                                    dateOptionSelected === CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.CUSTOM ? (
+                                        <View style={[styles.ph5]}>
+                                            <DatePicker
+                                                inputID=""
+                                                value={startDate}
+                                                label={translate('iou.startDate')}
+                                                onInputChange={(value) => {
+                                                    if (!isRequiredFulfilled(value)) {
+                                                        setErrorText(translate('common.error.fieldRequired'));
+                                                    } else {
+                                                        setErrorText('');
+                                                    }
+                                                    setLocalStartDate(value);
+                                                }}
+                                                minDate={CONST.CALENDAR_PICKER.MIN_DATE}
+                                                maxDate={new Date()}
+                                                errorText={errorText}
+                                            />
+                                        </View>
+                                    ) : null
+                                }
+                            />
+                        </View>
+                    </>
+                )}
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index 18cdfafd002c..de5121011e58 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -9,13 +9,10 @@ import {loadIllustration} from '@components/Icon/IllustrationLoader';
 import type {IllustrationName} from '@components/Icon/IllustrationLoader';
 import {ModalActions} from '@components/Modal/Global/ModalContext';
 import ScreenWrapper from '@components/ScreenWrapper';
-import SearchBar from '@components/SearchBar';
-import TableListItem from '@components/SelectionList/ListItem/TableListItem';
-import type {ListItem} from '@components/SelectionList/types';
-import SelectionListWithModal from '@components/SelectionListWithModal';
-import CustomListHeader from '@components/SelectionListWithModal/CustomListHeader';
-import Switch from '@components/Switch';
+import WorkspaceDistanceRatesTable from '@components/Tables/WorkspaceDistanceRatesTable';
+import type {DistanceRateTableItemData} from '@components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow';
 import Text from '@components/Text';
+import useCleanupSelectedOptions from '@hooks/useCleanupSelectedOptions';
 import useConfirmModal from '@hooks/useConfirmModal';
 import useFilteredSelection from '@hooks/useFilteredSelection';
 import {useMemoizedLazyAsset, useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
@@ -27,7 +24,6 @@ import usePolicy from '@hooks/usePolicy';
 import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useSearchBackPress from '@hooks/useSearchBackPress';
-import useSearchResults from '@hooks/useSearchResults';
 import useShouldDisplayButtonsInSeparateLine from '@hooks/useShouldDisplayButtonsInSeparateLine';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useTransactionViolation from '@hooks/useTransactionViolation';
@@ -41,12 +37,10 @@ import {
     setPolicyDistanceRatesEnabled,
 } from '@libs/actions/Policy/DistanceRate';
 import {convertAmountToDisplayString} from '@libs/CurrencyUtils';
-import {canUseTouchScreen} from '@libs/DeviceCapabilities';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import {getDistanceRateCustomUnit} from '@libs/PolicyUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
-import tokenizedSearch from '@libs/tokenizedSearch';
 import type {WorkspaceSplitNavigatorParamList} from '@navigation/types';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import ButtonWithDropdownMenu from '@src/components/ButtonWithDropdownMenu';
@@ -57,8 +51,6 @@ import type SCREENS from '@src/SCREENS';
 import type {Report, Transaction} from '@src/types/onyx';
 import type {Rate} from '@src/types/onyx/Policy';
 
-type RateForList = ListItem & {value: string; rate?: number};
-
 type PolicyDistanceRatesPageProps = PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.DISTANCE_RATES>;
 
 function PolicyDistanceRatesPage({
@@ -69,14 +61,13 @@ function PolicyDistanceRatesPage({
     const icons = useMemoizedLazyExpensifyIcons(['Checkmark', 'Close', 'Gear', 'Plus', 'Trashcan']);
     const {shouldUseNarrowLayout, isInLandscapeMode} = useResponsiveLayout();
     const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
+    const {translate} = useLocalize();
     const {showConfirmModal} = useConfirmModal();
     const policy = usePolicy(policyID);
     useWorkspaceDocumentTitle(policy?.name, 'workspace.common.distanceRates');
     const isMobileSelectionModeEnabled = useMobileSelectionMode();
-    const {canWrite: canWriteDistanceRates, showReadOnlyModal, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.DISTANCE_RATES);
+    const {canWrite: canWriteDistanceRates, showReadOnlyModal} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.DISTANCE_RATES);
 
-    const canSelectMultiple = canWriteDistanceRates && (shouldUseNarrowLayout ? isMobileSelectionModeEnabled : true);
     const {asset: CarIce} = useMemoizedLazyAsset(() => loadIllustration('CarIce' as IllustrationName));
     const customUnit = useMemo(() => getDistanceRateCustomUnit(policy), [policy]);
     const customUnitRates: Record<string, Rate> = useMemo(() => customUnit?.rates ?? {}, [customUnit?.rates]);
@@ -151,6 +142,12 @@ function PolicyDistanceRatesPage({
 
     const [selectedDistanceRates, setSelectedDistanceRates] = useFilteredSelection(selectableRates, filterRateSelection);
 
+    const clearTableSelection = useCallback(() => {
+        setSelectedDistanceRates((prev) => (prev.length > 0 ? [] : prev));
+    }, [setSelectedDistanceRates]);
+
+    useCleanupSelectedOptions(clearTableSelection);
+
     const canDisableOrDeleteSelectedRates = useMemo(
         () =>
             Object.keys(selectableRates)
@@ -163,22 +160,6 @@ function PolicyDistanceRatesPage({
         openPolicyDistanceRatesPage(policyID);
     }, [policyID]);
 
-    const dismissError = useCallback(
-        (item: RateForList) => {
-            if (!customUnit?.customUnitID) {
-                return;
-            }
-
-            if (customUnitRates[item.value].errors) {
-                clearDeleteDistanceRateError(policyID, customUnit.customUnitID, item.value);
-                return;
-            }
-
-            clearCreateDistanceRateItemAndError(policyID, customUnit.customUnitID, item.value);
-        },
-        [customUnit?.customUnitID, customUnitRates, policyID],
-    );
-
     const {isOffline} = useNetwork({onReconnect: fetchDistanceRates});
 
     useEffect(() => {
@@ -219,7 +200,6 @@ function PolicyDistanceRatesPage({
                 return;
             }
             const rate = customUnit?.rates?.[rateID];
-            // Rates can be disabled or deleted as long as in the remaining rates there is always at least one enabled rate and there are no pending delete actions
             if (!rate?.enabled || canDisableOrDeleteRate(rateID)) {
                 setPolicyDistanceRatesEnabled(policyID, customUnit, [{...rate, enabled: value}]);
             } else {
@@ -231,60 +211,6 @@ function PolicyDistanceRatesPage({
 
     const unitTranslation = translate(`common.${customUnit?.attributes?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES}`);
 
-    const distanceRatesList = useMemo<RateForList[]>(
-        () =>
-            Object.values(customUnitRates).map((value) => {
-                const alternateText = `${convertAmountToDisplayString(value.rate, value.currency ?? CONST.CURRENCY.USD)} / ${unitTranslation}`;
-
-                return {
-                    rate: value.rate,
-                    value: value.customUnitRateID,
-                    text: value.name,
-                    alternateText,
-                    keyForList: value.customUnitRateID,
-                    isDisabled: value.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
-                    pendingAction:
-                        value.pendingAction ??
-                        value.pendingFields?.rate ??
-                        value.pendingFields?.enabled ??
-                        value.pendingFields?.currency ??
-                        value.pendingFields?.taxRateExternalID ??
-                        value.pendingFields?.taxClaimablePercentage ??
-                        value.pendingFields?.name ??
-                        customUnit?.pendingFields?.attributes ??
-                        (policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? policy?.pendingAction : undefined),
-                    errors: value.errors ?? undefined,
-                    rightElement: (
-                        <Switch
-                            isOn={!!value?.enabled}
-                            accessibilityLabel={value?.name ?? ''}
-                            onToggle={(newValue: boolean) => updateDistanceRateEnabled(newValue, value.customUnitRateID)}
-                            showLockIcon={!canWriteDistanceRates || !canDisableOrDeleteRate(value.customUnitRateID)}
-                            disabled={!canWriteDistanceRates || value.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}
-                            disabledAction={withReadOnlyFallback()}
-                        />
-                    ),
-                };
-            }),
-        [
-            canDisableOrDeleteRate,
-            canWriteDistanceRates,
-            customUnitRates,
-            unitTranslation,
-            customUnit?.pendingFields?.attributes,
-            policy?.pendingAction,
-            withReadOnlyFallback,
-            updateDistanceRateEnabled,
-        ],
-    );
-
-    const filterRate = useCallback((rate: RateForList, searchInput: string) => {
-        const results = tokenizedSearch([rate], searchInput, (option) => [option.text ?? '']);
-        return results.length > 0;
-    }, []);
-    const sortRates = useCallback((rates: RateForList[]) => rates.sort((a, b) => localeCompare(a.text ?? '', b.text ?? '')), [localeCompare]);
-    const [inputValue, setInputValue, filteredDistanceRatesList] = useSearchResults(distanceRatesList, filterRate, sortRates);
-
     const addRate = () => {
         Navigation.navigate(ROUTES.WORKSPACE_CREATE_DISTANCE_RATE.getRoute(policyID));
     };
@@ -293,10 +219,6 @@ function PolicyDistanceRatesPage({
         Navigation.navigate(ROUTES.WORKSPACE_DISTANCE_RATES_SETTINGS.getRoute(policyID));
     }, [policyID]);
 
-    const openRateDetails = (rate: RateForList) => {
-        Navigation.navigate(ROUTES.WORKSPACE_DISTANCE_RATE_DETAILS.getRoute(policyID, rate.value));
-    };
-
     const disableRates = () => {
         if (customUnit === undefined) {
             return;
@@ -340,40 +262,70 @@ function PolicyDistanceRatesPage({
         setSelectedDistanceRates([]);
     };
 
-    const toggleRate = (rate: RateForList) => {
-        setSelectedDistanceRates((prevSelectedRates) => {
-            if (prevSelectedRates.includes(rate.value)) {
-                return prevSelectedRates.filter((selectedRate) => selectedRate !== rate.value);
+    const dismissErrorByID = useCallback(
+        (rateID: string) => {
+            if (!customUnit?.customUnitID) {
+                return;
             }
-            return [...prevSelectedRates, rate.value];
-        });
-    };
+            if (customUnitRates[rateID]?.errors) {
+                clearDeleteDistanceRateError(policyID, customUnit.customUnitID, rateID);
+                return;
+            }
+            clearCreateDistanceRateItemAndError(policyID, customUnit.customUnitID, rateID);
+        },
+        [customUnit?.customUnitID, customUnitRates, policyID],
+    );
 
-    const toggleAllRates = () => {
-        if (selectedDistanceRates.length > 0) {
-            setSelectedDistanceRates([]);
-        } else {
-            setSelectedDistanceRates(
-                Object.entries(selectableRates)
-                    .filter(([, rate]) => rate.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && filteredDistanceRatesList.some((item) => item.value === rate.customUnitRateID))
-                    .map(([key]) => key),
-            );
-        }
-    };
+    const openRateDetailsByID = useCallback(
+        (rateID: string) => {
+            Navigation.navigate(ROUTES.WORKSPACE_DISTANCE_RATE_DETAILS.getRoute(policyID, rateID));
+        },
+        [policyID],
+    );
 
-    const getCustomListHeader = () => {
-        if (filteredDistanceRatesList.length === 0) {
-            return null;
-        }
-        return (
-            <CustomListHeader
-                canSelectMultiple={canSelectMultiple}
-                leftHeaderText={translate('workspace.distanceRates.rate')}
-                rightHeaderText={translate('common.enabled')}
-                shouldShowRightCaret
-            />
-        );
-    };
+    const ratesData: DistanceRateTableItemData[] = useMemo(
+        () =>
+            Object.values(customUnitRates).map((rate) => {
+                const resolvedPendingAction =
+                    rate.pendingAction ??
+                    rate.pendingFields?.rate ??
+                    rate.pendingFields?.enabled ??
+                    rate.pendingFields?.currency ??
+                    rate.pendingFields?.taxRateExternalID ??
+                    rate.pendingFields?.taxClaimablePercentage ??
+                    rate.pendingFields?.name ??
+                    customUnit?.pendingFields?.attributes ??
+                    (policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? policy?.pendingAction : undefined);
+
+                const isDeleting = resolvedPendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
+
+                return {
+                    keyForList: rate.customUnitRateID,
+                    rateID: rate.customUnitRateID,
+                    rate,
+                    disabled: isDeleting,
+                    enabled: !!rate.enabled,
+                    isLocked: !canWriteDistanceRates || !canDisableOrDeleteRate(rate.customUnitRateID) || isDeleting,
+                    formattedRate: `${convertAmountToDisplayString(rate.rate, rate.currency ?? CONST.CURRENCY.USD)} / ${unitTranslation}`,
+                    pendingAction: resolvedPendingAction ?? undefined,
+                    errors: rate.errors ?? undefined,
+                    action: () => openRateDetailsByID(rate.customUnitRateID),
+                    dismissError: () => dismissErrorByID(rate.customUnitRateID),
+                    onToggleEnabled: (value: boolean) => updateDistanceRateEnabled(value, rate.customUnitRateID),
+                };
+            }),
+        [
+            customUnitRates,
+            unitTranslation,
+            customUnit?.pendingFields?.attributes,
+            policy?.pendingAction,
+            canWriteDistanceRates,
+            canDisableOrDeleteRate,
+            openRateDetailsByID,
+            dismissErrorByID,
+            updateDistanceRateEnabled,
+        ],
+    );
 
     const getBulkActionsButtonOptions = () => {
         const options: Array<DropdownOption<WorkspaceDistanceRatesBulkActionType>> = [
@@ -483,24 +435,6 @@ function PolicyDistanceRatesPage({
 
     const selectionModeHeader = isMobileSelectionModeEnabled && shouldUseNarrowLayout;
 
-    const headerContent = (
-        <>
-            {Object.values(customUnitRates).length > 0 && (
-                <View style={[styles.ph5, styles.pb5, styles.pt3, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
-                    <Text style={[styles.textNormal, styles.colorMuted]}>{translate('workspace.distanceRates.centrallyManage')}</Text>
-                </View>
-            )}
-            {Object.values(customUnitRates).length >= CONST.STANDARD_LIST_ITEM_LIMIT && (
-                <SearchBar
-                    label={translate('workspace.distanceRates.findRate')}
-                    inputValue={inputValue}
-                    onChangeText={setInputValue}
-                    shouldShowEmptyState={filteredDistanceRatesList.length === 0}
-                />
-            )}
-        </>
-    );
-
     return (
         <AccessOrNotFoundWrapper
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
@@ -540,27 +474,20 @@ function PolicyDistanceRatesPage({
                         reasonAttributes={reasonAttributes}
                     />
                 )}
-                {Object.values(customUnitRates).length > 0 && (
-                    <SelectionListWithModal
-                        data={filteredDistanceRatesList}
-                        ListItem={TableListItem}
-                        onSelectRow={openRateDetails}
-                        onSelectionButtonPress={toggleRate}
-                        selectedItems={selectedDistanceRates}
-                        customListHeader={getCustomListHeader()}
-                        onTurnOnSelectionMode={(item) => item && canWriteDistanceRates && toggleRate(item)}
-                        onSelectAll={canWriteDistanceRates && filteredDistanceRatesList.length > 0 ? toggleAllRates : undefined}
-                        shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
-                        customListHeaderContent={headerContent}
-                        canSelectMultiple={canSelectMultiple}
-                        selectAllAccessibilityLabel={translate('accessibilityHints.selectAllDistanceRates')}
-                        onDismissError={dismissError}
-                        shouldShowListEmptyContent={false}
-                        showScrollIndicator={false}
-                        turnOnSelectionModeOnLongPress={canWriteDistanceRates}
-                        shouldHeaderBeInsideList
-                        shouldShowRightCaret
-                    />
+                {!isLoading && (
+                    <>
+                        {ratesData.length > 0 && (
+                            <View style={[styles.ph5, styles.pb5, styles.pt3, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
+                                <Text style={[styles.textNormal, styles.colorMuted]}>{translate('workspace.distanceRates.centrallyManage')}</Text>
+                            </View>
+                        )}
+                        <WorkspaceDistanceRatesTable
+                            ratesData={ratesData}
+                            selectionEnabled={canWriteDistanceRates}
+                            selectedKeys={selectedDistanceRates}
+                            onRowSelectionChange={setSelectedDistanceRates}
+                        />
+                    </>
                 )}
             </ScreenWrapper>
         </AccessOrNotFoundWrapper>
diff --git a/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitPage.tsx b/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitPage.tsx
index 0bf95d3a8088..bc147e051d1b 100644
--- a/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitPage.tsx
+++ b/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitPage.tsx
@@ -124,6 +124,8 @@ function DynamicExpensifyCardLimitPage({route}: DynamicExpensifyCardLimitPagePro
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="DynamicExpensifyCardLimitPage"
diff --git a/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx b/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx
index 6a6dea91a04e..4ae64c0d84e5 100644
--- a/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx
+++ b/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx
@@ -207,6 +207,8 @@ function DynamicExpensifyCardLimitTypePage({route}: WorkspaceEditCardLimitTypePa
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceEditCardLimitTypePage"
diff --git a/src/pages/workspace/expensifyCard/DynamicExpensifyCardNamePage.tsx b/src/pages/workspace/expensifyCard/DynamicExpensifyCardNamePage.tsx
index 93ce3f1365e3..f52022df5c45 100644
--- a/src/pages/workspace/expensifyCard/DynamicExpensifyCardNamePage.tsx
+++ b/src/pages/workspace/expensifyCard/DynamicExpensifyCardNamePage.tsx
@@ -64,6 +64,8 @@ function DynamicExpensifyCardNamePage({route}: DynamicExpensifyCardNamePageProps
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceEditCardNamePage"
diff --git a/src/pages/workspace/expensifyCard/DynamicWorkspaceSettlementAccountPage.tsx b/src/pages/workspace/expensifyCard/DynamicWorkspaceSettlementAccountPage.tsx
index 470233636381..4244ad087ca3 100644
--- a/src/pages/workspace/expensifyCard/DynamicWorkspaceSettlementAccountPage.tsx
+++ b/src/pages/workspace/expensifyCard/DynamicWorkspaceSettlementAccountPage.tsx
@@ -149,6 +149,8 @@ function DynamicWorkspaceSettlementAccountPage({route}: WorkspaceSettlementAccou
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceSettlementAccountPage"
diff --git a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx
index 799909b471ea..dc7b2d0ef641 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx
@@ -55,6 +55,8 @@ function WorkspaceCardSettingsPage({route}: WorkspaceCardSettingsPageProps) {
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCardSettingsPage"
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx
index e988e0fccb83..337f88eba11c 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx
@@ -123,6 +123,8 @@ function WorkspaceExpensifyCardAddWorkEmailPage({route}: WorkspaceExpensifyCardA
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceExpensifyCardAddWorkEmailPage"
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
index 1b2d2afb3f38..65497407c1db 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
@@ -20,7 +20,7 @@ import {getLastFourDigits} from '@libs/BankAccountUtils';
 import {getEligibleBankAccountsForCard, getEligibleBankAccountsForUkEuCard} from '@libs/CardUtils';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import {canMemberWrite} from '@libs/PolicyUtils';
+import {canEditWorkspaceSettings} from '@libs/PolicyUtils';
 import Navigation from '@navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
@@ -38,11 +38,11 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const [bankAccountsList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
+    const {login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
 
     const policyID = route?.params?.policyID;
     const policy = usePolicy(policyID);
-    const {login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
-    const canWriteExpensifyCard = canMemberWrite(policy, currentUserLogin, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD);
+    const canStartBankAccountSetup = canEditWorkspaceSettings(policy, currentUserLogin);
 
     const isUkEuCurrencySupported = useExpensifyCardUkEuSupported(policyID);
 
@@ -122,7 +122,7 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
         }
         setIssueNewCardStepAndData({policyID, isChangeAssigneeDisabled: false});
         Navigation.dismissModal();
-        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path));
+        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID)));
     };
 
     const getHeaderButtonText = () => {
@@ -143,7 +143,8 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
-            shouldBeBlocked={!canWriteExpensifyCard}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+            shouldBeBlocked={!canStartBankAccountSetup}
         >
             <ScreenWrapper
                 testID="WorkspaceExpensifyCardBankAccounts"
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx
index 2f5c7c024a3d..c79f93c8a175 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx
@@ -24,7 +24,6 @@ import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDefaultFundID from '@hooks/useDefaultFundID';
 import useDynamicBackPath from '@hooks/useDynamicBackPath';
-import useEnvironment from '@hooks/useEnvironment';
 import useExpensifyCardFeeds from '@hooks/useExpensifyCardFeeds';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -75,7 +74,6 @@ function getLimitHintTranslationKey(limitType?: string): LimitHintTranslationKey
 }
 
 function WorkspaceExpensifyCardDetailsPage({route}: WorkspaceExpensifyCardDetailsPageProps) {
-    const {isProduction} = useEnvironment();
     const navigation = useNavigation<NavigationProp<SettingsNavigatorParamList>>();
     const {policyID, cardID, backTo} = route.params;
     const backPath = useDynamicBackPath(DYNAMIC_ROUTES.EXPENSIFY_CARD_DETAILS.path);
@@ -348,7 +346,7 @@ function WorkspaceExpensifyCardDetailsPage({route}: WorkspaceExpensifyCardDetail
                         interactive={false}
                         titleStyle={styles.walletCardNumber}
                     />
-                    {!isProduction && spendRulesSummary.length > 0 && (
+                    {spendRulesSummary.length > 0 && (
                         <MenuItemWithTopDescription
                             interactive={false}
                             description={translate('cardPage.spendRules')}
@@ -387,7 +385,7 @@ function WorkspaceExpensifyCardDetailsPage({route}: WorkspaceExpensifyCardDetail
                     </OfflineWithFeedback>
 
                     <View style={styles.mt6}>
-                        {!isProduction && canWriteExpensifyCard && (
+                        {canWriteExpensifyCard && (
                             <MenuItem
                                 icon={expensifyIcons.CreditCardLock}
                                 title={translate('cardPage.editSpendRules')}
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx
index bfc7f4207608..5ee035f30560 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx
@@ -107,7 +107,7 @@ function WorkspaceExpensifyCardFeedSelectorPage({route}: WorkspaceExpensifyCardF
         }
         updateSelectedExpensifyCardFeed(issueCardFundID, policyID);
         setIssueNewCardStepAndData({policyID, isChangeAssigneeDisabled: false});
-        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path));
+        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID)));
     };
 
     /** When there is no primary feed for this workspace, mirror empty-state flow: bank account / new program setup (same as WORKSPACE_EXPENSIFY_CARD_BANK_ACCOUNT). */
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
index 8ca4c6bdfc36..299a7c2d4c17 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
@@ -167,7 +167,7 @@ function WorkspaceExpensifyCardListPage({route, cardsList, fundID}: WorkspaceExp
             return;
         }
         setIssueNewCardStepAndData({policyID, isChangeAssigneeDisabled: false});
-        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path));
+        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID)));
     };
     const secondaryActions = canWriteExpensifyCard
         ? [
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
index d90179f83ca4..1dedcb23d1b0 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
@@ -7,6 +7,7 @@ import {useLockedAccountActions, useLockedAccountState} from '@components/Locked
 import {ModalActions} from '@components/Modal/Global/ModalContext';
 import Text from '@components/Text';
 import useConfirmModal from '@hooks/useConfirmModal';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useExpensifyCardUkEuSupported from '@hooks/useExpensifyCardUkEuSupported';
 import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -21,6 +22,7 @@ import {getEligibleBankAccountsForCard, getEligibleBankAccountsForUkEuCard} from
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
+import {canEditWorkspaceSettings} from '@libs/PolicyUtils';
 import {hasInProgressUSDVBBA} from '@libs/ReimbursementAccountUtils';
 import Navigation from '@navigation/Navigation';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
@@ -52,6 +54,7 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
     const {isAccountLocked} = useLockedAccountState();
     const {showLockedAccountModal} = useLockedAccountActions();
     const {canWrite: canWriteExpensifyCard, showReadOnlyModal} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD);
+    const {login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
 
     // Dismiss the "Update to USD" modal if the currency changes to USD externally (e.g. from another device)
     const isCurrencyModalOpen = useRef(false);
@@ -67,9 +70,12 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
     const isUkEuCurrencySupported = useExpensifyCardUkEuSupported(policy?.id);
 
     const eligibleBankAccounts = isUkEuCurrencySupported ? getEligibleBankAccountsForUkEuCard(bankAccountList, policy?.outputCurrency) : getEligibleBankAccountsForCard(bankAccountList);
+    const shouldStartBankAccountSetup = !eligibleBankAccounts.length || isSetupUnfinished;
+    const canStartBankAccountSetup = canEditWorkspaceSettings(policy, currentUserLogin);
+    const shouldDisableCTA = !canWriteExpensifyCard || (shouldStartBankAccountSetup && !canStartBankAccountSetup);
 
     const startFlow = () => {
-        if (!eligibleBankAccounts.length || isSetupUnfinished) {
+        if (shouldStartBankAccountSetup) {
             Navigation.navigate(
                 ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
                     policyID: policy?.id,
@@ -78,7 +84,7 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
             );
         } else if (policy?.id) {
             clearIssueNewCardFormData();
-            Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_SELECT_FEED.path));
+            Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_SELECT_FEED.path, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policy.id)));
         }
     };
 
@@ -137,6 +143,10 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
                             showReadOnlyModal();
                             return;
                         }
+                        if (shouldStartBankAccountSetup && !canStartBankAccountSetup) {
+                            showReadOnlyModal();
+                            return;
+                        }
                         if (isDelegateAccessRestricted) {
                             showDelegateNoAccessModal();
                             return;
@@ -155,8 +165,8 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
                     illustration={illustrations.ExpensifyCardIllustration}
                     illustrationStyle={styles.expensifyCardIllustrationContainer}
                     titleStyles={styles.textHeadlineH1}
-                    buttonInnerStyles={!canWriteExpensifyCard ? styles.buttonOpacityDisabled : undefined}
-                    buttonHoverStyles={!canWriteExpensifyCard ? styles.buttonOpacityDisabled : undefined}
+                    buttonInnerStyles={shouldDisableCTA ? styles.buttonOpacityDisabled : undefined}
+                    buttonHoverStyles={shouldDisableCTA ? styles.buttonOpacityDisabled : undefined}
                 />
             </View>
             <View style={[shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardVerifyWorkAccountPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardVerifyWorkAccountPage.tsx
index 9e6aaba317d7..8851d04f6e0a 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardVerifyWorkAccountPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardVerifyWorkAccountPage.tsx
@@ -9,6 +9,7 @@ import {expensifyLoginsSelector} from '@libs/UserUtils';
 import Navigation from '@navigation/Navigation';
 import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {linkCardFeedToPolicy} from '@userActions/CompanyCards';
 import {clearGetAccessiblePoliciesErrors, getAccessiblePolicies} from '@userActions/Policy/Policy';
 import {resendValidateCode} from '@userActions/User';
@@ -20,7 +21,9 @@ import type {Errors} from '@src/types/onyx/OnyxCommon';
 
 type WorkspaceExpensifyCardVerifyWorkAccountPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.EXPENSIFY_CARD_VERIFY_WORK_EMAIL>;
 
-function WorkspaceExpensifyCardVerifyWorkAccountPage({route}: WorkspaceExpensifyCardVerifyWorkAccountPageProps) {
+type WorkspaceExpensifyCardVerifyWorkAccountPageContentProps = Pick<WorkspaceExpensifyCardVerifyWorkAccountPageProps, 'route'>;
+
+function WorkspaceExpensifyCardVerifyWorkAccountPageContent({route}: WorkspaceExpensifyCardVerifyWorkAccountPageContentProps) {
     const {policyID, fundID} = route.params;
     const {translate} = useLocalize();
     const [loginList] = useOnyx(ONYXKEYS.LOGINS, {selector: expensifyLoginsSelector});
@@ -78,4 +81,19 @@ function WorkspaceExpensifyCardVerifyWorkAccountPage({route}: WorkspaceExpensify
     );
 }
 
+function WorkspaceExpensifyCardVerifyWorkAccountPage({route}: WorkspaceExpensifyCardVerifyWorkAccountPageProps) {
+    const {policyID} = route.params;
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <WorkspaceExpensifyCardVerifyWorkAccountPageContent route={route} />
+        </AccessOrNotFoundWrapper>
+    );
+}
+
 export default WorkspaceExpensifyCardVerifyWorkAccountPage;
diff --git a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx
index 73e009e2da25..1d3dcbf85d13 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx
@@ -73,6 +73,8 @@ function WorkspaceSettlementFrequencyPage({route}: WorkspaceSettlementFrequencyP
             policyID={policyID}
             shouldBeBlocked={isSettlementFrequencyBlocked}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceSettlementFrequencyPage"
diff --git a/src/pages/workspace/expensifyCard/issueNew/CardNameStep.tsx b/src/pages/workspace/expensifyCard/issueNew/CardNameStep.tsx
index 4ac929ff30b8..aa353727b596 100644
--- a/src/pages/workspace/expensifyCard/issueNew/CardNameStep.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/CardNameStep.tsx
@@ -6,7 +6,6 @@ import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import Text from '@components/Text';
 import TextInput from '@components/TextInput';
 import useAutoFocusInput from '@hooks/useAutoFocusInput';
-import useEnvironment from '@hooks/useEnvironment';
 import useIsInLandscapeMode from '@hooks/useIsInLandscapeMode';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
@@ -36,7 +35,6 @@ type CardNameStepProps = {
 function CardNameStep({policyID, stepNames, startStepIndex}: CardNameStepProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const {isProduction} = useEnvironment();
     const {inputCallbackRef} = useAutoFocusInput();
     const isInLandscapeMode = useIsInLandscapeMode();
 
@@ -46,7 +44,7 @@ function CardNameStep({policyID, stepNames, startStepIndex}: CardNameStepProps)
     const isEditing = issueNewCard?.isEditing;
     const data = issueNewCard?.data;
     const isVirtualCard = data?.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.VIRTUAL;
-    const isSpendRuleAvailable = !isProduction && isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
+    const areSpendRulesAvailable = isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
 
     const userName = getUserNameByEmail(data?.assigneeEmail ?? '', 'firstName');
     const defaultCardTitle = !isVirtualCard ? getDefaultCardName(userName) : '';
@@ -84,14 +82,14 @@ function CardNameStep({policyID, stepNames, startStepIndex}: CardNameStepProps)
                 setIssueNewCardStepAndData({step: CONST.EXPENSIFY_CARD.STEP.CONFIRMATION, isEditing: false, policyID});
                 return;
             }
-            if (isVirtualCard || isSpendRuleAvailable) {
+            if (isVirtualCard || areSpendRulesAvailable) {
                 setIssueNewCardStepAndData({step: CONST.EXPENSIFY_CARD.STEP.SPEND_RULES, policyID});
                 return;
             }
 
             setIssueNewCardStepAndData({step: CONST.EXPENSIFY_CARD.STEP.LIMIT_TYPE, policyID});
         });
-    }, [isEditing, isSpendRuleAvailable, isVirtualCard, policyID]);
+    }, [isEditing, areSpendRulesAvailable, isVirtualCard, policyID]);
 
     return (
         <InteractiveStepWrapper
diff --git a/src/pages/workspace/expensifyCard/issueNew/ConfirmationStep.tsx b/src/pages/workspace/expensifyCard/issueNew/ConfirmationStep.tsx
index 941d256b7622..698fc8bf462b 100644
--- a/src/pages/workspace/expensifyCard/issueNew/ConfirmationStep.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/ConfirmationStep.tsx
@@ -20,6 +20,7 @@ import {getTranslationKeyForLimitType} from '@libs/CardUtils';
 import {convertToShortDisplayString} from '@libs/CurrencyUtils';
 import {getLatestErrorMessage} from '@libs/ErrorUtils';
 import {getUserNameByEmail} from '@libs/PersonalDetailsUtils';
+import {isPolicyFeatureEnabled} from '@libs/PolicyUtils';
 import createDynamicRoute from '@navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@navigation/Navigation';
 import CONST from '@src/CONST';
@@ -53,6 +54,7 @@ function ConfirmationStep({policyID, stepNames, startStepIndex}: ConfirmationSte
     const isSuccessful = issueNewCard?.isSuccessful;
     const hasApprovalError = !!policy?.errorFields?.approvalMode;
     const isSpendRuleApplied = !!issueNewCard?.data.spendRuleEnabled;
+    const areRulesEnabled = isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
     const isAddApprovalEnabled = policy?.approvalMode !== CONST.POLICY.APPROVAL_MODE.OPTIONAL && !hasApprovalError;
     const shouldDisableSubmitButton = !isAddApprovalEnabled && data?.limitType === CONST.EXPENSIFY_CARD.LIMIT_TYPES.SMART;
     const personalDetails = usePersonalDetails();
@@ -206,7 +208,7 @@ function ConfirmationStep({policyID, stepNames, startStepIndex}: ConfirmationSte
                         onPress={() => editStep(CONST.EXPENSIFY_CARD.STEP.SPEND_RULES)}
                     />
                 )}
-                {isSpendRuleApplied && (
+                {isSpendRuleApplied && areRulesEnabled && (
                     <MenuItemWithTopDescription
                         description={translate('common.restrictions')}
                         title={cardRuleRestrictionsTitle}
diff --git a/src/pages/workspace/expensifyCard/issueNew/DynamicIssueNewCardPage.tsx b/src/pages/workspace/expensifyCard/issueNew/DynamicIssueNewCardPage.tsx
index 69cb37a518d4..ae712023367f 100644
--- a/src/pages/workspace/expensifyCard/issueNew/DynamicIssueNewCardPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/DynamicIssueNewCardPage.tsx
@@ -147,9 +147,10 @@ function DynamicIssueNewCardPage({policy, route}: IssueNewCardPageProps) {
 
     return (
         <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             {getCurrentStep()}
         </AccessOrNotFoundWrapper>
diff --git a/src/pages/workspace/expensifyCard/issueNew/IssueNewCardConfirmMagicCodePage.tsx b/src/pages/workspace/expensifyCard/issueNew/IssueNewCardConfirmMagicCodePage.tsx
index 727338e86a6f..2c15aad2bdb8 100644
--- a/src/pages/workspace/expensifyCard/issueNew/IssueNewCardConfirmMagicCodePage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/IssueNewCardConfirmMagicCodePage.tsx
@@ -13,6 +13,7 @@ import {getLatestErrorMessageField} from '@libs/ErrorUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Route} from '@src/ROUTES';
@@ -68,17 +69,24 @@ function IssueNewCardConfirmMagicCodePage({route}: IssueNewCardConfirmMagicCodeP
     }, [backPath]);
 
     return (
-        <ValidateCodeActionContent
-            isLoading={issueNewCard?.isLoading}
-            title={translate('cardPage.validateCardTitle')}
-            descriptionPrimary={translate('cardPage.enterMagicCode', primaryLogin)}
-            sendValidateCode={() => requestValidateCodeAction()}
-            validateCodeActionErrorField={data?.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.PHYSICAL ? 'createExpensifyCard' : 'createAdminIssuedVirtualCard'}
-            handleSubmitForm={handleSubmit}
-            validateError={validateError}
-            clearError={() => clearIssueNewCardError(policyID)}
-            onClose={handleClose}
-        />
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <ValidateCodeActionContent
+                isLoading={issueNewCard?.isLoading}
+                title={translate('cardPage.validateCardTitle')}
+                descriptionPrimary={translate('cardPage.enterMagicCode', primaryLogin)}
+                sendValidateCode={() => requestValidateCodeAction()}
+                validateCodeActionErrorField={data?.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.PHYSICAL ? 'createExpensifyCard' : 'createAdminIssuedVirtualCard'}
+                handleSubmitForm={handleSubmit}
+                validateError={validateError}
+                clearError={() => clearIssueNewCardError(policyID)}
+                onClose={handleClose}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/expensifyCard/issueNew/LimitTypeStep.tsx b/src/pages/workspace/expensifyCard/issueNew/LimitTypeStep.tsx
index 4e1b4f7cbf8d..9a0d269cb92b 100644
--- a/src/pages/workspace/expensifyCard/issueNew/LimitTypeStep.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/LimitTypeStep.tsx
@@ -8,7 +8,6 @@ import type {FormInputErrors, FormOnyxValues, FormRef} from '@components/Form/ty
 import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import Text from '@components/Text';
 import ValuePicker from '@components/ValuePicker';
-import useEnvironment from '@hooks/useEnvironment';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -38,7 +37,6 @@ type LimitTypeStepProps = {
 function LimitTypeStep({policy, stepNames, startStepIndex}: LimitTypeStepProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const {isProduction} = useEnvironment();
 
     const policyID = policy?.id;
     const formRef = useRef<FormRef | null>(null);
@@ -50,17 +48,17 @@ function LimitTypeStep({policy, stepNames, startStepIndex}: LimitTypeStepProps)
     const [typeSelected, setTypeSelected] = useState(issueNewCard?.data?.limitType ?? defaultType);
 
     const isEditing = issueNewCard?.isEditing;
-    const isSpendRuleAvailable = !isProduction && isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
+    const areSpendRulesAvailable = isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
 
     const nextStep = useMemo(() => {
         if (isEditing) {
             return CONST.EXPENSIFY_CARD.STEP.CONFIRMATION;
         }
-        if (isSpendRuleAvailable || issueNewCard?.data.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.VIRTUAL) {
+        if (areSpendRulesAvailable || issueNewCard?.data.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.VIRTUAL) {
             return CONST.EXPENSIFY_CARD.STEP.SPEND_RULES;
         }
         return CONST.EXPENSIFY_CARD.STEP.CARD_NAME;
-    }, [isSpendRuleAvailable, isEditing, issueNewCard?.data.cardType]);
+    }, [areSpendRulesAvailable, isEditing, issueNewCard?.data.cardType]);
 
     const onInputFocus = useCallback(() => {
         formRef.current?.scrollToEnd();
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx
index de4390f202db..f0ba776f0de6 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx
@@ -14,7 +14,6 @@ import SpendRuleRestrictionTypeToggle from '@components/SpendRules/SpendRuleRest
 import TabSelectorBase from '@components/TabSelector/TabSelectorBase';
 import Text from '@components/Text';
 import useDefaultFundID from '@hooks/useDefaultFundID';
-import useEnvironment from '@hooks/useEnvironment';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
@@ -45,7 +44,6 @@ type SetSpendRulesStepProps = {
 function SetSpendRulesStep({policyID, stepNames, startStepIndex}: SetSpendRulesStepProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const {isProduction} = useEnvironment();
     const personalDetails = usePersonalDetails();
     const domainAccountID = useDefaultFundID(policyID);
     const icons = useMemoizedLazyExpensifyIcons(['Copy', 'Pencil']);
@@ -59,7 +57,7 @@ function SetSpendRulesStep({policyID, stepNames, startStepIndex}: SetSpendRulesS
     const isEditing = issueNewCard?.isEditing;
     const currencyCode = issueNewCard?.data?.currency ?? CONST.CURRENCY.USD;
     const isVirtualCard = issueNewCard?.data?.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.VIRTUAL;
-    const isSpendRuleVisible = !isProduction && isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
+    const isSpendRuleVisible = isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
 
     const spendRuleID = issueNewCard?.data?.spendRuleID;
     const spendRuleForm = issueNewCard?.data.spendRuleValue ?? {};
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleCategoryPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleCategoryPage.tsx
index d86618d85ce9..c5350c8dfb20 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleCategoryPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleCategoryPage.tsx
@@ -4,6 +4,8 @@ import useOnyx from '@hooks/useOnyx';
 import {setIssueNewCardData} from '@libs/actions/Card';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
 import type {SpendRuleCategory} from '@src/types/form/SpendRuleForm';
@@ -21,9 +23,16 @@ export default function SpendRuleCategoryEditPage({route}: SpendRuleCategoryEdit
     };
 
     return (
-        <SpendRuleCategoryBase
-            categories={categories}
-            onCategoriesChange={handleCategoriesChange}
-        />
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SpendRuleCategoryBase
+                categories={categories}
+                onCategoriesChange={handleCategoriesChange}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMaxAmountPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMaxAmountPage.tsx
index be76686b73a6..88d78a083ba4 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMaxAmountPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMaxAmountPage.tsx
@@ -4,6 +4,7 @@ import useOnyx from '@hooks/useOnyx';
 import {setIssueNewCardData} from '@libs/actions/Card';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
@@ -22,11 +23,18 @@ export default function SpendRuleMaxAmountPage({route}: SpendRuleMaxAmountPagePr
     };
 
     return (
-        <SpendRuleMaxAmountBase
+        <AccessOrNotFoundWrapper
             policyID={policyID}
-            maxAmount={defaultValue}
-            currencyCode={selectedCurrency}
-            onMaxAmountChange={handleMaxAmountChange}
-        />
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SpendRuleMaxAmountBase
+                policyID={policyID}
+                maxAmount={defaultValue}
+                currencyCode={selectedCurrency}
+                onMaxAmountChange={handleMaxAmountChange}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantEditPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantEditPage.tsx
index 2f1811b53616..1f6e28b424fd 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantEditPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantEditPage.tsx
@@ -4,6 +4,8 @@ import useOnyx from '@hooks/useOnyx';
 import {setIssueNewCardData} from '@libs/actions/Card';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
 
@@ -17,14 +19,21 @@ export default function SpendRuleMerchantEditPage({route}: SpendRuleMerchantEdit
     const merchantMatchTypes = issueNewCardForm?.data.spendRuleValue?.merchantMatchTypes ?? [];
 
     return (
-        <SpendRuleMerchantEditBase
+        <AccessOrNotFoundWrapper
             policyID={policyID}
-            merchantIndex={merchantIndex}
-            merchantMatchTypes={merchantMatchTypes}
-            merchantNames={merchantNames}
-            onMerchantDataChange={(newMerchantNames, newMerchantMatchTypes) => {
-                setIssueNewCardData(policyID, {spendRuleValue: {merchantNames: newMerchantNames, merchantMatchTypes: newMerchantMatchTypes}});
-            }}
-        />
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SpendRuleMerchantEditBase
+                policyID={policyID}
+                merchantIndex={merchantIndex}
+                merchantMatchTypes={merchantMatchTypes}
+                merchantNames={merchantNames}
+                onMerchantDataChange={(newMerchantNames, newMerchantMatchTypes) => {
+                    setIssueNewCardData(policyID, {spendRuleValue: {merchantNames: newMerchantNames, merchantMatchTypes: newMerchantMatchTypes}});
+                }}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantsPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantsPage.tsx
index 0a2dfe21423d..de812a119d02 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantsPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantsPage.tsx
@@ -4,6 +4,7 @@ import useOnyx from '@hooks/useOnyx';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import {DYNAMIC_ROUTES} from '@src/ROUTES';
@@ -20,12 +21,19 @@ export default function SpendRuleMerchantsPage({route}: SpendRuleMerchantsPagePr
     const restrictionAction = issueNewCardForm?.data.spendRuleValue?.restrictionAction ?? CONST.SPEND_RULES.ACTION.ALLOW;
 
     return (
-        <SpendRuleMerchantsBase
+        <AccessOrNotFoundWrapper
             policyID={policyID}
-            action={restrictionAction}
-            merchantNames={merchantNames}
-            merchantMatchTypes={merchantMatchTypes}
-            getEditMerchantRoute={(merchantIndex) => createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_MERCHANT_EDIT.getRoute(merchantIndex))}
-        />
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SpendRuleMerchantsBase
+                policyID={policyID}
+                action={restrictionAction}
+                merchantNames={merchantNames}
+                merchantMatchTypes={merchantMatchTypes}
+                getEditMerchantRoute={(merchantIndex) => createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_MERCHANT_EDIT.getRoute(merchantIndex))}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage.tsx
index f373983e35f6..54c055ad7002 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage.tsx
@@ -115,6 +115,8 @@ function SpendRuleSelectionPage({route}: SpendRuleSelectionPageProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="SpendRuleSelectionPage"
diff --git a/src/pages/workspace/fields/CreateFieldsPage.tsx b/src/pages/workspace/fields/CreateFieldsPage.tsx
deleted file mode 100644
index 31e063ec3206..000000000000
--- a/src/pages/workspace/fields/CreateFieldsPage.tsx
+++ /dev/null
@@ -1,284 +0,0 @@
-import React, {useCallback, useEffect, useMemo, useRef} from 'react';
-import {View} from 'react-native';
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import FormProvider from '@components/Form/FormProvider';
-import InputWrapper from '@components/Form/InputWrapper';
-import type {FormInputErrors, FormOnyxValues, FormRef} from '@components/Form/types';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
-import ScreenWrapper from '@components/ScreenWrapper';
-import TextPicker from '@components/TextPicker';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import useThemeStyles from '@hooks/useThemeStyles';
-import DateUtils from '@libs/DateUtils';
-import {addErrorMessage} from '@libs/ErrorUtils';
-import {hasCircularReferences} from '@libs/Formula';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections} from '@libs/PolicyUtils';
-import {isRequiredFulfilled} from '@libs/ValidationUtils';
-import {getUnsupportedReportFieldFormulaParts, hasFormulaPartsInInitialValue, isReportFieldNameExisting} from '@libs/WorkspaceReportFieldUtils';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import InitialListValueSelector from '@pages/workspace/reports/InitialListValueSelector';
-import TypeSelector from '@pages/workspace/reports/TypeSelector';
-import {createReportField, setInitialCreateReportFieldsForm} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {Route as Routes} from '@src/ROUTES';
-import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
-import type {Policy, Report} from '@src/types/onyx';
-
-type CreateFieldsPageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    isInvoiceField: boolean;
-    listValuesRoute: Routes;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    testID: string;
-};
-
-const defaultDate = DateUtils.extractDate(new Date().toString());
-
-function CreateFieldsPage({policy, policyID, isInvoiceField, listValuesRoute, featureName, testID}: CreateFieldsPageProps) {
-    const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
-    const formRef = useRef<FormRef>(null);
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-
-    const reportTypeForTarget = useMemo(() => (isInvoiceField ? CONST.REPORT.TYPE.INVOICE : CONST.REPORT.TYPE.EXPENSE), [isInvoiceField]);
-    const fieldTarget = useMemo(() => (isInvoiceField ? CONST.REPORT_FIELD_TARGETS.INVOICE : CONST.REPORT_FIELD_TARGETS.EXPENSE), [isInvoiceField]);
-
-    const policyReportIDsSelector = useCallback(
-        (reports: OnyxCollection<Report>) =>
-            Object.values(reports ?? {})
-                .filter((report) => report?.policyID === policyID && report.type === reportTypeForTarget)
-                .map((report) => report?.reportID),
-        [policyID, reportTypeForTarget],
-    );
-
-    const [policyReportIDs] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: policyReportIDsSelector});
-
-    const availableListValuesLength = (formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? []).filter((disabledListValue) => !disabledListValue).length;
-
-    const submitForm = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
-            const shouldClearListInitialValue = values[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength === 0;
-            createReportField({
-                policy,
-                name: values[INPUT_IDS.NAME],
-                type: values[INPUT_IDS.TYPE],
-                initialValue: shouldClearListInitialValue ? '' : values[INPUT_IDS.INITIAL_VALUE],
-                listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
-                disabledListValues: formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? [],
-                policyReportIDs,
-                isInvoiceField,
-            });
-            Navigation.goBack();
-        },
-        [availableListValuesLength, formDraft, isInvoiceField, policy, policyReportIDs],
-    );
-
-    const validateForm = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> => {
-            const {name, type, initialValue: formInitialValue} = values;
-            const errors: FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> = {};
-
-            if (!isRequiredFulfilled(name)) {
-                errors[INPUT_IDS.NAME] = translate(isInvoiceField ? 'workspace.invoiceFields.invoiceFieldNameRequiredError' : 'workspace.reportFields.reportFieldNameRequiredError');
-            } else if (isReportFieldNameExisting(policy?.fieldList, name, fieldTarget)) {
-                errors[INPUT_IDS.NAME] = translate(isInvoiceField ? 'workspace.invoiceFields.existingInvoiceFieldNameError' : 'workspace.reportFields.existingReportFieldNameError');
-            } else if ([...name].length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
-                addErrorMessage(errors, INPUT_IDS.NAME, translate('common.error.characterLimitExceedCounter', [...name].length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH));
-            }
-
-            if (!isRequiredFulfilled(type)) {
-                errors[INPUT_IDS.TYPE] = translate(isInvoiceField ? 'workspace.invoiceFields.invoiceFieldTypeRequiredError' : 'workspace.reportFields.reportFieldTypeRequiredError');
-            }
-
-            if (type === CONST.REPORT_FIELD_TYPES.TEXT && !!formInitialValue && formInitialValue.length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate('common.error.characterLimitExceedCounter', formInitialValue.length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH);
-            }
-
-            if ((type === CONST.REPORT_FIELD_TYPES.TEXT || type === CONST.REPORT_FIELD_TYPES.FORMULA) && hasCircularReferences(formInitialValue, name, policy?.fieldList)) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.circularReferenceError');
-            }
-
-            if ((type === CONST.REPORT_FIELD_TYPES.TEXT || type === CONST.REPORT_FIELD_TYPES.FORMULA) && !!formInitialValue && !errors[INPUT_IDS.INITIAL_VALUE]) {
-                const unsupportedFormulaParts = getUnsupportedReportFieldFormulaParts(formInitialValue);
-                if (unsupportedFormulaParts.length > 0) {
-                    errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.unsupportedFormulaValueError', {
-                        value: unsupportedFormulaParts.join(', '),
-                    });
-                }
-            }
-
-            if (type === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && !isRequiredFulfilled(formInitialValue)) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate(
-                    isInvoiceField ? 'workspace.invoiceFields.invoiceFieldInitialValueRequiredError' : 'workspace.reportFields.reportFieldInitialValueRequiredError',
-                );
-            }
-
-            return errors;
-        },
-        [availableListValuesLength, fieldTarget, isInvoiceField, policy?.fieldList, translate],
-    );
-
-    const validateName = useCallback(
-        (values: Record<string, string>) => {
-            const errors: Record<string, string> = {};
-            const name = values[INPUT_IDS.NAME];
-            if (isReportFieldNameExisting(policy?.fieldList, name, fieldTarget)) {
-                errors[INPUT_IDS.NAME] = translate(isInvoiceField ? 'workspace.invoiceFields.existingInvoiceFieldNameError' : 'workspace.reportFields.existingReportFieldNameError');
-            }
-            return errors;
-        },
-        [fieldTarget, isInvoiceField, policy?.fieldList, translate],
-    );
-
-    const handleOnValueCommitted = useCallback(
-        (inputValues: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => (initialValue: string) => {
-            const isFormula = hasFormulaPartsInInitialValue(initialValue);
-            if (isFormula) {
-                formRef.current?.resetForm({
-                    ...inputValues,
-                    [INPUT_IDS.TYPE]: CONST.REPORT_FIELD_TYPES.FORMULA,
-                    [INPUT_IDS.INITIAL_VALUE]: initialValue,
-                });
-            } else {
-                formRef.current?.resetForm({
-                    ...inputValues,
-                    [INPUT_IDS.TYPE]: CONST.REPORT_FIELD_TYPES.TEXT,
-                    [INPUT_IDS.INITIAL_VALUE]: initialValue,
-                });
-            }
-        },
-        [],
-    );
-
-    useEffect(() => {
-        setInitialCreateReportFieldsForm();
-    }, []);
-
-    const listValues = [...(formDraft?.[INPUT_IDS.LIST_VALUES] ?? [])].sort(localeCompare).join(', ');
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            shouldBeBlocked={hasAccountingConnections(policy)}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate(isInvoiceField ? 'workspace.invoiceFields.addField' : 'workspace.reportFields.addField')}
-                    onBackButtonPress={Navigation.goBack}
-                />
-                <FormProvider
-                    ref={formRef}
-                    style={[styles.mh5, styles.flex1]}
-                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
-                    onSubmit={submitForm}
-                    validate={validateForm}
-                    submitButtonText={translate('common.save')}
-                    enabledWhenOffline
-                    shouldValidateOnBlur={false}
-                    addBottomSafeAreaPadding
-                    shouldUseStrictHtmlTagValidation
-                >
-                    {({inputValues}) => (
-                        <View style={styles.mhn5}>
-                            <InputWrapper
-                                InputComponent={TextPicker}
-                                inputID={INPUT_IDS.NAME}
-                                label={translate('common.name')}
-                                subtitle={translate(isInvoiceField ? 'workspace.invoiceFields.nameInputSubtitle' : 'workspace.reportFields.nameInputSubtitle')}
-                                description={translate('common.name')}
-                                rightLabel={translate('common.required')}
-                                accessibilityLabel={translate('workspace.editor.nameInputLabel')}
-                                maxLength={CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH}
-                                multiline={false}
-                                role={CONST.ROLE.PRESENTATION}
-                                required
-                                customValidate={validateName}
-                                shouldUseStrictHtmlTagValidation
-                            />
-                            <InputWrapper
-                                InputComponent={TypeSelector}
-                                inputID={INPUT_IDS.TYPE}
-                                label={translate('common.type')}
-                                subtitle={translate(isInvoiceField ? 'workspace.invoiceFields.typeInputSubtitle' : 'workspace.reportFields.typeInputSubtitle')}
-                                rightLabel={translate('common.required')}
-                                onTypeSelected={(type) => {
-                                    let initialValue;
-                                    if (type === CONST.REPORT_FIELD_TYPES.DATE) {
-                                        initialValue = defaultDate;
-                                    } else if (type === CONST.REPORT_FIELD_TYPES.FORMULA) {
-                                        initialValue = '{report:id}';
-                                    } else {
-                                        initialValue = '';
-                                    }
-
-                                    formRef.current?.resetForm({
-                                        ...inputValues,
-                                        type,
-                                        initialValue,
-                                    });
-                                }}
-                            />
-
-                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && (
-                                <MenuItemWithTopDescription
-                                    description={translate('workspace.reportFields.listValues')}
-                                    shouldShowRightIcon
-                                    onPress={() => Navigation.navigate(listValuesRoute)}
-                                    title={listValues}
-                                    numberOfLinesTitle={5}
-                                />
-                            )}
-
-                            {(inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.TEXT || inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.FORMULA) && (
-                                <InputWrapper
-                                    InputComponent={TextPicker}
-                                    inputID={INPUT_IDS.INITIAL_VALUE}
-                                    label={translate('common.initialValue')}
-                                    subtitle={translate(isInvoiceField ? 'workspace.invoiceFields.initialValueInputSubtitle' : 'workspace.reportFields.initialValueInputSubtitle')}
-                                    description={translate('common.initialValue')}
-                                    accessibilityLabel={translate('workspace.editor.initialValueInputLabel')}
-                                    maxLength={CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH}
-                                    multiline={false}
-                                    role={CONST.ROLE.PRESENTATION}
-                                    onValueCommitted={handleOnValueCommitted(inputValues)}
-                                />
-                            )}
-
-                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.DATE && (
-                                <MenuItemWithTopDescription
-                                    description={translate('common.initialValue')}
-                                    title={translate('common.currentDate')}
-                                    rightLabel={translate('common.required')}
-                                    interactive={false}
-                                />
-                            )}
-
-                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && (
-                                <InputWrapper
-                                    InputComponent={InitialListValueSelector}
-                                    inputID={INPUT_IDS.INITIAL_VALUE}
-                                    label={translate('common.initialValue')}
-                                />
-                            )}
-                        </View>
-                    )}
-                </FormProvider>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default CreateFieldsPage;
diff --git a/src/pages/workspace/fields/FieldsAddListValuePage.tsx b/src/pages/workspace/fields/FieldsAddListValuePage.tsx
deleted file mode 100644
index 48bceb9f0166..000000000000
--- a/src/pages/workspace/fields/FieldsAddListValuePage.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-import React, {useCallback, useMemo} from 'react';
-import {Keyboard} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import FormProvider from '@components/Form/FormProvider';
-import InputWrapper from '@components/Form/InputWrapper';
-import type {FormOnyxValues} from '@components/Form/types';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import ScreenWrapper from '@components/ScreenWrapper';
-import TextInput from '@components/TextInput';
-import useAutoFocusInput from '@hooks/useAutoFocusInput';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useThemeStyles from '@hooks/useThemeStyles';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import {validateReportFieldListValueName} from '@libs/WorkspaceReportFieldUtils';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import {addReportFieldListValue, createReportFieldsListValue} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsAddListValuePageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    reportFieldID?: string;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    testID: string;
-};
-
-function FieldsAddListValuePage({policy, policyID, reportFieldID, featureName, policyFeature, testID}: FieldsAddListValuePageProps) {
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const {inputCallbackRef} = useAutoFocusInput();
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-    const {canWrite} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const listValues = useMemo(() => {
-        let reportFieldListValues: string[];
-        if (reportFieldID) {
-            const reportFieldKey = getReportFieldKey(reportFieldID);
-            reportFieldListValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {});
-        } else {
-            reportFieldListValues = formDraft?.[INPUT_IDS.LIST_VALUES] ?? [];
-        }
-        return reportFieldListValues;
-    }, [formDraft, policy?.fieldList, reportFieldID]);
-
-    const validate = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) =>
-            validateReportFieldListValueName(values[INPUT_IDS.VALUE_NAME].trim(), '', listValues, INPUT_IDS.VALUE_NAME, translate),
-        [listValues, translate],
-    );
-
-    const createValue = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
-            if (reportFieldID) {
-                addReportFieldListValue({policy, reportFieldID, valueName: values[INPUT_IDS.VALUE_NAME]});
-            } else {
-                createReportFieldsListValue({
-                    valueName: values[INPUT_IDS.VALUE_NAME],
-                    listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
-                    disabledListValues: formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? [],
-                });
-            }
-            Keyboard.dismiss();
-            Navigation.goBack();
-        },
-        [formDraft, policy, reportFieldID],
-    );
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-            shouldBeBlocked={hasAccountingConnections(policy)}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate('workspace.reportFields.addValue')}
-                    onBackButtonPress={Navigation.goBack}
-                />
-                <FormProvider
-                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
-                    onSubmit={createValue}
-                    submitButtonText={translate('common.save')}
-                    validate={validate}
-                    style={[styles.mh5, styles.flex1]}
-                    enabledWhenOffline
-                    isSubmitButtonVisible={canWrite}
-                    shouldHideFixErrorsAlert
-                    addBottomSafeAreaPadding
-                >
-                    <InputWrapper
-                        InputComponent={TextInput}
-                        label={translate('common.value')}
-                        accessibilityLabel={translate('common.value')}
-                        inputID={INPUT_IDS.VALUE_NAME}
-                        role={CONST.ROLE.PRESENTATION}
-                        ref={inputCallbackRef}
-                        disabled={!canWrite}
-                    />
-                </FormProvider>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsAddListValuePage;
diff --git a/src/pages/workspace/fields/FieldsEditValuePage.tsx b/src/pages/workspace/fields/FieldsEditValuePage.tsx
deleted file mode 100644
index dcd021dd23a0..000000000000
--- a/src/pages/workspace/fields/FieldsEditValuePage.tsx
+++ /dev/null
@@ -1,112 +0,0 @@
-import React, {useCallback} from 'react';
-import {Keyboard} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import FormProvider from '@components/Form/FormProvider';
-import InputWrapper from '@components/Form/InputWrapper';
-import type {FormOnyxValues} from '@components/Form/types';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import ScreenWrapper from '@components/ScreenWrapper';
-import TextInput from '@components/TextInput';
-import useAutoFocusInput from '@hooks/useAutoFocusInput';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useThemeStyles from '@hooks/useThemeStyles';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {validateReportFieldListValueName} from '@libs/WorkspaceReportFieldUtils';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import {renameReportFieldsListValue} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsEditValuePageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    valueIndex: number;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    testID: string;
-};
-
-function FieldsEditValuePage({policy, policyID, valueIndex, featureName, policyFeature, testID}: FieldsEditValuePageProps) {
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const {inputCallbackRef} = useAutoFocusInput();
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-    const {canWrite} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const currentValueName = formDraft?.listValues?.[valueIndex] ?? '';
-
-    const validate = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) =>
-            validateReportFieldListValueName(values[INPUT_IDS.NEW_VALUE_NAME].trim(), currentValueName, formDraft?.[INPUT_IDS.LIST_VALUES] ?? [], INPUT_IDS.NEW_VALUE_NAME, translate),
-        [currentValueName, formDraft, translate],
-    );
-
-    const editValue = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
-            const valueName = values[INPUT_IDS.NEW_VALUE_NAME]?.trim();
-            if (currentValueName !== valueName) {
-                renameReportFieldsListValue({
-                    valueIndex,
-                    newValueName: valueName,
-                    listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
-                });
-            }
-            Keyboard.dismiss();
-            Navigation.goBack();
-        },
-        [currentValueName, formDraft, valueIndex],
-    );
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-            shouldBeBlocked={hasAccountingConnections(policy)}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate('workspace.reportFields.editValue')}
-                    onBackButtonPress={Navigation.goBack}
-                />
-                <FormProvider
-                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
-                    onSubmit={editValue}
-                    submitButtonText={translate('common.save')}
-                    validate={validate}
-                    style={[styles.mh5, styles.flex1]}
-                    enabledWhenOffline
-                    isSubmitButtonVisible={canWrite}
-                    shouldHideFixErrorsAlert
-                    addBottomSafeAreaPadding
-                >
-                    <InputWrapper
-                        InputComponent={TextInput}
-                        defaultValue={currentValueName}
-                        label={translate('common.value')}
-                        accessibilityLabel={translate('common.value')}
-                        inputID={INPUT_IDS.NEW_VALUE_NAME}
-                        role={CONST.ROLE.PRESENTATION}
-                        ref={inputCallbackRef}
-                        disabled={!canWrite}
-                    />
-                </FormProvider>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsEditValuePage;
diff --git a/src/pages/workspace/fields/FieldsInitialValuePage.tsx b/src/pages/workspace/fields/FieldsInitialValuePage.tsx
deleted file mode 100644
index c4ab5c8562c9..000000000000
--- a/src/pages/workspace/fields/FieldsInitialValuePage.tsx
+++ /dev/null
@@ -1,171 +0,0 @@
-import React, {useCallback, useState} from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import FormProvider from '@components/Form/FormProvider';
-import InputWrapper from '@components/Form/InputWrapper';
-import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import ScreenWrapper from '@components/ScreenWrapper';
-import Text from '@components/Text';
-import TextInput from '@components/TextInput';
-import useAutoFocusInput from '@hooks/useAutoFocusInput';
-import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {hasCircularReferences} from '@libs/Formula';
-import Navigation from '@libs/Navigation/Navigation';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import {isRequiredFulfilled} from '@libs/ValidationUtils';
-import {getReportFieldInitialValue, getUnsupportedReportFieldFormulaParts} from '@libs/WorkspaceReportFieldUtils';
-import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import ReportFieldsInitialListValuePicker from '@pages/workspace/reports/InitialListValueSelector/ReportFieldsInitialListValuePicker';
-import {updateReportFieldInitialValue} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsInitialValuePageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    reportFieldID: string;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    testID: string;
-};
-
-function FieldsInitialValuePage({policy, policyID, reportFieldID, featureName, testID}: FieldsInitialValuePageProps) {
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const {inputCallbackRef} = useAutoFocusInput();
-
-    const reportField = policy?.fieldList?.[getReportFieldKey(reportFieldID)] ?? null;
-    const isInvoiceField = reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const availableListValuesLength = (reportField?.disabledOptions ?? []).filter((disabledListValue) => !disabledListValue).length;
-    const currentInitialValue = getReportFieldInitialValue(reportField, translate);
-    const [initialValue, setInitialValue] = useState(currentInitialValue);
-
-    const submitForm = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
-            if (currentInitialValue !== values.initialValue) {
-                updateReportFieldInitialValue({policy, reportFieldID, newInitialValue: values.initialValue});
-            }
-            Navigation.goBack();
-        },
-        [currentInitialValue, policy, reportFieldID],
-    );
-
-    const submitListValueUpdate = (value: string) => {
-        updateReportFieldInitialValue({policy, reportFieldID, newInitialValue: currentInitialValue === value ? '' : value});
-        Navigation.goBack();
-    };
-
-    const validateForm = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> => {
-            const {initialValue: formInitialValue} = values;
-            const errors: FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> = {};
-
-            if (formInitialValue.length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate('common.error.characterLimitExceedCounter', formInitialValue.length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH);
-            }
-
-            if (
-                (reportField?.type === CONST.REPORT_FIELD_TYPES.TEXT || reportField?.type === CONST.REPORT_FIELD_TYPES.FORMULA) &&
-                hasCircularReferences(formInitialValue, reportField?.name, policy?.fieldList)
-            ) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.circularReferenceError');
-            }
-
-            if ((reportField?.type === CONST.REPORT_FIELD_TYPES.TEXT || reportField?.type === CONST.REPORT_FIELD_TYPES.FORMULA) && !!formInitialValue && !errors[INPUT_IDS.INITIAL_VALUE]) {
-                const unsupportedFormulaParts = getUnsupportedReportFieldFormulaParts(formInitialValue);
-                if (unsupportedFormulaParts.length > 0) {
-                    errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.unsupportedFormulaValueError', {
-                        value: unsupportedFormulaParts.join(', '),
-                    });
-                }
-            }
-
-            if (reportField?.type === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && !isRequiredFulfilled(formInitialValue)) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate(
-                    isInvoiceField ? 'workspace.invoiceFields.invoiceFieldInitialValueRequiredError' : 'workspace.reportFields.reportFieldInitialValueRequiredError',
-                );
-            }
-
-            return errors;
-        },
-        [availableListValuesLength, isInvoiceField, reportField?.name, reportField?.type, policy?.fieldList, translate],
-    );
-
-    if (!reportField) {
-        return <NotFoundPage />;
-    }
-
-    const isTextFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.TEXT;
-    const isFormulaFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.FORMULA;
-    const isListFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.LIST;
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate('common.initialValue')}
-                    onBackButtonPress={Navigation.goBack}
-                />
-                {isListFieldType && (
-                    <View style={[styles.ph5, styles.pb4]}>
-                        <Text style={[styles.sidebarLinkText, styles.optionAlternateText]}>
-                            {translate(isInvoiceField ? 'workspace.invoiceFields.listValuesInputSubtitle' : 'workspace.reportFields.listValuesInputSubtitle')}
-                        </Text>
-                    </View>
-                )}
-
-                {(isTextFieldType || isFormulaFieldType) && (
-                    <FormProvider
-                        addBottomSafeAreaPadding
-                        formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
-                        onSubmit={submitForm}
-                        submitButtonText={translate('common.save')}
-                        validate={validateForm}
-                        style={styles.flex1}
-                        enabledWhenOffline
-                        isSubmitButtonVisible
-                        submitButtonStyles={styles.mh5}
-                        shouldHideFixErrorsAlert
-                    >
-                        <InputWrapper
-                            containerStyles={styles.mh5}
-                            InputComponent={TextInput}
-                            inputID={INPUT_IDS.INITIAL_VALUE}
-                            label={translate('common.initialValue')}
-                            accessibilityLabel={translate('workspace.editor.initialValueInputLabel')}
-                            multiline={false}
-                            value={initialValue}
-                            role={CONST.ROLE.PRESENTATION}
-                            ref={inputCallbackRef}
-                            onChangeText={setInitialValue}
-                        />
-                    </FormProvider>
-                )}
-                {isListFieldType && (
-                    <ReportFieldsInitialListValuePicker
-                        listValues={reportField.values}
-                        disabledOptions={reportField.disabledOptions}
-                        value={initialValue}
-                        onValueChange={submitListValueUpdate}
-                    />
-                )}
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsInitialValuePage;
diff --git a/src/pages/workspace/fields/FieldsListValuesPage.tsx b/src/pages/workspace/fields/FieldsListValuesPage.tsx
deleted file mode 100644
index 9e7f2386bfd8..000000000000
--- a/src/pages/workspace/fields/FieldsListValuesPage.tsx
+++ /dev/null
@@ -1,438 +0,0 @@
-import React, {useCallback, useMemo, useState} from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import Button from '@components/Button';
-import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
-import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types';
-import EmptyStateComponent from '@components/EmptyStateComponent';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import {ModalActions} from '@components/Modal/Global/ModalContext';
-import ScreenWrapper from '@components/ScreenWrapper';
-import ScrollView from '@components/ScrollView';
-import SearchBar from '@components/SearchBar';
-import TableListItem from '@components/SelectionList/ListItem/TableListItem';
-import type {ListItem} from '@components/SelectionList/types';
-import SelectionListWithModal from '@components/SelectionListWithModal';
-import CustomListHeader from '@components/SelectionListWithModal/CustomListHeader';
-import Switch from '@components/Switch';
-import Text from '@components/Text';
-import useConfirmModal from '@hooks/useConfirmModal';
-import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useResponsiveLayout from '@hooks/useResponsiveLayout';
-import useSearchBackPress from '@hooks/useSearchBackPress';
-import useSearchResults from '@hooks/useSearchResults';
-import useShouldDisplayButtonsInSeparateLine from '@hooks/useShouldDisplayButtonsInSeparateLine';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
-import {
-    deleteReportFieldsListValue,
-    removeReportFieldListValue,
-    setReportFieldsListValueEnabled,
-    updateReportFieldListValueEnabled as updateReportFieldListValueEnabledReportField,
-} from '@libs/actions/Policy/ReportField';
-import {canUseTouchScreen} from '@libs/DeviceCapabilities';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections as hasAccountingConnectionsPolicyUtils} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import StringUtils from '@libs/StringUtils';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {Route as Routes} from '@src/ROUTES';
-import type {Policy} from '@src/types/onyx';
-import type DeepValueOf from '@src/types/utils/DeepValueOf';
-
-type ValueListItem = ListItem & {
-    /** The value */
-    value: string;
-
-    /** Whether the value is enabled */
-    enabled: boolean;
-
-    /** The value order weight in the list */
-    orderWeight?: number;
-};
-
-type FieldsListValuesPageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    reportFieldID?: string;
-    isInvoicePage: boolean;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    getValueSettingsRoute: (isInvoiceRoute: boolean, policyID: string, valueIndex: number, reportFieldID?: string) => Routes;
-    getAddValueRoute: (isInvoiceRoute: boolean, policyID: string, reportFieldID?: string) => Routes;
-    testID: string;
-};
-
-function FieldsListValuesPage({policy, policyID, reportFieldID, isInvoicePage, featureName, policyFeature, getValueSettingsRoute, getAddValueRoute, testID}: FieldsListValuesPageProps) {
-    const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
-    // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout here to use the mobile selection mode on small screens only
-    // See https://github.com/Expensify/App/issues/48724 for more details
-    // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
-    const {isSmallScreenWidth} = useResponsiveLayout();
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-    const isMobileSelectionModeEnabled = useMobileSelectionMode();
-    const icons = useMemoizedLazyExpensifyIcons(['Checkmark', 'Close', 'Plus', 'Trashcan']);
-    const illustrations = useMemoizedLazyIllustrations(['FolderWithPapers']);
-    const {showConfirmModal} = useConfirmModal();
-    const {canWrite, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const [selectedValues, setSelectedValues] = useState<Record<string, boolean>>({});
-    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
-    const reportField = reportFieldID ? policy?.fieldList?.[getReportFieldKey(reportFieldID)] : undefined;
-    const shouldUseInvoiceRoutes = isInvoicePage || reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const listInputSubtitleKey = shouldUseInvoiceRoutes ? 'workspace.invoiceFields.listInputSubtitle' : 'workspace.reportFields.listInputSubtitle';
-    const findFieldKey = shouldUseInvoiceRoutes ? 'workspace.invoiceFields.findInvoiceField' : 'workspace.reportFields.findReportField';
-    const emptyValuesSubtitleKey = shouldUseInvoiceRoutes ? 'workspace.invoiceFields.emptyInvoiceFieldsValues.subtitle' : 'workspace.reportFields.emptyReportFieldsValues.subtitle';
-
-    const canSelectMultiple = canWrite && (isSmallScreenWidth ? isMobileSelectionModeEnabled : true);
-
-    const [listValues, disabledListValues] = useMemo(() => {
-        let reportFieldValues: string[];
-        let reportFieldDisabledValues: boolean[];
-
-        if (reportFieldID) {
-            const reportFieldKey = getReportFieldKey(reportFieldID);
-
-            reportFieldValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {});
-            reportFieldDisabledValues = Object.values(policy?.fieldList?.[reportFieldKey]?.disabledOptions ?? {});
-        } else {
-            reportFieldValues = formDraft?.listValues ?? [];
-            reportFieldDisabledValues = formDraft?.disabledListValues ?? [];
-        }
-
-        return [reportFieldValues, reportFieldDisabledValues];
-    }, [formDraft?.disabledListValues, formDraft?.listValues, policy?.fieldList, reportFieldID]);
-
-    const updateReportFieldListValueEnabled = useCallback(
-        (value: boolean, valueIndex: number) => {
-            if (reportFieldID) {
-                updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: [Number(valueIndex)], enabled: value});
-                return;
-            }
-
-            setReportFieldsListValueEnabled({
-                valueIndexes: [valueIndex],
-                enabled: value,
-                disabledListValues,
-            });
-        },
-        [disabledListValues, policy, reportFieldID],
-    );
-
-    useSearchBackPress({
-        onClearSelection: () => {
-            setSelectedValues({});
-        },
-        onNavigationCallBack: () => Navigation.goBack(),
-    });
-
-    const data = useMemo(
-        () =>
-            listValues.map<ValueListItem>((value, index) => ({
-                value,
-                index,
-                text: value,
-                keyForList: value,
-                isSelected: selectedValues[value] && canSelectMultiple,
-                enabled: !disabledListValues.at(index),
-                rightElement: (
-                    <Switch
-                        isOn={!disabledListValues.at(index)}
-                        accessibilityLabel={translate('workspace.distanceRates.trackTax')}
-                        onToggle={(newValue: boolean) => updateReportFieldListValueEnabled(newValue, index)}
-                        disabled={!canWrite}
-                        disabledAction={withReadOnlyFallback()}
-                        showLockIcon={!canWrite}
-                    />
-                ),
-            })),
-        [canSelectMultiple, canWrite, disabledListValues, listValues, selectedValues, translate, updateReportFieldListValueEnabled, withReadOnlyFallback],
-    );
-
-    const filterListValue = useCallback((item: ValueListItem, searchInput: string) => {
-        const itemText = StringUtils.normalize(item.text?.toLowerCase() ?? '');
-        const normalizedSearchInput = StringUtils.normalize(searchInput.toLowerCase());
-        return itemText.includes(normalizedSearchInput);
-    }, []);
-    const sortListValues = useCallback((values: ValueListItem[]) => values.sort((a, b) => localeCompare(a.value, b.value)), [localeCompare]);
-    const [inputValue, setInputValue, filteredListValues] = useSearchResults(data, filterListValue, sortListValues);
-    const shouldDisplayButtonsInSeparateLine = useShouldDisplayButtonsInSeparateLine();
-
-    const filteredListValuesArray = filteredListValues.map((item) => item.value);
-
-    const shouldShowEmptyState = Object.values(listValues ?? {}).length <= 0;
-    const selectedValuesArray = Object.keys(selectedValues).filter((key) => selectedValues[key] && listValues.includes(key));
-
-    const toggleValue = (valueItem: ValueListItem) => {
-        setSelectedValues((prev) => ({
-            ...prev,
-            [valueItem.value]: !prev[valueItem.value],
-        }));
-    };
-
-    const toggleAllValues = () => {
-        setSelectedValues(selectedValuesArray.length > 0 ? {} : Object.fromEntries(filteredListValuesArray.map((value) => [value, true])));
-    };
-
-    const handleDeleteValues = () => {
-        const valuesToDelete = selectedValuesArray.reduce<number[]>((acc, valueName) => {
-            const index = listValues?.indexOf(valueName) ?? -1;
-
-            if (index !== -1) {
-                acc.push(index);
-            }
-
-            return acc;
-        }, []);
-
-        if (reportFieldID) {
-            removeReportFieldListValue({policy, reportFieldID, valueIndexes: valuesToDelete});
-        } else {
-            deleteReportFieldsListValue({
-                valueIndexes: valuesToDelete,
-                listValues,
-                disabledListValues,
-            });
-        }
-
-        setSelectedValues({});
-    };
-
-    const openListValuePage = (valueItem: ValueListItem) => {
-        if (valueItem.index === undefined) {
-            return;
-        }
-
-        Navigation.navigate(getValueSettingsRoute(shouldUseInvoiceRoutes, policyID, valueItem.index, reportFieldID));
-    };
-
-    const getCustomListHeader = () => {
-        if (filteredListValues.length === 0) {
-            return null;
-        }
-        return (
-            <CustomListHeader
-                canSelectMultiple={canSelectMultiple}
-                leftHeaderText={translate('common.name')}
-                rightHeaderText={translate('common.enabled')}
-                shouldShowRightCaret
-            />
-        );
-    };
-
-    const getHeaderButtons = () => {
-        const options: Array<DropdownOption<DeepValueOf<typeof CONST.POLICY.BULK_ACTION_TYPES>>> = [];
-        if (canWrite && (isSmallScreenWidth ? isMobileSelectionModeEnabled : selectedValuesArray.length > 0)) {
-            if (selectedValuesArray.length > 0 && !hasAccountingConnections) {
-                options.push({
-                    icon: icons.Trashcan,
-                    text: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValue' : 'workspace.reportFields.deleteValues'),
-                    value: CONST.POLICY.BULK_ACTION_TYPES.DELETE,
-                    onSelected: () => {
-                        showConfirmModal({
-                            danger: true,
-                            title: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValue' : 'workspace.reportFields.deleteValues'),
-                            prompt: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValuePrompt' : 'workspace.reportFields.deleteValuesPrompt'),
-                            confirmText: translate('common.delete'),
-                            cancelText: translate('common.cancel'),
-                        }).then((result) => {
-                            if (result.action !== ModalActions.CONFIRM) {
-                                return;
-                            }
-
-                            handleDeleteValues();
-                        });
-                    },
-                });
-            }
-            const enabledValues = selectedValuesArray.filter((valueName) => {
-                const index = listValues?.indexOf(valueName) ?? -1;
-                return !disabledListValues?.at(index);
-            });
-
-            if (enabledValues.length > 0) {
-                const valuesToDisable = selectedValuesArray.reduce<number[]>((acc, valueName) => {
-                    const index = listValues?.indexOf(valueName) ?? -1;
-                    if (!disabledListValues?.at(index) && index !== -1) {
-                        acc.push(index);
-                    }
-
-                    return acc;
-                }, []);
-
-                options.push({
-                    icon: icons.Close,
-                    text: translate(enabledValues.length === 1 ? 'workspace.reportFields.disableValue' : 'workspace.reportFields.disableValues'),
-                    value: CONST.POLICY.BULK_ACTION_TYPES.DISABLE,
-                    onSelected: () => {
-                        setSelectedValues({});
-
-                        if (reportFieldID) {
-                            updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: valuesToDisable, enabled: false});
-                            return;
-                        }
-
-                        setReportFieldsListValueEnabled({
-                            valueIndexes: valuesToDisable,
-                            enabled: false,
-                            disabledListValues,
-                        });
-                    },
-                });
-            }
-
-            const disabledValues = selectedValuesArray.filter((valueName) => {
-                const index = listValues?.indexOf(valueName) ?? -1;
-                return disabledListValues?.at(index);
-            });
-
-            if (disabledValues.length > 0) {
-                const valuesToEnable = selectedValuesArray.reduce<number[]>((acc, valueName) => {
-                    const index = listValues?.indexOf(valueName) ?? -1;
-                    if (disabledListValues?.at(index) && index !== -1) {
-                        acc.push(index);
-                    }
-
-                    return acc;
-                }, []);
-
-                options.push({
-                    icon: icons.Checkmark,
-                    text: translate(disabledValues.length === 1 ? 'workspace.reportFields.enableValue' : 'workspace.reportFields.enableValues'),
-                    value: CONST.POLICY.BULK_ACTION_TYPES.ENABLE,
-                    onSelected: () => {
-                        setSelectedValues({});
-
-                        if (reportFieldID) {
-                            updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: valuesToEnable, enabled: true});
-                            return;
-                        }
-
-                        setReportFieldsListValueEnabled({
-                            valueIndexes: valuesToEnable,
-                            enabled: true,
-                            disabledListValues,
-                        });
-                    },
-                });
-            }
-
-            return (
-                <ButtonWithDropdownMenu
-                    onPress={() => null}
-                    shouldAlwaysShowDropdownMenu
-                    buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM}
-                    customText={translate('workspace.common.selected', {count: selectedValuesArray.length})}
-                    options={options}
-                    isSplitButton={false}
-                    style={[shouldDisplayButtonsInSeparateLine && styles.flexGrow1, shouldDisplayButtonsInSeparateLine && styles.mb3]}
-                    isDisabled={!selectedValuesArray.length}
-                />
-            );
-        }
-
-        if (canWrite && !hasAccountingConnections) {
-            return (
-                <Button
-                    style={[shouldDisplayButtonsInSeparateLine && styles.flexGrow1, shouldDisplayButtonsInSeparateLine && styles.mb3]}
-                    success
-                    icon={icons.Plus}
-                    text={translate('workspace.reportFields.addValue')}
-                    onPress={() => Navigation.navigate(getAddValueRoute(shouldUseInvoiceRoutes, policyID, reportFieldID))}
-                />
-            );
-        }
-    };
-
-    const selectionModeHeader = isMobileSelectionModeEnabled && isSmallScreenWidth;
-
-    const headerContent = (
-        <>
-            <View style={[styles.ph5, styles.pv4]}>
-                <Text style={[styles.sidebarLinkText, styles.optionAlternateText]}>{translate(listInputSubtitleKey)}</Text>
-            </View>
-            {data.length >= CONST.STANDARD_LIST_ITEM_LIMIT && (
-                <SearchBar
-                    label={translate(findFieldKey)}
-                    inputValue={inputValue}
-                    onChangeText={setInputValue}
-                    shouldShowEmptyState={!shouldShowEmptyState && filteredListValues.length === 0}
-                />
-            )}
-        </>
-    );
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate(selectionModeHeader ? 'common.selectMultiple' : 'workspace.reportFields.listValues')}
-                    onBackButtonPress={() => {
-                        if (isMobileSelectionModeEnabled) {
-                            setSelectedValues({});
-                            turnOffMobileSelectionMode();
-                            return;
-                        }
-                        Navigation.goBack();
-                    }}
-                >
-                    {!shouldDisplayButtonsInSeparateLine && getHeaderButtons()}
-                </HeaderWithBackButton>
-                {shouldDisplayButtonsInSeparateLine && <View style={[styles.pl5, styles.pr5]}>{getHeaderButtons()}</View>}
-                {shouldShowEmptyState && (
-                    <ScrollView contentContainerStyle={[styles.flexGrow1, styles.flexShrink0]}>
-                        {headerContent}
-                        <EmptyStateComponent
-                            title={translate('workspace.reportFields.emptyReportFieldsValues.title')}
-                            subtitle={translate(emptyValuesSubtitleKey)}
-                            headerMedia={illustrations.FolderWithPapers}
-                            headerStyles={styles.emptyStateCardIllustrationContainer}
-                            headerContentStyles={styles.emptyStateFolderWithPaperIconSize}
-                        />
-                    </ScrollView>
-                )}
-                {!shouldShowEmptyState && (
-                    <SelectionListWithModal
-                        data={filteredListValues}
-                        ListItem={TableListItem}
-                        onSelectRow={openListValuePage}
-                        selectedItems={selectedValuesArray}
-                        onSelectAll={canWrite && filteredListValues.length > 0 ? toggleAllValues : undefined}
-                        onTurnOnSelectionMode={(item) => item && canWrite && toggleValue(item)}
-                        shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
-                        customListHeader={getCustomListHeader()}
-                        customListHeaderContent={headerContent}
-                        canSelectMultiple={canSelectMultiple}
-                        onSelectionButtonPress={toggleValue}
-                        shouldShowListEmptyContent={false}
-                        showScrollIndicator={false}
-                        turnOnSelectionModeOnLongPress={canWrite}
-                        shouldHeaderBeInsideList
-                        shouldShowRightCaret
-                    />
-                )}
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsListValuesPage;
diff --git a/src/pages/workspace/fields/FieldsSettingsPage.tsx b/src/pages/workspace/fields/FieldsSettingsPage.tsx
deleted file mode 100644
index ccba8c0093e5..000000000000
--- a/src/pages/workspace/fields/FieldsSettingsPage.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-import {Str} from 'expensify-common';
-import React from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import MenuItem from '@components/MenuItem';
-import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
-import {ModalActions} from '@components/Modal/Global/ModalContext';
-import ScreenWrapper from '@components/ScreenWrapper';
-import useConfirmModal from '@hooks/useConfirmModal';
-import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useThemeStyles from '@hooks/useThemeStyles';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections as hasAccountingConnectionsPolicyUtils} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import {getReportFieldInitialValue, getReportFieldTypeTranslationKey, isReportFieldTargetValid} from '@libs/WorkspaceReportFieldUtils';
-import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import {deleteReportFields} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import type {Route as Routes} from '@src/ROUTES';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsSettingsPageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    reportFieldID: string;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    expectedTarget?: ValueOf<typeof CONST.REPORT_FIELD_TARGETS>;
-    getListValuesRoute: (policyID: string, reportFieldID: string) => Routes;
-    getInitialValueRoute: (policyID: string, reportFieldID: string) => Routes;
-    deleteTitleKey?: 'workspace.reportFields.delete' | 'workspace.invoiceFields.delete';
-    deletePromptKey?: 'workspace.reportFields.deleteConfirmation' | 'workspace.invoiceFields.deleteConfirmation';
-    testID: string;
-};
-
-function FieldsSettingsPage({
-    policy,
-    policyID,
-    reportFieldID,
-    featureName,
-    policyFeature,
-    expectedTarget,
-    getListValuesRoute,
-    getInitialValueRoute,
-    deleteTitleKey = 'workspace.reportFields.delete',
-    deletePromptKey = 'workspace.reportFields.deleteConfirmation',
-    testID,
-}: FieldsSettingsPageProps) {
-    const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
-    const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
-    const {showConfirmModal} = useConfirmModal();
-    const {canWrite} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
-    const reportFieldKey = getReportFieldKey(reportFieldID);
-    const reportField = policy?.fieldList?.[reportFieldKey] ?? null;
-
-    if (!reportField || !isReportFieldTargetValid(reportField, expectedTarget)) {
-        return <NotFoundPage />;
-    }
-
-    const isDateFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.DATE;
-    const isListFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.LIST;
-    const isListFieldEmpty = isListFieldType && reportField.disabledOptions.filter((disabledListValue) => !disabledListValue).length <= 0;
-    const listValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {})?.sort(localeCompare);
-
-    const deleteReportFieldAndHideModal = () => {
-        deleteReportFields({policy, reportFieldsToUpdate: [reportFieldKey]});
-        Navigation.goBack();
-    };
-
-    const showDeleteModal = () => {
-        showConfirmModal({
-            danger: true,
-            title: translate(deleteTitleKey),
-            prompt: translate(deletePromptKey),
-            confirmText: translate('common.delete'),
-            cancelText: translate('common.cancel'),
-        }).then((result) => {
-            if (result.action !== ModalActions.CONFIRM) {
-                return;
-            }
-
-            deleteReportFieldAndHideModal();
-        });
-    };
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={[styles.defaultModalContainer]}
-                testID={testID}
-            >
-                <HeaderWithBackButton
-                    title={reportField.name}
-                    shouldSetModalVisibility={false}
-                />
-                <View style={styles.flexGrow1}>
-                    <MenuItemWithTopDescription
-                        style={[styles.moneyRequestMenuItem]}
-                        titleStyle={styles.flex1}
-                        title={reportField.name}
-                        description={translate('common.name')}
-                        interactive={false}
-                    />
-                    <MenuItemWithTopDescription
-                        style={[styles.moneyRequestMenuItem]}
-                        titleStyle={styles.flex1}
-                        title={Str.recapitalize(translate(getReportFieldTypeTranslationKey(reportField.type)))}
-                        description={translate('common.type')}
-                        interactive={false}
-                    />
-                    {isListFieldType && (
-                        <MenuItemWithTopDescription
-                            style={[styles.moneyRequestMenuItem]}
-                            titleStyle={styles.flex1}
-                            description={translate('workspace.reportFields.listValues')}
-                            shouldShowRightIcon={canWrite}
-                            interactive={canWrite}
-                            onPress={() => Navigation.navigate(getListValuesRoute(policyID, reportFieldID))}
-                            title={listValues.join(', ')}
-                            numberOfLinesTitle={5}
-                        />
-                    )}
-                    {!isListFieldEmpty && (
-                        <MenuItemWithTopDescription
-                            style={[styles.moneyRequestMenuItem]}
-                            titleStyle={styles.flex1}
-                            title={getReportFieldInitialValue(reportField, translate)}
-                            description={translate('common.initialValue')}
-                            shouldShowRightIcon={canWrite && !isDateFieldType}
-                            interactive={canWrite && !isDateFieldType}
-                            onPress={() => Navigation.navigate(getInitialValueRoute(policyID, reportFieldID))}
-                        />
-                    )}
-                    {canWrite && !hasAccountingConnections && (
-                        <View style={styles.flexGrow1}>
-                            <MenuItem
-                                icon={icons.Trashcan}
-                                title={translate('common.delete')}
-                                onPress={showDeleteModal}
-                            />
-                        </View>
-                    )}
-                </View>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsSettingsPage;
diff --git a/src/pages/workspace/fields/FieldsValueSettingsPage.tsx b/src/pages/workspace/fields/FieldsValueSettingsPage.tsx
deleted file mode 100644
index bdb6a0320398..000000000000
--- a/src/pages/workspace/fields/FieldsValueSettingsPage.tsx
+++ /dev/null
@@ -1,178 +0,0 @@
-import React, {useMemo} from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import MenuItem from '@components/MenuItem';
-import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
-import {ModalActions} from '@components/Modal/Global/ModalContext';
-import ScreenWrapper from '@components/ScreenWrapper';
-import Switch from '@components/Switch';
-import Text from '@components/Text';
-import useConfirmModal from '@hooks/useConfirmModal';
-import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import usePrevious from '@hooks/usePrevious';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {deleteReportFieldsListValue, removeReportFieldListValue, setReportFieldsListValueEnabled, updateReportFieldListValueEnabled} from '@libs/actions/Policy/ReportField';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections as hasAccountingConnectionsUtil} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {Route as Routes} from '@src/ROUTES';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsValueSettingsPageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    valueIndex: number;
-    reportFieldID?: string;
-    isInvoicePage: boolean;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    getEditValueRoute: (isInvoiceRoute: boolean, policyID: string, valueIndex: number) => Routes;
-    testID: string;
-};
-
-function FieldsValueSettingsPage({policy, policyID, valueIndex, reportFieldID, isInvoicePage, featureName, policyFeature, getEditValueRoute, testID}: FieldsValueSettingsPageProps) {
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
-    const {showConfirmModal} = useConfirmModal();
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-    const {canWrite, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const [currentValueName, currentValueDisabled] = useMemo(() => {
-        let reportFieldValue: string;
-        let reportFieldDisabledValue: boolean;
-
-        if (reportFieldID) {
-            const reportFieldKey = getReportFieldKey(reportFieldID);
-
-            reportFieldValue = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {})?.at(valueIndex) ?? '';
-            reportFieldDisabledValue = Object.values(policy?.fieldList?.[reportFieldKey]?.disabledOptions ?? {})?.at(valueIndex) ?? false;
-        } else {
-            reportFieldValue = formDraft?.listValues?.[valueIndex] ?? '';
-            reportFieldDisabledValue = formDraft?.disabledListValues?.[valueIndex] ?? false;
-        }
-
-        return [reportFieldValue, reportFieldDisabledValue];
-    }, [formDraft?.disabledListValues, formDraft?.listValues, policy?.fieldList, reportFieldID, valueIndex]);
-
-    const hasAccountingConnections = hasAccountingConnectionsUtil(policy);
-    const oldValueName = usePrevious(currentValueName);
-    const reportField = reportFieldID ? policy?.fieldList?.[getReportFieldKey(reportFieldID)] : undefined;
-    const shouldUseInvoiceRoutes = isInvoicePage || reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-
-    if (!currentValueName && !oldValueName) {
-        return <NotFoundPage />;
-    }
-
-    const deleteListValueAndHideModal = () => {
-        if (reportFieldID) {
-            removeReportFieldListValue({policy, reportFieldID, valueIndexes: [valueIndex]});
-        } else {
-            deleteReportFieldsListValue({
-                valueIndexes: [valueIndex],
-                listValues: formDraft?.listValues ?? [],
-                disabledListValues: formDraft?.disabledListValues ?? [],
-            });
-        }
-        Navigation.goBack();
-    };
-
-    const showDeleteModal = () => {
-        showConfirmModal({
-            danger: true,
-            title: translate('workspace.reportFields.deleteValue'),
-            prompt: translate('workspace.reportFields.deleteValuePrompt'),
-            confirmText: translate('common.delete'),
-            cancelText: translate('common.cancel'),
-        }).then((result) => {
-            if (result.action !== ModalActions.CONFIRM) {
-                return;
-            }
-
-            deleteListValueAndHideModal();
-        });
-    };
-
-    const updateListValueEnabled = (value: boolean) => {
-        if (reportFieldID) {
-            updateReportFieldListValueEnabled({policy, reportFieldID, valueIndexes: [Number(valueIndex)], enabled: value});
-            return;
-        }
-
-        setReportFieldsListValueEnabled({
-            valueIndexes: [valueIndex],
-            enabled: value,
-            disabledListValues: formDraft?.disabledListValues ?? [],
-        });
-    };
-
-    const navigateToEditValue = () => {
-        Navigation.navigate(getEditValueRoute(shouldUseInvoiceRoutes, policyID, valueIndex));
-    };
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-            >
-                <HeaderWithBackButton
-                    title={currentValueName ?? oldValueName}
-                    shouldSetModalVisibility={false}
-                />
-                <View style={styles.flexGrow1}>
-                    <View style={[styles.mt2, styles.mh5]}>
-                        <View style={[styles.flexRow, styles.mb5, styles.mr2, styles.alignItemsCenter, styles.justifyContentBetween]}>
-                            <Text
-                                accessible={false}
-                                aria-hidden
-                            >
-                                {translate('workspace.reportFields.enableValue')}
-                            </Text>
-                            <Switch
-                                isOn={!currentValueDisabled}
-                                accessibilityLabel={translate('workspace.reportFields.enableValue')}
-                                onToggle={updateListValueEnabled}
-                                disabled={!canWrite}
-                                disabledAction={withReadOnlyFallback()}
-                                showLockIcon={!canWrite}
-                            />
-                        </View>
-                    </View>
-                    <MenuItemWithTopDescription
-                        title={currentValueName ?? oldValueName}
-                        description={translate('common.value')}
-                        shouldShowRightIcon={canWrite && !reportFieldID}
-                        interactive={canWrite && !reportFieldID}
-                        onPress={navigateToEditValue}
-                    />
-                    {canWrite && !hasAccountingConnections && (
-                        <MenuItem
-                            icon={icons.Trashcan}
-                            title={translate('common.delete')}
-                            onPress={showDeleteModal}
-                        />
-                    )}
-                </View>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsValueSettingsPage;
diff --git a/src/pages/workspace/fields/WorkspaceFieldsSection.tsx b/src/pages/workspace/fields/WorkspaceFieldsSection.tsx
deleted file mode 100644
index 3d21a54f3147..000000000000
--- a/src/pages/workspace/fields/WorkspaceFieldsSection.tsx
+++ /dev/null
@@ -1,278 +0,0 @@
-import {FlashList} from '@shopify/flash-list';
-import type {ListRenderItemInfo} from '@shopify/flash-list';
-import {Str} from 'expensify-common';
-import React, {useCallback, useEffect, useMemo} from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import ImportedFromAccountingSoftware from '@components/ImportedFromAccountingSoftware';
-import MenuItem from '@components/MenuItem';
-import {ModalActions} from '@components/Modal/Global/ModalContext';
-import OfflineWithFeedback from '@components/OfflineWithFeedback';
-import Section from '@components/Section';
-import Text from '@components/Text';
-import useConfirmModal from '@hooks/useConfirmModal';
-import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import useNetwork from '@hooks/useNetwork';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useResponsiveLayout from '@hooks/useResponsiveLayout';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {isConnectionInProgress, isConnectionUnverified} from '@libs/actions/connections';
-import Navigation from '@libs/Navigation/Navigation';
-import {getConnectedIntegration, getCurrentConnectionName, hasAccountingConnections as hasAccountingConnectionsPolicyUtils, isControlPolicy, shouldShowSyncError} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldTypeTranslationKey} from '@libs/WorkspaceReportFieldUtils';
-import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow';
-import CONST from '@src/CONST';
-import type {TranslationPaths} from '@src/languages/types';
-import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES from '@src/ROUTES';
-import type {Route} from '@src/ROUTES';
-import type {Policy, PolicyConnectionName} from '@src/types/onyx';
-import type {PendingAction} from '@src/types/onyx/OnyxCommon';
-
-type FieldListValue = NonNullable<Policy['fieldList']>[string];
-
-type FieldListItem = {
-    fieldID: string;
-    isDisabled: boolean;
-    keyForList: string;
-    pendingAction?: PendingAction;
-    rightLabel: string;
-    text: string;
-};
-
-type WorkspaceFieldsSectionProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    isEnabled: boolean;
-    pendingAction?: PendingAction | null;
-    fieldFilter: (field: FieldListValue) => boolean;
-    titleKey: TranslationPaths;
-    subtitleKey: TranslationPaths;
-    importedFromAccountingSoftwareKey: TranslationPaths;
-    disableTitleKey: TranslationPaths;
-    disablePromptKey: TranslationPaths;
-    addFieldKey: TranslationPaths;
-    createRoute: Route;
-    getSettingsRoute: (policyID: string, fieldID: string) => Route;
-    upgradeFeatureAlias: string;
-    upgradeBackToRoute: Route;
-    enableFields: (policyID: string, enabled: boolean) => void;
-    openFieldsPage: (policyID: string) => void;
-    policyFeature: PolicyFeature;
-    syncErrorConnectionNames?: readonly PolicyConnectionName[];
-    titleAccessibilityRole?: typeof CONST.ROLE.HEADER;
-};
-
-function keyExtractor(item: FieldListItem) {
-    return item.keyForList;
-}
-
-function WorkspaceFieldsSection({
-    policy,
-    policyID,
-    isEnabled,
-    pendingAction,
-    fieldFilter,
-    titleKey,
-    subtitleKey,
-    importedFromAccountingSoftwareKey,
-    disableTitleKey,
-    disablePromptKey,
-    addFieldKey,
-    createRoute,
-    getSettingsRoute,
-    upgradeFeatureAlias,
-    upgradeBackToRoute,
-    enableFields,
-    openFieldsPage,
-    policyFeature,
-    syncErrorConnectionNames,
-    titleAccessibilityRole,
-}: WorkspaceFieldsSectionProps) {
-    const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
-    const icons = useMemoizedLazyExpensifyIcons(['Plus']);
-    const {shouldUseNarrowLayout} = useResponsiveLayout();
-    const {showConfirmModal} = useConfirmModal();
-    const [connectionSyncProgress] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policyID}`);
-    const isSyncInProgress = isConnectionInProgress(connectionSyncProgress, policy);
-    const syncingAccountingIntegration = CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES.find((connectionName) => connectionName === connectionSyncProgress?.connectionName);
-    const hasSyncError = shouldShowSyncError(policy, isSyncInProgress, syncErrorConnectionNames);
-    const connectedIntegration = getConnectedIntegration(policy) ?? syncingAccountingIntegration;
-    const isConnectionVerified = connectedIntegration && !isConnectionUnverified(policy, connectedIntegration);
-    const currentConnectionName = getCurrentConnectionName(policy);
-    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
-    const fieldList = policy?.fieldList;
-    const {canWrite, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const fetchFields = useCallback(() => {
-        openFieldsPage(policyID);
-    }, [openFieldsPage, policyID]);
-
-    const {isOffline} = useNetwork({onReconnect: fetchFields});
-
-    useEffect(() => {
-        fetchFields();
-    }, [fetchFields]);
-
-    const fields = useMemo<FieldListItem[]>(() => {
-        if (!fieldList) {
-            return [];
-        }
-
-        return Object.values(fieldList)
-            .filter(fieldFilter)
-            .sort((a, b) => localeCompare(a.name, b.name))
-            .map((field) => ({
-                text: field.name,
-                keyForList: String(field.fieldID),
-                fieldID: field.fieldID,
-                pendingAction: field.pendingAction,
-                isDisabled: field.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
-                rightLabel: Str.recapitalize(translate(getReportFieldTypeTranslationKey(field.type ?? CONST.REPORT_FIELD_TYPES.TEXT))),
-            }));
-    }, [fieldFilter, fieldList, localeCompare, translate]);
-
-    const navigateToFieldSettings = useCallback(
-        (item: FieldListItem) => {
-            if (!canWrite) {
-                return;
-            }
-
-            Navigation.navigate(getSettingsRoute(policyID, item.fieldID));
-        },
-        [canWrite, getSettingsRoute, policyID],
-    );
-
-    const renderItem = useCallback(
-        ({item}: ListRenderItemInfo<FieldListItem>) => (
-            <OfflineWithFeedback pendingAction={item.pendingAction}>
-                <MenuItem
-                    style={shouldUseNarrowLayout ? styles.ph5 : styles.ph8}
-                    onPress={() => navigateToFieldSettings(item)}
-                    description={item.text}
-                    disabled={item.isDisabled}
-                    shouldShowRightIcon={!item.isDisabled && canWrite}
-                    interactive={!item.isDisabled && canWrite}
-                    rightLabel={item.rightLabel}
-                    descriptionTextStyle={[styles.popoverMenuText, styles.textStrong]}
-                />
-            </OfflineWithFeedback>
-        ),
-        [canWrite, navigateToFieldSettings, shouldUseNarrowLayout, styles.ph5, styles.ph8, styles.popoverMenuText, styles.textStrong],
-    );
-
-    const headerText =
-        !hasSyncError && isConnectionVerified && currentConnectionName ? (
-            <Text style={[styles.mr5, styles.mt1]}>
-                <ImportedFromAccountingSoftware
-                    policyID={policyID}
-                    currentConnectionName={currentConnectionName}
-                    connectedIntegration={connectedIntegration}
-                    translatedText={translate(importedFromAccountingSoftwareKey)}
-                />
-            </Text>
-        ) : (
-            <Text style={[styles.textNormal, styles.colorMuted, styles.mr5, styles.mt1]}>{translate(subtitleKey)}</Text>
-        );
-
-    const switchAccessibilityLabel =
-        !hasSyncError && isConnectionVerified && currentConnectionName
-            ? `${translate(titleKey)}, ${translate(importedFromAccountingSoftwareKey)} ${currentConnectionName} ${translate('workspace.accounting.settings')}`
-            : `${translate(titleKey)}, ${translate(subtitleKey)}`;
-
-    const isLoading = !isOffline && policy === undefined;
-
-    const onDisabledOrganizeSwitchPress = () => {
-        if (!hasAccountingConnections) {
-            return;
-        }
-
-        showConfirmModal({
-            title: translate('workspace.moreFeatures.connectionsWarningModal.featureEnabledTitle'),
-            prompt: translate('workspace.moreFeatures.connectionsWarningModal.featureEnabledText'),
-            confirmText: translate('workspace.moreFeatures.connectionsWarningModal.manageSettings'),
-            cancelText: translate('common.cancel'),
-        }).then((result) => {
-            if (result.action !== ModalActions.CONFIRM) {
-                return;
-            }
-
-            Navigation.navigate(ROUTES.POLICY_ACCOUNTING.getRoute(policyID));
-        });
-    };
-
-    return (
-        <Section
-            isCentralPane
-            containerStyles={shouldUseNarrowLayout ? styles.p5 : styles.p8}
-        >
-            <ToggleSettingOptionRow
-                pendingAction={pendingAction}
-                title={translate(titleKey)}
-                switchAccessibilityLabel={switchAccessibilityLabel}
-                subtitle={headerText}
-                titleStyle={[styles.textHeadline, styles.cardSectionTitle, styles.accountSettingsSectionTitle, styles.mb1]}
-                titleAccessibilityRole={titleAccessibilityRole}
-                isActive={isEnabled}
-                onToggle={(enabled) => {
-                    if (!enabled) {
-                        showConfirmModal({
-                            danger: true,
-                            title: translate(disableTitleKey),
-                            prompt: translate(disablePromptKey),
-                            confirmText: translate('common.disable'),
-                            cancelText: translate('common.cancel'),
-                        }).then((result) => {
-                            if (result.action !== ModalActions.CONFIRM) {
-                                return;
-                            }
-
-                            enableFields(policyID, false);
-                        });
-                        return;
-                    }
-
-                    if (!isControlPolicy(policy)) {
-                        Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(policyID, upgradeFeatureAlias, upgradeBackToRoute));
-                        return;
-                    }
-
-                    enableFields(policyID, true);
-                }}
-                disabled={hasAccountingConnections || !canWrite}
-                disabledAction={withReadOnlyFallback(onDisabledOrganizeSwitchPress)}
-                showLockIcon={!canWrite}
-                subMenuItems={
-                    isEnabled && (
-                        <>
-                            <View style={[shouldUseNarrowLayout ? styles.mhn5 : styles.mhn8, styles.mt6]}>
-                                {!isLoading && (
-                                    <FlashList
-                                        data={fields}
-                                        renderItem={renderItem}
-                                        keyExtractor={keyExtractor}
-                                        maintainVisibleContentPosition={{disabled: true}}
-                                    />
-                                )}
-                            </View>
-                            {!hasAccountingConnections && canWrite && (
-                                <MenuItem
-                                    onPress={() => Navigation.navigate(createRoute)}
-                                    title={translate(addFieldKey)}
-                                    icon={icons.Plus}
-                                    style={[styles.sectionMenuItemTopDescription]}
-                                />
-                            )}
-                        </>
-                    )
-                }
-            />
-        </Section>
-    );
-}
-
-export default WorkspaceFieldsSection;
diff --git a/src/pages/workspace/hr/HRProviderCard.tsx b/src/pages/workspace/hr/HRProviderCard.tsx
index 9505bf644310..2eb2e184a8a7 100644
--- a/src/pages/workspace/hr/HRProviderCard.tsx
+++ b/src/pages/workspace/hr/HRProviderCard.tsx
@@ -156,7 +156,7 @@ function HRProviderCard({card, policy, handleConnect, canWriteMoreFeatures, show
                 iconType={CONST.ICON_TYPE_AVATAR}
                 wrapperStyle={[styles.ph0, styles.pv2, !!lastSyncErrorMessage && styles.pb0]}
                 interactive={false}
-                description={card.completeSetupRoute ? undefined : connectionDescription}
+                description={!card.completeSetupRoute && card.isConnected ? connectionDescription : undefined}
                 descriptionAddon={
                     card.completeSetupRoute ? (
                         <RenderHTML html={translate('workspace.hr.mergeHR.setupIncomplete', canWriteMoreFeatures ? `${environmentURL}/${card.completeSetupRoute}` : undefined)} />
diff --git a/src/pages/workspace/hr/WorkspaceHRPage.tsx b/src/pages/workspace/hr/WorkspaceHRPage.tsx
index 71b9f2c5628a..55f7f90a5363 100644
--- a/src/pages/workspace/hr/WorkspaceHRPage.tsx
+++ b/src/pages/workspace/hr/WorkspaceHRPage.tsx
@@ -125,6 +125,7 @@ function WorkspaceHRPage({
                     <ConnectToHRFlow
                         key={activeHRFlow.key}
                         setupLink={activeHRFlow.setupLink}
+                        onDone={() => setActiveHRFlow(undefined)}
                     />
                 )}
                 <HeaderWithBackButton
diff --git a/src/pages/workspace/invoices/CreateInvoiceFieldsPage.tsx b/src/pages/workspace/invoices/CreateInvoiceFieldsPage.tsx
deleted file mode 100644
index 09d2fcfb6220..000000000000
--- a/src/pages/workspace/invoices/CreateInvoiceFieldsPage.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import CreateFieldsPage from '@pages/workspace/fields/CreateFieldsPage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
-
-type CreateInvoiceFieldsPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE>;
-
-function CreateInvoiceFieldsPage({
-    policy,
-    route: {
-        params: {policyID},
-    },
-}: CreateInvoiceFieldsPageProps) {
-    return (
-        <CreateFieldsPage
-            policy={policy}
-            policyID={policyID}
-            isInvoiceField
-            listValuesRoute={ROUTES.WORKSPACE_INVOICE_FIELDS_LIST_VALUES.getRoute(policyID)}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            testID="CreateInvoiceFieldsPage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(CreateInvoiceFieldsPage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsAddListValuePage.tsx b/src/pages/workspace/invoices/InvoiceFieldsAddListValuePage.tsx
deleted file mode 100644
index 2c5903371e3a..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsAddListValuePage.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsAddListValuePage from '@pages/workspace/fields/FieldsAddListValuePage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsAddListValuePageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE>;
-
-function InvoiceFieldsAddListValuePage({
-    policy,
-    route: {
-        params: {policyID, reportFieldID},
-    },
-}: InvoiceFieldsAddListValuePageProps) {
-    return (
-        <FieldsAddListValuePage
-            policy={policy}
-            policyID={policyID}
-            reportFieldID={reportFieldID}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            testID="InvoiceFieldsAddListValuePage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsAddListValuePage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsEditValuePage.tsx b/src/pages/workspace/invoices/InvoiceFieldsEditValuePage.tsx
deleted file mode 100644
index fa85ea322669..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsEditValuePage.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsEditValuePage from '@pages/workspace/fields/FieldsEditValuePage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsEditValuePageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE>;
-
-function InvoiceFieldsEditValuePage({
-    policy,
-    route: {
-        params: {policyID, valueIndex},
-    },
-}: InvoiceFieldsEditValuePageProps) {
-    return (
-        <FieldsEditValuePage
-            policy={policy}
-            policyID={policyID}
-            valueIndex={valueIndex}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            testID="InvoiceFieldsEditValuePage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsEditValuePage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsInitialValuePage.tsx b/src/pages/workspace/invoices/InvoiceFieldsInitialValuePage.tsx
deleted file mode 100644
index 37d848eb6ec4..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsInitialValuePage.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsInitialValuePage from '@pages/workspace/fields/FieldsInitialValuePage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsInitialValuePageProps = WithPolicyAndFullscreenLoadingProps &
-    PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE>;
-
-function InvoiceFieldsInitialValuePage({
-    policy,
-    route: {
-        params: {policyID, reportFieldID},
-    },
-}: InvoiceFieldsInitialValuePageProps) {
-    return (
-        <FieldsInitialValuePage
-            policy={policy}
-            policyID={policyID}
-            reportFieldID={reportFieldID}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            testID="InvoiceFieldsInitialValuePage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsInitialValuePage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsListValuesPage.tsx b/src/pages/workspace/invoices/InvoiceFieldsListValuesPage.tsx
deleted file mode 100644
index faad02a12da1..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsListValuesPage.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsListValuesPage from '@pages/workspace/fields/FieldsListValuesPage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsListValuesPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES>;
-
-function InvoiceFieldsListValuesPage({
-    policy,
-    route: {
-        params: {policyID, reportFieldID},
-    },
-}: InvoiceFieldsListValuesPageProps) {
-    return (
-        <FieldsListValuesPage
-            policy={policy}
-            policyID={policyID}
-            reportFieldID={reportFieldID}
-            isInvoicePage
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            getValueSettingsRoute={(isInvoiceRoute, id, valueIndex, fieldID) =>
-                isInvoiceRoute
-                    ? ROUTES.WORKSPACE_INVOICE_FIELDS_VALUE_SETTINGS.getRoute(id, valueIndex, fieldID)
-                    : ROUTES.WORKSPACE_REPORT_FIELDS_VALUE_SETTINGS.getRoute(id, valueIndex, fieldID)
-            }
-            getAddValueRoute={(isInvoiceRoute, id, fieldID) =>
-                isInvoiceRoute ? ROUTES.WORKSPACE_INVOICE_FIELDS_ADD_VALUE.getRoute(id, fieldID) : ROUTES.WORKSPACE_REPORT_FIELDS_ADD_VALUE.getRoute(id, fieldID)
-            }
-            testID="InvoiceFieldsListValuesPage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsListValuesPage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsSettingsPage.tsx b/src/pages/workspace/invoices/InvoiceFieldsSettingsPage.tsx
deleted file mode 100644
index 34d2d62452f7..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsSettingsPage.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsSettingsPage from '@pages/workspace/fields/FieldsSettingsPage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsSettingsPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS>;
-
-function InvoiceFieldsSettingsPage({
-    policy,
-    route: {
-        params: {policyID, reportFieldID},
-    },
-}: InvoiceFieldsSettingsPageProps) {
-    return (
-        <FieldsSettingsPage
-            policy={policy}
-            policyID={policyID}
-            reportFieldID={reportFieldID}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            expectedTarget={CONST.REPORT_FIELD_TARGETS.INVOICE}
-            getListValuesRoute={(id, fieldID) => ROUTES.WORKSPACE_INVOICE_FIELDS_LIST_VALUES.getRoute(id, fieldID)}
-            getInitialValueRoute={(id, fieldID) => ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_INITIAL_VALUE.getRoute(id, fieldID)}
-            deleteTitleKey="workspace.invoiceFields.delete"
-            deletePromptKey="workspace.invoiceFields.deleteConfirmation"
-            testID="InvoiceFieldsSettingsPage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsSettingsPage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsValueSettingsPage.tsx b/src/pages/workspace/invoices/InvoiceFieldsValueSettingsPage.tsx
deleted file mode 100644
index aa11fd1d4423..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsValueSettingsPage.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsValueSettingsPage from '@pages/workspace/fields/FieldsValueSettingsPage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsValueSettingsPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS>;
-
-function InvoiceFieldsValueSettingsPage({
-    policy,
-    route: {
-        params: {policyID, valueIndex, reportFieldID},
-    },
-}: InvoiceFieldsValueSettingsPageProps) {
-    return (
-        <FieldsValueSettingsPage
-            policy={policy}
-            policyID={policyID}
-            valueIndex={valueIndex}
-            reportFieldID={reportFieldID}
-            isInvoicePage
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            getEditValueRoute={(isInvoiceRoute, id, index) =>
-                isInvoiceRoute ? ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_VALUE.getRoute(id, index) : ROUTES.WORKSPACE_REPORT_FIELDS_EDIT_VALUE.getRoute(id, index)
-            }
-            testID="InvoiceFieldsValueSettingsPage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsValueSettingsPage);
diff --git a/src/pages/workspace/invoices/WorkspaceInvoiceFieldsSection.tsx b/src/pages/workspace/invoices/WorkspaceInvoiceFieldsSection.tsx
deleted file mode 100644
index b3f3b8ef0510..000000000000
--- a/src/pages/workspace/invoices/WorkspaceInvoiceFieldsSection.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react';
-import usePolicy from '@hooks/usePolicy';
-import {enablePolicyInvoiceFields} from '@libs/actions/Policy/Policy';
-import WorkspaceFieldsSection from '@pages/workspace/fields/WorkspaceFieldsSection';
-import {openPolicyInvoicesPage} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-
-type WorkspaceInvoiceFieldsSectionProps = {
-    policyID: string;
-};
-
-function WorkspaceInvoiceFieldsSection({policyID}: WorkspaceInvoiceFieldsSectionProps) {
-    const policy = usePolicy(policyID);
-
-    return (
-        <WorkspaceFieldsSection
-            policy={policy}
-            policyID={policyID}
-            isEnabled={!!policy?.areInvoiceFieldsEnabled}
-            pendingAction={policy?.pendingFields?.areInvoiceFieldsEnabled}
-            fieldFilter={(field) => field.target === CONST.REPORT_FIELD_TARGETS.INVOICE}
-            titleKey="workspace.common.invoiceFields"
-            subtitleKey="workspace.invoiceFields.subtitle"
-            importedFromAccountingSoftwareKey="workspace.invoiceFields.importedFromAccountingSoftware"
-            disableTitleKey="workspace.invoiceFields.disableInvoiceFields"
-            disablePromptKey="workspace.invoiceFields.disableInvoiceFieldsConfirmation"
-            addFieldKey="workspace.invoiceFields.addField"
-            createRoute={ROUTES.WORKSPACE_INVOICE_FIELDS_CREATE.getRoute(policyID)}
-            getSettingsRoute={ROUTES.WORKSPACE_INVOICE_FIELDS_SETTINGS.getRoute}
-            upgradeFeatureAlias={CONST.UPGRADE_FEATURE_INTRO_MAPPING.invoiceFields.alias}
-            upgradeBackToRoute={ROUTES.WORKSPACE_INVOICES.getRoute(policyID)}
-            enableFields={enablePolicyInvoiceFields}
-            openFieldsPage={openPolicyInvoicesPage}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-        />
-    );
-}
-
-WorkspaceInvoiceFieldsSection.displayName = 'WorkspaceInvoiceFieldsSection';
-
-export default WorkspaceInvoiceFieldsSection;
diff --git a/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx b/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
index 849baa0567a4..4766790eb1b8 100644
--- a/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
+++ b/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
@@ -53,11 +53,15 @@ function WorkspaceInvoiceVBASection({policyID, canWriteMoreFeatures, showReadOnl
     const {showConfirmModal} = useConfirmModal();
     // Determines whether or not the modal popup is mounted from the bottom of the screen instead of the side mount on Web screen
     const isPopoverBottomMount = shouldUseNarrowLayout;
-    const shouldShowMakeDefaultButton = !paymentMethod.isSelectedPaymentMethodDefault;
     const transferBankAccountID = policy?.invoice?.bankAccount?.transferBankAccountID ?? CONST.DEFAULT_NUMBER_ID;
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
 
-    const hasValidExistingAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, policy?.outputCurrency).length > 0;
+    const eligibleBusinessBankAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, policy?.outputCurrency);
+    const hasValidExistingAccounts = eligibleBusinessBankAccounts.length > 0;
+    const hasMultipleEligibleBankAccounts = eligibleBusinessBankAccounts.length > 1;
+    const hasInvoiceDefaultBankAccount = transferBankAccountID !== CONST.DEFAULT_NUMBER_ID;
+    const isInvoiceDefaultBankAccountMissing = hasInvoiceDefaultBankAccount && !eligibleBusinessBankAccounts.some((account) => account.accountData?.bankAccountID === transferBankAccountID);
+    const shouldShowMakeDefaultButton = !paymentMethod.isSelectedPaymentMethodDefault && (hasMultipleEligibleBankAccounts || isInvoiceDefaultBankAccountMissing);
     const isSupportedGlobalReimbursement = isCurrencySupportedForGlobalReimbursement((policy?.outputCurrency ?? '') as CurrencyType);
 
     const isNonUSDWorkspace = policy?.outputCurrency !== CONST.CURRENCY.USD;
@@ -106,10 +110,17 @@ function WorkspaceInvoiceVBASection({policyID, canWriteMoreFeatures, showReadOnl
 
     const deletePaymentMethod = useCallback(() => {
         const bankAccountID = paymentMethod.selectedPaymentMethod.bankAccountID;
-        if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT && bankAccountID) {
-            deletePaymentBankAccount(bankAccountID, personalPolicyID);
+        if (paymentMethod.selectedPaymentMethodType !== CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT || !bankAccountID) {
+            return;
+        }
+
+        const remainingEligibleBankAccountID = eligibleBusinessBankAccounts.find((account) => account.accountData?.bankAccountID !== bankAccountID)?.accountData?.bankAccountID;
+        if (transferBankAccountID === bankAccountID && remainingEligibleBankAccountID) {
+            setInvoicingTransferBankAccount(remainingEligibleBankAccountID, policyID, bankAccountID);
         }
-    }, [paymentMethod.selectedPaymentMethod.bankAccountID, paymentMethod.selectedPaymentMethodType, personalPolicyID]);
+
+        deletePaymentBankAccount(bankAccountID, personalPolicyID);
+    }, [eligibleBusinessBankAccounts, paymentMethod.selectedPaymentMethod.bankAccountID, paymentMethod.selectedPaymentMethodType, personalPolicyID, policyID, transferBankAccountID]);
 
     const makeDefaultPaymentMethod = useCallback(() => {
         // Find the previous default payment method so we can revert if the MakeDefaultPaymentMethod command errors
diff --git a/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx b/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx
index 1cd2bd91961a..836b4dbff4c6 100644
--- a/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx
+++ b/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx
@@ -14,7 +14,6 @@ import WorkspacePageWithSections from '@pages/workspace/WorkspacePageWithSection
 import CONST from '@src/CONST';
 import type SCREENS from '@src/SCREENS';
 import WorkspaceInvoiceBalanceSection from './WorkspaceInvoiceBalanceSection';
-import WorkspaceInvoiceFieldsSection from './WorkspaceInvoiceFieldsSection';
 import WorkspaceInvoiceVBASection from './WorkspaceInvoiceVBASection';
 import WorkspaceInvoicingDetailsSection from './WorkspaceInvoicingDetailsSection';
 
@@ -61,7 +60,6 @@ function WorkspaceInvoicesPage({route}: WorkspaceInvoicesPageProps) {
                                 canWriteMoreFeatures={canWriteMoreFeatures}
                             />
                         )}
-                        {!!policyID && <WorkspaceInvoiceFieldsSection policyID={policyID} />}
                     </View>
                 )}
             </WorkspacePageWithSections>
diff --git a/src/pages/workspace/members/ImportedMembersPage.tsx b/src/pages/workspace/members/ImportedMembersPage.tsx
index 57f485ab98e4..790d01383aa8 100644
--- a/src/pages/workspace/members/ImportedMembersPage.tsx
+++ b/src/pages/workspace/members/ImportedMembersPage.tsx
@@ -92,14 +92,16 @@ function ImportedMembersPage({route}: ImportedMembersPageProps) {
         const columns = Object.values(spreadsheet?.columns ?? {});
 
         const membersRolesColumn = columns.findIndex((column) => column === CONST.CSV_IMPORT_COLUMNS.ROLE);
-        const hasAuditorRole =
+        const controlPolicyOnlyRoles = [CONST.POLICY.ROLE.AUDITOR, CONST.POLICY.ROLE.CARD_ADMIN, CONST.POLICY.ROLE.PEOPLE_ADMIN, CONST.POLICY.ROLE.PAYMENTS_ADMIN];
+        const hasControlPolicyOnlyRole =
             membersRolesColumn !== -1 &&
-            spreadsheet?.data
-                ?.at(membersRolesColumn)
-                ?.some((role, index) => (containsHeader ? spreadsheet?.data?.at(membersRolesColumn)?.at(index + 1) : (role ?? '')) === CONST.POLICY.ROLE.AUDITOR);
+            spreadsheet?.data?.at(membersRolesColumn)?.some((role, index) => {
+                const memberRole = containsHeader ? spreadsheet?.data?.at(membersRolesColumn)?.at(index + 1) : (role ?? '');
+                return controlPolicyOnlyRoles.some((controlPolicyOnlyRole) => controlPolicyOnlyRole === memberRole);
+            });
 
-        if (hasAuditorRole && !isControlPolicy(policy)) {
-            Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(route.params.policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.auditor.alias, Navigation.getActiveRoute()));
+        if (hasControlPolicyOnlyRole && !isControlPolicy(policy)) {
+            Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(route.params.policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.controlPolicyRoles.alias, Navigation.getActiveRoute()));
             return;
         }
 
diff --git a/src/pages/workspace/reports/CreateReportFieldsPage.tsx b/src/pages/workspace/reports/CreateReportFieldsPage.tsx
index 0b068a78a6b7..5b5deafe055a 100644
--- a/src/pages/workspace/reports/CreateReportFieldsPage.tsx
+++ b/src/pages/workspace/reports/CreateReportFieldsPage.tsx
@@ -1,30 +1,285 @@
-import React from 'react';
+import React, {useCallback, useEffect, useRef} from 'react';
+import {View} from 'react-native';
+import type {OnyxCollection} from 'react-native-onyx';
+import FormProvider from '@components/Form/FormProvider';
+import InputWrapper from '@components/Form/InputWrapper';
+import type {FormInputErrors, FormOnyxValues, FormRef} from '@components/Form/types';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import ScreenWrapper from '@components/ScreenWrapper';
+import TextPicker from '@components/TextPicker';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import useThemeStyles from '@hooks/useThemeStyles';
+import DateUtils from '@libs/DateUtils';
+import {addErrorMessage} from '@libs/ErrorUtils';
+import {hasCircularReferences} from '@libs/Formula';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections} from '@libs/PolicyUtils';
+import {isRequiredFulfilled} from '@libs/ValidationUtils';
+import {getUnsupportedReportFieldFormulaParts, hasFormulaPartsInInitialValue, isReportFieldNameExisting} from '@libs/WorkspaceReportFieldUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import CreateFieldsPage from '@pages/workspace/fields/CreateFieldsPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {createReportField, setInitialCreateReportFieldsForm} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
+import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
+import type {Report} from '@src/types/onyx';
+import InitialListValueSelector from './InitialListValueSelector';
+import TypeSelector from './TypeSelector';
 
 type CreateReportFieldsPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_CREATE>;
 
+const defaultDate = DateUtils.extractDate(new Date().toString());
+
 function WorkspaceCreateReportFieldsPage({
     policy,
     route: {
         params: {policyID},
     },
 }: CreateReportFieldsPageProps) {
+    const styles = useThemeStyles();
+    const {translate, localeCompare} = useLocalize();
+    const formRef = useRef<FormRef>(null);
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+
+    const policyExpenseReportIDsSelector = useCallback(
+        (reports: OnyxCollection<Report>) =>
+            Object.values(reports ?? {})
+                .filter((report) => report?.policyID === policyID && report.type === CONST.REPORT.TYPE.EXPENSE)
+                .map((report) => report?.reportID),
+        [policyID],
+    );
+
+    const [policyExpenseReportIDs] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {
+        selector: policyExpenseReportIDsSelector,
+    });
+
+    const availableListValuesLength = (formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? []).filter((disabledListValue) => !disabledListValue).length;
+
+    const submitForm = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
+            createReportField({
+                policy,
+                name: values[INPUT_IDS.NAME],
+                type: values[INPUT_IDS.TYPE],
+                initialValue: !(values[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength === 0) ? values[INPUT_IDS.INITIAL_VALUE] : '',
+                listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
+                disabledListValues: formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? [],
+                policyExpenseReportIDs,
+            });
+            Navigation.goBack();
+        },
+        [availableListValuesLength, formDraft, policy, policyExpenseReportIDs],
+    );
+
+    const validateForm = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> => {
+            const {name, type, initialValue: formInitialValue} = values;
+            const errors: FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> = {};
+
+            if (!isRequiredFulfilled(name)) {
+                errors[INPUT_IDS.NAME] = translate('workspace.reportFields.reportFieldNameRequiredError');
+            } else if (isReportFieldNameExisting(policy?.fieldList, name)) {
+                errors[INPUT_IDS.NAME] = translate('workspace.reportFields.existingReportFieldNameError');
+            } else if ([...name].length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
+                // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 code units.
+                addErrorMessage(errors, INPUT_IDS.NAME, translate('common.error.characterLimitExceedCounter', [...name].length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH));
+            }
+
+            if (!isRequiredFulfilled(type)) {
+                errors[INPUT_IDS.TYPE] = translate('workspace.reportFields.reportFieldTypeRequiredError');
+            }
+
+            // formInitialValue can be undefined because the InitialValue component is rendered conditionally.
+            // If it's not been rendered when the validation is executed, formInitialValue will be undefined.
+            if (type === CONST.REPORT_FIELD_TYPES.TEXT && !!formInitialValue && formInitialValue.length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('common.error.characterLimitExceedCounter', formInitialValue.length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH);
+            }
+
+            if ((type === CONST.REPORT_FIELD_TYPES.TEXT || type === CONST.REPORT_FIELD_TYPES.FORMULA) && hasCircularReferences(formInitialValue, name, policy?.fieldList)) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.circularReferenceError');
+            }
+
+            if ((type === CONST.REPORT_FIELD_TYPES.TEXT || type === CONST.REPORT_FIELD_TYPES.FORMULA) && !!formInitialValue && !errors[INPUT_IDS.INITIAL_VALUE]) {
+                const unsupportedFormulaParts = getUnsupportedReportFieldFormulaParts(formInitialValue);
+                if (unsupportedFormulaParts.length > 0) {
+                    errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.unsupportedFormulaValueError', {
+                        value: unsupportedFormulaParts.join(', '),
+                    });
+                }
+            }
+
+            if (type === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && !isRequiredFulfilled(formInitialValue)) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.reportFieldInitialValueRequiredError');
+            }
+
+            return errors;
+        },
+        [availableListValuesLength, policy?.fieldList, translate],
+    );
+
+    const validateName = useCallback(
+        (values: Record<string, string>) => {
+            const errors: Record<string, string> = {};
+            const name = values[INPUT_IDS.NAME];
+            if (isReportFieldNameExisting(policy?.fieldList, name)) {
+                errors[INPUT_IDS.NAME] = translate('workspace.reportFields.existingReportFieldNameError');
+            }
+            return errors;
+        },
+        [policy?.fieldList, translate],
+    );
+
+    const handleOnValueCommitted = useCallback(
+        (inputValues: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => (initialValue: string) => {
+            // Mirror optimisticType logic from createReportField: if user enters a formula
+            // while type is Text, automatically switch the type to Formula in the form, otherwise back to Text.
+            const isFormula = hasFormulaPartsInInitialValue(initialValue);
+            if (isFormula) {
+                formRef.current?.resetForm({
+                    ...inputValues,
+                    [INPUT_IDS.TYPE]: CONST.REPORT_FIELD_TYPES.FORMULA,
+                    [INPUT_IDS.INITIAL_VALUE]: initialValue,
+                });
+            } else {
+                formRef.current?.resetForm({
+                    ...inputValues,
+                    [INPUT_IDS.TYPE]: CONST.REPORT_FIELD_TYPES.TEXT,
+                    [INPUT_IDS.INITIAL_VALUE]: initialValue,
+                });
+            }
+        },
+        [],
+    );
+
+    useEffect(() => {
+        setInitialCreateReportFieldsForm();
+    }, []);
+
+    const listValues = [...(formDraft?.[INPUT_IDS.LIST_VALUES] ?? [])].sort(localeCompare).join(', ');
+
     return (
-        <CreateFieldsPage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            isInvoiceField={false}
-            listValuesRoute={ROUTES.WORKSPACE_REPORT_FIELDS_LIST_VALUES.getRoute(policyID)}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
-            testID="WorkspaceCreateReportFieldsPage"
-        />
+            shouldBeBlocked={hasAccountingConnections(policy)}
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="WorkspaceCreateReportFieldsPage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate('workspace.reportFields.addField')}
+                    onBackButtonPress={Navigation.goBack}
+                />
+                <FormProvider
+                    ref={formRef}
+                    style={[styles.mh5, styles.flex1]}
+                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
+                    onSubmit={submitForm}
+                    validate={validateForm}
+                    submitButtonText={translate('common.save')}
+                    enabledWhenOffline
+                    shouldValidateOnBlur={false}
+                    addBottomSafeAreaPadding
+                    shouldUseStrictHtmlTagValidation
+                >
+                    {({inputValues}) => (
+                        <View style={styles.mhn5}>
+                            <InputWrapper
+                                InputComponent={TextPicker}
+                                inputID={INPUT_IDS.NAME}
+                                label={translate('common.name')}
+                                subtitle={translate('workspace.reportFields.nameInputSubtitle')}
+                                description={translate('common.name')}
+                                rightLabel={translate('common.required')}
+                                accessibilityLabel={translate('workspace.editor.nameInputLabel')}
+                                maxLength={CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH}
+                                multiline={false}
+                                role={CONST.ROLE.PRESENTATION}
+                                required
+                                customValidate={validateName}
+                                shouldUseStrictHtmlTagValidation
+                            />
+                            <InputWrapper
+                                InputComponent={TypeSelector}
+                                inputID={INPUT_IDS.TYPE}
+                                label={translate('common.type')}
+                                subtitle={translate('workspace.reportFields.typeInputSubtitle')}
+                                rightLabel={translate('common.required')}
+                                onTypeSelected={(type) => {
+                                    let initialValue;
+                                    if (type === CONST.REPORT_FIELD_TYPES.DATE) {
+                                        initialValue = defaultDate;
+                                    } else if (type === CONST.REPORT_FIELD_TYPES.FORMULA) {
+                                        initialValue = '{report:id}';
+                                    } else {
+                                        initialValue = '';
+                                    }
+
+                                    formRef.current?.resetForm({
+                                        ...inputValues,
+                                        type,
+                                        initialValue,
+                                    });
+                                }}
+                            />
+
+                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && (
+                                <MenuItemWithTopDescription
+                                    description={translate('workspace.reportFields.listValues')}
+                                    shouldShowRightIcon
+                                    onPress={() => Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_LIST_VALUES.getRoute(policyID))}
+                                    title={listValues}
+                                    numberOfLinesTitle={5}
+                                />
+                            )}
+
+                            {(inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.TEXT || inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.FORMULA) && (
+                                <InputWrapper
+                                    InputComponent={TextPicker}
+                                    inputID={INPUT_IDS.INITIAL_VALUE}
+                                    label={translate('common.initialValue')}
+                                    subtitle={translate('workspace.reportFields.initialValueInputSubtitle')}
+                                    description={translate('common.initialValue')}
+                                    accessibilityLabel={translate('workspace.editor.initialValueInputLabel')}
+                                    maxLength={CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH}
+                                    multiline={false}
+                                    role={CONST.ROLE.PRESENTATION}
+                                    onValueCommitted={handleOnValueCommitted(inputValues)}
+                                />
+                            )}
+
+                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.DATE && (
+                                <MenuItemWithTopDescription
+                                    title={translate('common.currentDate')}
+                                    description={translate('common.initialValue')}
+                                    rightLabel={translate('common.required')}
+                                    interactive={false}
+                                />
+                            )}
+
+                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && (
+                                <InputWrapper
+                                    InputComponent={InitialListValueSelector}
+                                    inputID={INPUT_IDS.INITIAL_VALUE}
+                                    label={translate('common.initialValue')}
+                                />
+                            )}
+                        </View>
+                    )}
+                </FormProvider>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsAddListValuePage.tsx b/src/pages/workspace/reports/ReportFieldsAddListValuePage.tsx
index 9d2539e51100..6e4aa986b611 100644
--- a/src/pages/workspace/reports/ReportFieldsAddListValuePage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsAddListValuePage.tsx
@@ -1,11 +1,29 @@
-import React from 'react';
+import React, {useCallback, useMemo} from 'react';
+import {Keyboard} from 'react-native';
+import FormProvider from '@components/Form/FormProvider';
+import InputWrapper from '@components/Form/InputWrapper';
+import type {FormOnyxValues} from '@components/Form/types';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ScreenWrapper from '@components/ScreenWrapper';
+import TextInput from '@components/TextInput';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections} from '@libs/PolicyUtils';
+import {getReportFieldKey} from '@libs/ReportUtils';
+import {validateReportFieldListValueName} from '@libs/WorkspaceReportFieldUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsAddListValuePage from '@pages/workspace/fields/FieldsAddListValuePage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {addReportFieldListValue, createReportFieldsListValue} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
+import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
 
 type ReportFieldsAddListValuePageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_ADD_VALUE>;
 
@@ -15,15 +33,83 @@ function ReportFieldsAddListValuePage({
         params: {policyID, reportFieldID},
     },
 }: ReportFieldsAddListValuePageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const {inputCallbackRef} = useAutoFocusInput();
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+
+    const listValues = useMemo(() => {
+        let reportFieldListValues: string[];
+        if (reportFieldID) {
+            const reportFieldKey = getReportFieldKey(reportFieldID);
+            reportFieldListValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {});
+        } else {
+            reportFieldListValues = formDraft?.[INPUT_IDS.LIST_VALUES] ?? [];
+        }
+        return reportFieldListValues;
+    }, [formDraft, policy?.fieldList, reportFieldID]);
+
+    const validate = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) =>
+            validateReportFieldListValueName(values[INPUT_IDS.VALUE_NAME].trim(), '', listValues, INPUT_IDS.VALUE_NAME, translate),
+        [listValues, translate],
+    );
+
+    const createValue = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
+            if (reportFieldID) {
+                addReportFieldListValue({policy, reportFieldID, valueName: values[INPUT_IDS.VALUE_NAME]});
+            } else {
+                createReportFieldsListValue({
+                    valueName: values[INPUT_IDS.VALUE_NAME],
+                    listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
+                    disabledListValues: formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? [],
+                });
+            }
+            Keyboard.dismiss();
+            Navigation.goBack();
+        },
+        [formDraft, policy, reportFieldID],
+    );
+
     return (
-        <FieldsAddListValuePage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            reportFieldID={reportFieldID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            testID="ReportFieldsAddListValuePage"
-        />
+            shouldBeBlocked={hasAccountingConnections(policy)}
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsAddListValuePage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate('workspace.reportFields.addValue')}
+                    onBackButtonPress={Navigation.goBack}
+                />
+                <FormProvider
+                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
+                    onSubmit={createValue}
+                    submitButtonText={translate('common.save')}
+                    validate={validate}
+                    style={[styles.mh5, styles.flex1]}
+                    enabledWhenOffline
+                    shouldHideFixErrorsAlert
+                    addBottomSafeAreaPadding
+                >
+                    <InputWrapper
+                        InputComponent={TextInput}
+                        label={translate('common.value')}
+                        accessibilityLabel={translate('common.value')}
+                        inputID={INPUT_IDS.VALUE_NAME}
+                        role={CONST.ROLE.PRESENTATION}
+                        ref={inputCallbackRef}
+                    />
+                </FormProvider>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsEditValuePage.tsx b/src/pages/workspace/reports/ReportFieldsEditValuePage.tsx
index a6e560eea958..4a9247b6071f 100644
--- a/src/pages/workspace/reports/ReportFieldsEditValuePage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsEditValuePage.tsx
@@ -1,11 +1,29 @@
-import React from 'react';
+import React, {useCallback} from 'react';
+import {Keyboard} from 'react-native';
+import FormProvider from '@components/Form/FormProvider';
+import InputWrapper from '@components/Form/InputWrapper';
+import type {FormOnyxValues} from '@components/Form/types';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ScreenWrapper from '@components/ScreenWrapper';
+import TextInput from '@components/TextInput';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections} from '@libs/PolicyUtils';
+import {validateReportFieldListValueName} from '@libs/WorkspaceReportFieldUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsEditValuePage from '@pages/workspace/fields/FieldsEditValuePage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {renameReportFieldsListValue} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
+import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
 
 type ReportFieldsEditValuePageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE>;
 
@@ -15,15 +33,78 @@ function ReportFieldsEditValuePage({
         params: {policyID, valueIndex},
     },
 }: ReportFieldsEditValuePageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const {inputCallbackRef} = useAutoFocusInput();
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+    const {canWrite: canWriteReportFields} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
+
+    const currentValueName = formDraft?.listValues?.[valueIndex] ?? '';
+
+    const validate = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) =>
+            validateReportFieldListValueName(values[INPUT_IDS.NEW_VALUE_NAME].trim(), currentValueName, formDraft?.[INPUT_IDS.LIST_VALUES] ?? [], INPUT_IDS.NEW_VALUE_NAME, translate),
+        [currentValueName, formDraft, translate],
+    );
+
+    const editValue = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
+            const valueName = values[INPUT_IDS.NEW_VALUE_NAME]?.trim();
+            if (currentValueName !== valueName) {
+                renameReportFieldsListValue({
+                    valueIndex,
+                    newValueName: valueName,
+                    listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
+                });
+            }
+            Keyboard.dismiss();
+            Navigation.goBack();
+        },
+        [currentValueName, formDraft, valueIndex],
+    );
+
     return (
-        <FieldsEditValuePage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            valueIndex={valueIndex}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            testID="ReportFieldsEditValuePage"
-        />
+            shouldBeBlocked={hasAccountingConnections(policy)}
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsEditValuePage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate('workspace.reportFields.editValue')}
+                    onBackButtonPress={Navigation.goBack}
+                />
+                <FormProvider
+                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
+                    onSubmit={editValue}
+                    submitButtonText={translate('common.save')}
+                    validate={validate}
+                    style={[styles.mh5, styles.flex1]}
+                    enabledWhenOffline
+                    shouldHideFixErrorsAlert
+                    addBottomSafeAreaPadding
+                    isSubmitButtonVisible={canWriteReportFields}
+                >
+                    <InputWrapper
+                        InputComponent={TextInput}
+                        defaultValue={currentValueName}
+                        label={translate('common.value')}
+                        accessibilityLabel={translate('common.value')}
+                        inputID={INPUT_IDS.NEW_VALUE_NAME}
+                        role={CONST.ROLE.PRESENTATION}
+                        ref={inputCallbackRef}
+                        disabled={!canWriteReportFields}
+                    />
+                </FormProvider>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsInitialValuePage.tsx b/src/pages/workspace/reports/ReportFieldsInitialValuePage.tsx
index 68fbc55020bf..00e5f16fc426 100644
--- a/src/pages/workspace/reports/ReportFieldsInitialValuePage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsInitialValuePage.tsx
@@ -1,29 +1,166 @@
-import React from 'react';
+import React, {useCallback, useState} from 'react';
+import {View} from 'react-native';
+import FormProvider from '@components/Form/FormProvider';
+import InputWrapper from '@components/Form/InputWrapper';
+import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ScreenWrapper from '@components/ScreenWrapper';
+import Text from '@components/Text';
+import TextInput from '@components/TextInput';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {hasCircularReferences} from '@libs/Formula';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsInitialValuePage from '@pages/workspace/fields/FieldsInitialValuePage';
+import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import {getReportFieldKey} from '@libs/ReportUtils';
+import {isRequiredFulfilled} from '@libs/ValidationUtils';
+import {getReportFieldInitialValue, getUnsupportedReportFieldFormulaParts} from '@libs/WorkspaceReportFieldUtils';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {updateReportFieldInitialValue} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
+import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
+import ReportFieldsInitialListValuePicker from './InitialListValueSelector/ReportFieldsInitialListValuePicker';
 
 type ReportFieldsInitialValuePageProps = WithPolicyAndFullscreenLoadingProps &
     PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE>;
-
 function ReportFieldsInitialValuePage({
     policy,
     route: {
         params: {policyID, reportFieldID},
     },
 }: ReportFieldsInitialValuePageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const {inputCallbackRef} = useAutoFocusInput();
+
+    const reportField = policy?.fieldList?.[getReportFieldKey(reportFieldID)] ?? null;
+    const availableListValuesLength = (reportField?.disabledOptions ?? []).filter((disabledListValue) => !disabledListValue).length;
+    const currentInitialValue = getReportFieldInitialValue(reportField, translate);
+    const [initialValue, setInitialValue] = useState(currentInitialValue);
+
+    const submitForm = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
+            if (currentInitialValue !== values.initialValue) {
+                updateReportFieldInitialValue({policy, reportFieldID, newInitialValue: values.initialValue});
+            }
+            Navigation.goBack();
+        },
+        [currentInitialValue, policy, reportFieldID],
+    );
+
+    const submitListValueUpdate = (value: string) => {
+        updateReportFieldInitialValue({policy, reportFieldID, newInitialValue: currentInitialValue === value ? '' : value});
+        Navigation.goBack();
+    };
+
+    const validateForm = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> => {
+            const {initialValue: formInitialValue} = values;
+            const errors: FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> = {};
+
+            if (formInitialValue.length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('common.error.characterLimitExceedCounter', formInitialValue.length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH);
+            }
+
+            if (
+                (reportField?.type === CONST.REPORT_FIELD_TYPES.TEXT || reportField?.type === CONST.REPORT_FIELD_TYPES.FORMULA) &&
+                hasCircularReferences(formInitialValue, reportField?.name, policy?.fieldList)
+            ) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.circularReferenceError');
+            }
+
+            if ((reportField?.type === CONST.REPORT_FIELD_TYPES.TEXT || reportField?.type === CONST.REPORT_FIELD_TYPES.FORMULA) && !!formInitialValue && !errors[INPUT_IDS.INITIAL_VALUE]) {
+                const unsupportedFormulaParts = getUnsupportedReportFieldFormulaParts(formInitialValue);
+                if (unsupportedFormulaParts.length > 0) {
+                    errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.unsupportedFormulaValueError', {
+                        value: unsupportedFormulaParts.join(', '),
+                    });
+                }
+            }
+
+            if (reportField?.type === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && !isRequiredFulfilled(formInitialValue)) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.reportFieldInitialValueRequiredError');
+            }
+
+            return errors;
+        },
+        [availableListValuesLength, reportField?.name, reportField?.type, policy?.fieldList, translate],
+    );
+
+    if (!reportField) {
+        return <NotFoundPage />;
+    }
+
+    const isTextFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.TEXT;
+    const isFormulaFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.FORMULA;
+    const isListFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.LIST;
+
     return (
-        <FieldsInitialValuePage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            reportFieldID={reportFieldID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
-            testID="ReportFieldsInitialValuePage"
-        />
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsInitialValuePage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate('common.initialValue')}
+                    onBackButtonPress={Navigation.goBack}
+                />
+                {isListFieldType && (
+                    <View style={[styles.ph5, styles.pb4]}>
+                        <Text style={[styles.sidebarLinkText, styles.optionAlternateText]}>{translate('workspace.reportFields.listValuesInputSubtitle')}</Text>
+                    </View>
+                )}
+
+                {(isTextFieldType || isFormulaFieldType) && (
+                    <FormProvider
+                        addBottomSafeAreaPadding
+                        formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
+                        onSubmit={submitForm}
+                        submitButtonText={translate('common.save')}
+                        validate={validateForm}
+                        style={styles.flex1}
+                        enabledWhenOffline
+                        isSubmitButtonVisible
+                        submitButtonStyles={styles.mh5}
+                        shouldHideFixErrorsAlert
+                    >
+                        <InputWrapper
+                            containerStyles={styles.mh5}
+                            InputComponent={TextInput}
+                            inputID={INPUT_IDS.INITIAL_VALUE}
+                            label={translate('common.initialValue')}
+                            accessibilityLabel={translate('workspace.editor.initialValueInputLabel')}
+                            multiline={false}
+                            value={initialValue}
+                            role={CONST.ROLE.PRESENTATION}
+                            ref={inputCallbackRef}
+                            onChangeText={setInitialValue}
+                        />
+                    </FormProvider>
+                )}
+                {isListFieldType && (
+                    <ReportFieldsInitialListValuePicker
+                        listValues={reportField.values}
+                        disabledOptions={reportField.disabledOptions}
+                        value={initialValue}
+                        onValueChange={submitListValueUpdate}
+                    />
+                )}
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsListValuesPage.tsx b/src/pages/workspace/reports/ReportFieldsListValuesPage.tsx
index 4d422631c213..ddb277d4f350 100644
--- a/src/pages/workspace/reports/ReportFieldsListValuesPage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsListValuesPage.tsx
@@ -1,12 +1,64 @@
-import React from 'react';
+import React, {useCallback, useMemo, useState} from 'react';
+import {View} from 'react-native';
+import Button from '@components/Button';
+import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
+import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import {ModalActions} from '@components/Modal/Global/ModalContext';
+import ScreenWrapper from '@components/ScreenWrapper';
+import ScrollView from '@components/ScrollView';
+import SearchBar from '@components/SearchBar';
+import TableListItem from '@components/SelectionList/ListItem/TableListItem';
+import type {ListItem} from '@components/SelectionList/types';
+import SelectionListWithModal from '@components/SelectionListWithModal';
+import CustomListHeader from '@components/SelectionListWithModal/CustomListHeader';
+import Switch from '@components/Switch';
+import Text from '@components/Text';
+import useConfirmModal from '@hooks/useConfirmModal';
+import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
+import useOnyx from '@hooks/useOnyx';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useSearchBackPress from '@hooks/useSearchBackPress';
+import useSearchResults from '@hooks/useSearchResults';
+import useShouldDisplayButtonsInSeparateLine from '@hooks/useShouldDisplayButtonsInSeparateLine';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
+import {
+    deleteReportFieldsListValue,
+    removeReportFieldListValue,
+    setReportFieldsListValueEnabled,
+    updateReportFieldListValueEnabled as updateReportFieldListValueEnabledReportField,
+} from '@libs/actions/Policy/ReportField';
+import {canUseTouchScreen} from '@libs/DeviceCapabilities';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections as hasAccountingConnectionsPolicyUtils} from '@libs/PolicyUtils';
+import {getReportFieldKey} from '@libs/ReportUtils';
+import StringUtils from '@libs/StringUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsListValuesPage from '@pages/workspace/fields/FieldsListValuesPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
+import type DeepValueOf from '@src/types/utils/DeepValueOf';
+
+type ValueListItem = ListItem & {
+    /** The value */
+    value: string;
+
+    /** Whether the value is enabled */
+    enabled: boolean;
+
+    /** The value order weight in the list */
+    orderWeight?: number;
+};
 
 type ReportFieldsListValuesPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_LIST_VALUES>;
 
@@ -16,24 +68,363 @@ function ReportFieldsListValuesPage({
         params: {policyID, reportFieldID},
     },
 }: ReportFieldsListValuesPageProps) {
+    const styles = useThemeStyles();
+    const {translate, localeCompare} = useLocalize();
+    // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout here to use the mobile selection mode on small screens only
+    // See https://github.com/Expensify/App/issues/48724 for more details
+    // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
+    const {isSmallScreenWidth} = useResponsiveLayout();
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+    const isMobileSelectionModeEnabled = useMobileSelectionMode();
+    const illustrations = useMemoizedLazyIllustrations(['FolderWithPapers']);
+    const {showConfirmModal} = useConfirmModal();
+    const {canWrite: canWriteReportFields, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
+
+    const [selectedValues, setSelectedValues] = useState<Record<string, boolean>>({});
+    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
+
+    const canSelectMultiple = canWriteReportFields && (isSmallScreenWidth ? isMobileSelectionModeEnabled : true);
+
+    const [listValues, disabledListValues] = useMemo(() => {
+        let reportFieldValues: string[];
+        let reportFieldDisabledValues: boolean[];
+
+        if (reportFieldID) {
+            const reportFieldKey = getReportFieldKey(reportFieldID);
+
+            reportFieldValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {});
+            reportFieldDisabledValues = Object.values(policy?.fieldList?.[reportFieldKey]?.disabledOptions ?? {});
+        } else {
+            reportFieldValues = formDraft?.listValues ?? [];
+            reportFieldDisabledValues = formDraft?.disabledListValues ?? [];
+        }
+
+        return [reportFieldValues, reportFieldDisabledValues];
+    }, [formDraft?.disabledListValues, formDraft?.listValues, policy?.fieldList, reportFieldID]);
+
+    const updateReportFieldListValueEnabled = useCallback(
+        (value: boolean, valueIndex: number) => {
+            if (reportFieldID) {
+                updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: [Number(valueIndex)], enabled: value});
+                return;
+            }
+
+            setReportFieldsListValueEnabled({
+                valueIndexes: [valueIndex],
+                enabled: value,
+                disabledListValues,
+            });
+        },
+        [disabledListValues, policy, reportFieldID],
+    );
+
+    useSearchBackPress({
+        onClearSelection: () => {
+            setSelectedValues({});
+        },
+        onNavigationCallBack: () => Navigation.goBack(),
+    });
+
+    const data = useMemo(
+        () =>
+            listValues.map<ValueListItem>((value, index) => ({
+                value,
+                index,
+                text: value,
+                keyForList: value,
+                isSelected: selectedValues[value] && canSelectMultiple,
+                enabled: !disabledListValues.at(index),
+                rightElement: (
+                    <Switch
+                        isOn={!disabledListValues.at(index)}
+                        accessibilityLabel={translate('workspace.distanceRates.trackTax')}
+                        onToggle={(newValue: boolean) => updateReportFieldListValueEnabled(newValue, index)}
+                        disabled={!canWriteReportFields}
+                        disabledAction={withReadOnlyFallback()}
+                        showLockIcon={!canWriteReportFields}
+                    />
+                ),
+            })),
+        [canSelectMultiple, canWriteReportFields, disabledListValues, withReadOnlyFallback, listValues, selectedValues, translate, updateReportFieldListValueEnabled],
+    );
+
+    const filterListValue = useCallback((item: ValueListItem, searchInput: string) => {
+        const itemText = StringUtils.normalize(item.text?.toLowerCase() ?? '');
+        const normalizedSearchInput = StringUtils.normalize(searchInput.toLowerCase());
+        return itemText.includes(normalizedSearchInput);
+    }, []);
+    const sortListValues = useCallback((values: ValueListItem[]) => values.sort((a, b) => localeCompare(a.value, b.value)), [localeCompare]);
+    const [inputValue, setInputValue, filteredListValues] = useSearchResults(data, filterListValue, sortListValues);
+    const icons = useMemoizedLazyExpensifyIcons(['Checkmark', 'Close', 'Plus', 'Trashcan']);
+
+    const filteredListValuesArray = filteredListValues.map((item) => item.value);
+
+    const shouldShowEmptyState = Object.values(listValues ?? {}).length <= 0;
+    const selectedValuesArray = Object.keys(selectedValues).filter((key) => selectedValues[key] && listValues.includes(key));
+
+    const toggleValue = (valueItem: ValueListItem) => {
+        setSelectedValues((prev) => ({
+            ...prev,
+            [valueItem.value]: !prev[valueItem.value],
+        }));
+    };
+
+    const toggleAllValues = () => {
+        setSelectedValues(selectedValuesArray.length > 0 ? {} : Object.fromEntries(filteredListValuesArray.map((value) => [value, true])));
+    };
+
+    const handleDeleteValues = () => {
+        const valuesToDelete = selectedValuesArray.reduce<number[]>((acc, valueName) => {
+            const index = listValues?.indexOf(valueName) ?? -1;
+
+            if (index !== -1) {
+                acc.push(index);
+            }
+
+            return acc;
+        }, []);
+
+        if (reportFieldID) {
+            removeReportFieldListValue({policy, reportFieldID, valueIndexes: valuesToDelete});
+        } else {
+            deleteReportFieldsListValue({
+                valueIndexes: valuesToDelete,
+                listValues,
+                disabledListValues,
+            });
+        }
+
+        setSelectedValues({});
+    };
+
+    const openListValuePage = (valueItem: ValueListItem) => {
+        if (valueItem.index === undefined) {
+            return;
+        }
+
+        Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_VALUE_SETTINGS.getRoute(policyID, valueItem.index, reportFieldID));
+    };
+
+    const getCustomListHeader = () => {
+        if (filteredListValues.length === 0) {
+            return null;
+        }
+        return (
+            <CustomListHeader
+                canSelectMultiple={canSelectMultiple}
+                leftHeaderText={translate('common.name')}
+                rightHeaderText={translate('common.enabled')}
+                shouldShowRightCaret
+            />
+        );
+    };
+
+    const shouldDisplayButtonsInSeparateLine = useShouldDisplayButtonsInSeparateLine();
+
+    const getHeaderButtons = () => {
+        const options: Array<DropdownOption<DeepValueOf<typeof CONST.POLICY.BULK_ACTION_TYPES>>> = [];
+        if (canWriteReportFields && (isSmallScreenWidth ? isMobileSelectionModeEnabled : selectedValuesArray.length > 0)) {
+            if (selectedValuesArray.length > 0 && !hasAccountingConnections) {
+                options.push({
+                    icon: icons.Trashcan,
+                    text: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValue' : 'workspace.reportFields.deleteValues'),
+                    value: CONST.POLICY.BULK_ACTION_TYPES.DELETE,
+                    onSelected: () => {
+                        showConfirmModal({
+                            danger: true,
+                            title: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValue' : 'workspace.reportFields.deleteValues'),
+                            prompt: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValuePrompt' : 'workspace.reportFields.deleteValuesPrompt'),
+                            confirmText: translate('common.delete'),
+                            cancelText: translate('common.cancel'),
+                        }).then((result) => {
+                            if (result.action !== ModalActions.CONFIRM) {
+                                return;
+                            }
+
+                            handleDeleteValues();
+                        });
+                    },
+                });
+            }
+            const enabledValues = selectedValuesArray.filter((valueName) => {
+                const index = listValues?.indexOf(valueName) ?? -1;
+                return !disabledListValues?.at(index);
+            });
+
+            if (enabledValues.length > 0) {
+                const valuesToDisable = selectedValuesArray.reduce<number[]>((acc, valueName) => {
+                    const index = listValues?.indexOf(valueName) ?? -1;
+                    if (!disabledListValues?.at(index) && index !== -1) {
+                        acc.push(index);
+                    }
+
+                    return acc;
+                }, []);
+
+                options.push({
+                    icon: icons.Close,
+                    text: translate(enabledValues.length === 1 ? 'workspace.reportFields.disableValue' : 'workspace.reportFields.disableValues'),
+                    value: CONST.POLICY.BULK_ACTION_TYPES.DISABLE,
+                    onSelected: () => {
+                        setSelectedValues({});
+
+                        if (reportFieldID) {
+                            updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: valuesToDisable, enabled: false});
+                            return;
+                        }
+
+                        setReportFieldsListValueEnabled({
+                            valueIndexes: valuesToDisable,
+                            enabled: false,
+                            disabledListValues,
+                        });
+                    },
+                });
+            }
+
+            const disabledValues = selectedValuesArray.filter((valueName) => {
+                const index = listValues?.indexOf(valueName) ?? -1;
+                return disabledListValues?.at(index);
+            });
+
+            if (disabledValues.length > 0) {
+                const valuesToEnable = selectedValuesArray.reduce<number[]>((acc, valueName) => {
+                    const index = listValues?.indexOf(valueName) ?? -1;
+                    if (disabledListValues?.at(index) && index !== -1) {
+                        acc.push(index);
+                    }
+
+                    return acc;
+                }, []);
+
+                options.push({
+                    icon: icons.Checkmark,
+                    text: translate(disabledValues.length === 1 ? 'workspace.reportFields.enableValue' : 'workspace.reportFields.enableValues'),
+                    value: CONST.POLICY.BULK_ACTION_TYPES.ENABLE,
+                    onSelected: () => {
+                        setSelectedValues({});
+
+                        if (reportFieldID) {
+                            updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: valuesToEnable, enabled: true});
+                            return;
+                        }
+
+                        setReportFieldsListValueEnabled({
+                            valueIndexes: valuesToEnable,
+                            enabled: true,
+                            disabledListValues,
+                        });
+                    },
+                });
+            }
+
+            return (
+                <ButtonWithDropdownMenu
+                    onPress={() => null}
+                    shouldAlwaysShowDropdownMenu
+                    buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM}
+                    customText={translate('workspace.common.selected', {count: selectedValuesArray.length})}
+                    options={options}
+                    isSplitButton={false}
+                    style={[shouldDisplayButtonsInSeparateLine && styles.flexGrow1, shouldDisplayButtonsInSeparateLine && styles.mb3]}
+                    isDisabled={!selectedValuesArray.length}
+                />
+            );
+        }
+
+        if (canWriteReportFields && !hasAccountingConnections) {
+            return (
+                <Button
+                    style={[shouldDisplayButtonsInSeparateLine && styles.flexGrow1, shouldDisplayButtonsInSeparateLine && styles.mb3]}
+                    success
+                    icon={icons.Plus}
+                    text={translate('workspace.reportFields.addValue')}
+                    onPress={() => Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_ADD_VALUE.getRoute(policyID, reportFieldID))}
+                />
+            );
+        }
+    };
+
+    const selectionModeHeader = isMobileSelectionModeEnabled && isSmallScreenWidth;
+
+    const headerContent = (
+        <>
+            <View style={[styles.ph5, styles.pv4]}>
+                <Text style={[styles.sidebarLinkText, styles.optionAlternateText]}>{translate('workspace.reportFields.listInputSubtitle')}</Text>
+            </View>
+            {data.length >= CONST.STANDARD_LIST_ITEM_LIMIT && (
+                <SearchBar
+                    label={translate('workspace.reportFields.findReportField')}
+                    inputValue={inputValue}
+                    onChangeText={setInputValue}
+                    shouldShowEmptyState={!shouldShowEmptyState && filteredListValues.length === 0}
+                />
+            )}
+        </>
+    );
+
     return (
-        <FieldsListValuesPage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            reportFieldID={reportFieldID}
-            isInvoicePage={false}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            getValueSettingsRoute={(isInvoiceRoute, id, valueIndex, fieldID) =>
-                isInvoiceRoute
-                    ? ROUTES.WORKSPACE_INVOICE_FIELDS_VALUE_SETTINGS.getRoute(id, valueIndex, fieldID)
-                    : ROUTES.WORKSPACE_REPORT_FIELDS_VALUE_SETTINGS.getRoute(id, valueIndex, fieldID)
-            }
-            getAddValueRoute={(isInvoiceRoute, id, fieldID) =>
-                isInvoiceRoute ? ROUTES.WORKSPACE_INVOICE_FIELDS_ADD_VALUE.getRoute(id, fieldID) : ROUTES.WORKSPACE_REPORT_FIELDS_ADD_VALUE.getRoute(id, fieldID)
-            }
-            testID="ReportFieldsListValuesPage"
-        />
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsListValuesPage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate(selectionModeHeader ? 'common.selectMultiple' : 'workspace.reportFields.listValues')}
+                    onBackButtonPress={() => {
+                        if (isMobileSelectionModeEnabled) {
+                            setSelectedValues({});
+                            turnOffMobileSelectionMode();
+                            return;
+                        }
+                        Navigation.goBack();
+                    }}
+                >
+                    {!shouldDisplayButtonsInSeparateLine && getHeaderButtons()}
+                </HeaderWithBackButton>
+                {shouldDisplayButtonsInSeparateLine && <View style={[styles.pl5, styles.pr5]}>{getHeaderButtons()}</View>}
+                {shouldShowEmptyState && (
+                    <ScrollView contentContainerStyle={[styles.flexGrow1, styles.flexShrink0]}>
+                        {headerContent}
+                        <EmptyStateComponent
+                            title={translate('workspace.reportFields.emptyReportFieldsValues.title')}
+                            subtitle={translate('workspace.reportFields.emptyReportFieldsValues.subtitle')}
+                            headerMedia={illustrations.FolderWithPapers}
+                            headerStyles={styles.emptyStateCardIllustrationContainer}
+                            headerContentStyles={styles.emptyStateFolderWithPaperIconSize}
+                        />
+                    </ScrollView>
+                )}
+                {!shouldShowEmptyState && (
+                    <SelectionListWithModal
+                        data={filteredListValues}
+                        ListItem={TableListItem}
+                        onSelectRow={openListValuePage}
+                        selectedItems={selectedValuesArray}
+                        onSelectAll={canWriteReportFields && filteredListValues.length > 0 ? toggleAllValues : undefined}
+                        onTurnOnSelectionMode={(item) => item && canWriteReportFields && toggleValue(item)}
+                        shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
+                        customListHeader={getCustomListHeader()}
+                        customListHeaderContent={headerContent}
+                        canSelectMultiple={canSelectMultiple}
+                        selectAllAccessibilityLabel={translate('accessibilityHints.selectAllValues')}
+                        onSelectionButtonPress={toggleValue}
+                        shouldShowListEmptyContent={false}
+                        showScrollIndicator={false}
+                        turnOnSelectionModeOnLongPress={canWriteReportFields}
+                        shouldHeaderBeInsideList
+                        shouldShowRightCaret
+                    />
+                )}
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsSettingsPage.tsx b/src/pages/workspace/reports/ReportFieldsSettingsPage.tsx
index b68eeda0dd55..443c46529177 100644
--- a/src/pages/workspace/reports/ReportFieldsSettingsPage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsSettingsPage.tsx
@@ -1,9 +1,27 @@
+import {Str} from 'expensify-common';
 import React from 'react';
+import {View} from 'react-native';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import {ModalActions} from '@components/Modal/Global/ModalContext';
+import ScreenWrapper from '@components/ScreenWrapper';
+import useConfirmModal from '@hooks/useConfirmModal';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections as hasAccountingConnectionsPolicyUtils} from '@libs/PolicyUtils';
+import {getReportFieldKey} from '@libs/ReportUtils';
+import {getReportFieldInitialValue, getReportFieldTypeTranslationKey} from '@libs/WorkspaceReportFieldUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsSettingsPage from '@pages/workspace/fields/FieldsSettingsPage';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {deleteReportFields} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
@@ -16,18 +34,108 @@ function ReportFieldsSettingsPage({
         params: {policyID, reportFieldID},
     },
 }: ReportFieldsSettingsPageProps) {
+    const styles = useThemeStyles();
+    const {translate, localeCompare} = useLocalize();
+    const {showConfirmModal} = useConfirmModal();
+    const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
+    const {canWrite: canWriteReportFields} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
+
+    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
+    const reportFieldKey = getReportFieldKey(reportFieldID);
+    const reportField = policy?.fieldList?.[reportFieldKey] ?? null;
+
+    if (!reportField) {
+        return <NotFoundPage />;
+    }
+
+    const isDateFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.DATE;
+    const isListFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.LIST;
+    const isListFieldEmpty = isListFieldType && reportField.disabledOptions.filter((disabledListValue) => !disabledListValue).length <= 0;
+    const listValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {})?.sort(localeCompare);
+
+    const confirmAndDeleteReportField = async () => {
+        const result = await showConfirmModal({
+            danger: true,
+            title: translate('workspace.reportFields.delete'),
+            prompt: translate('workspace.reportFields.deleteConfirmation'),
+            confirmText: translate('common.delete'),
+            cancelText: translate('common.cancel'),
+            shouldSetModalVisibility: false,
+        });
+
+        if (result.action !== ModalActions.CONFIRM) {
+            return;
+        }
+
+        deleteReportFields({policy, reportFieldsToUpdate: [reportFieldKey]});
+        Navigation.goBack();
+    };
+
     return (
-        <FieldsSettingsPage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            reportFieldID={reportFieldID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            expectedTarget={CONST.REPORT_FIELD_TARGETS.EXPENSE}
-            getListValuesRoute={(id, fieldID) => ROUTES.WORKSPACE_REPORT_FIELDS_LIST_VALUES.getRoute(id, fieldID)}
-            getInitialValueRoute={(id, fieldID) => ROUTES.WORKSPACE_EDIT_REPORT_FIELDS_INITIAL_VALUE.getRoute(id, fieldID)}
-            testID="ReportFieldsSettingsPage"
-        />
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={[styles.defaultModalContainer]}
+                testID="ReportFieldsSettingsPage"
+            >
+                <HeaderWithBackButton
+                    title={reportField.name}
+                    shouldSetModalVisibility={false}
+                />
+                <View style={styles.flexGrow1}>
+                    <MenuItemWithTopDescription
+                        style={[styles.moneyRequestMenuItem]}
+                        titleStyle={styles.flex1}
+                        title={reportField.name}
+                        description={translate('common.name')}
+                        interactive={false}
+                    />
+                    <MenuItemWithTopDescription
+                        style={[styles.moneyRequestMenuItem]}
+                        titleStyle={styles.flex1}
+                        title={Str.recapitalize(translate(getReportFieldTypeTranslationKey(reportField.type)))}
+                        description={translate('common.type')}
+                        interactive={false}
+                    />
+                    {isListFieldType && (
+                        <MenuItemWithTopDescription
+                            style={[styles.moneyRequestMenuItem]}
+                            titleStyle={styles.flex1}
+                            description={translate('workspace.reportFields.listValues')}
+                            shouldShowRightIcon
+                            onPress={() => Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_LIST_VALUES.getRoute(policyID, reportFieldID))}
+                            title={listValues.join(', ')}
+                            numberOfLinesTitle={5}
+                        />
+                    )}
+                    {!isListFieldEmpty && (
+                        <MenuItemWithTopDescription
+                            style={[styles.moneyRequestMenuItem]}
+                            titleStyle={styles.flex1}
+                            title={getReportFieldInitialValue(reportField, translate)}
+                            description={translate('common.initialValue')}
+                            shouldShowRightIcon={canWriteReportFields && !isDateFieldType}
+                            interactive={canWriteReportFields && !isDateFieldType}
+                            onPress={() => Navigation.navigate(ROUTES.WORKSPACE_EDIT_REPORT_FIELDS_INITIAL_VALUE.getRoute(policyID, reportFieldID))}
+                        />
+                    )}
+                    {canWriteReportFields && !hasAccountingConnections && (
+                        <View style={styles.flexGrow1}>
+                            <MenuItem
+                                icon={icons.Trashcan}
+                                title={translate('common.delete')}
+                                onPress={confirmAndDeleteReportField}
+                            />
+                        </View>
+                    )}
+                </View>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsValueSettingsPage.tsx b/src/pages/workspace/reports/ReportFieldsValueSettingsPage.tsx
index aca3618eeab0..e3b4f33f358f 100644
--- a/src/pages/workspace/reports/ReportFieldsValueSettingsPage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsValueSettingsPage.tsx
@@ -1,10 +1,31 @@
-import React from 'react';
+import React, {useMemo} from 'react';
+import {View} from 'react-native';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import {ModalActions} from '@components/Modal/Global/ModalContext';
+import ScreenWrapper from '@components/ScreenWrapper';
+import Switch from '@components/Switch';
+import Text from '@components/Text';
+import useConfirmModal from '@hooks/useConfirmModal';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
+import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {deleteReportFieldsListValue, removeReportFieldListValue, setReportFieldsListValueEnabled, updateReportFieldListValueEnabled} from '@libs/actions/Policy/ReportField';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections as hasAccountingConnectionsUtil} from '@libs/PolicyUtils';
+import {getReportFieldKey} from '@libs/ReportUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsValueSettingsPage from '@pages/workspace/fields/FieldsValueSettingsPage';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 
@@ -16,20 +37,131 @@ function ReportFieldsValueSettingsPage({
         params: {policyID, valueIndex, reportFieldID},
     },
 }: ReportFieldsValueSettingsPageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+    const {showConfirmModal} = useConfirmModal();
+    const {canWrite: canWriteReportFields, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
+
+    const [currentValueName, currentValueDisabled] = useMemo(() => {
+        let reportFieldValue: string;
+        let reportFieldDisabledValue: boolean;
+
+        if (reportFieldID) {
+            const reportFieldKey = getReportFieldKey(reportFieldID);
+
+            reportFieldValue = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {})?.at(valueIndex) ?? '';
+            reportFieldDisabledValue = Object.values(policy?.fieldList?.[reportFieldKey]?.disabledOptions ?? {})?.at(valueIndex) ?? false;
+        } else {
+            reportFieldValue = formDraft?.listValues?.[valueIndex] ?? '';
+            reportFieldDisabledValue = formDraft?.disabledListValues?.[valueIndex] ?? false;
+        }
+
+        return [reportFieldValue, reportFieldDisabledValue];
+    }, [formDraft?.disabledListValues, formDraft?.listValues, policy?.fieldList, reportFieldID, valueIndex]);
+
+    const hasAccountingConnections = hasAccountingConnectionsUtil(policy);
+    const oldValueName = usePrevious(currentValueName);
+    const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
+
+    if (!currentValueName && !oldValueName) {
+        return <NotFoundPage />;
+    }
+    const confirmAndDeleteListValue = async () => {
+        const result = await showConfirmModal({
+            danger: true,
+            title: translate('workspace.reportFields.deleteValue'),
+            prompt: translate('workspace.reportFields.deleteValuePrompt'),
+            confirmText: translate('common.delete'),
+            cancelText: translate('common.cancel'),
+            shouldSetModalVisibility: false,
+        });
+
+        if (result.action !== ModalActions.CONFIRM) {
+            return;
+        }
+
+        if (reportFieldID) {
+            removeReportFieldListValue({policy, reportFieldID, valueIndexes: [valueIndex]});
+        } else {
+            deleteReportFieldsListValue({
+                valueIndexes: [valueIndex],
+                listValues: formDraft?.listValues ?? [],
+                disabledListValues: formDraft?.disabledListValues ?? [],
+            });
+        }
+        Navigation.goBack();
+    };
+
+    const updateListValueEnabled = (value: boolean) => {
+        if (reportFieldID) {
+            updateReportFieldListValueEnabled({policy, reportFieldID, valueIndexes: [Number(valueIndex)], enabled: value});
+            return;
+        }
+
+        setReportFieldsListValueEnabled({
+            valueIndexes: [valueIndex],
+            enabled: value,
+            disabledListValues: formDraft?.disabledListValues ?? [],
+        });
+    };
+
+    const navigateToEditValue = () => {
+        Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_EDIT_VALUE.getRoute(policyID, valueIndex));
+    };
+
     return (
-        <FieldsValueSettingsPage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            valueIndex={valueIndex}
-            reportFieldID={reportFieldID}
-            isInvoicePage={false}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            getEditValueRoute={(isInvoiceRoute, id, index) =>
-                isInvoiceRoute ? ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_VALUE.getRoute(id, index) : ROUTES.WORKSPACE_REPORT_FIELDS_EDIT_VALUE.getRoute(id, index)
-            }
-            testID="ReportFieldsValueSettingsPage"
-        />
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsValueSettingsPage"
+            >
+                <HeaderWithBackButton
+                    title={currentValueName ?? oldValueName}
+                    shouldSetModalVisibility={false}
+                />
+                <View style={styles.flexGrow1}>
+                    <View style={[styles.mt2, styles.mh5]}>
+                        <View style={[styles.flexRow, styles.mb5, styles.mr2, styles.alignItemsCenter, styles.justifyContentBetween]}>
+                            <Text
+                                accessible={false}
+                                aria-hidden
+                            >
+                                {translate('workspace.reportFields.enableValue')}
+                            </Text>
+                            <Switch
+                                isOn={!currentValueDisabled}
+                                accessibilityLabel={translate('workspace.reportFields.enableValue')}
+                                onToggle={updateListValueEnabled}
+                                disabled={!canWriteReportFields}
+                                disabledAction={withReadOnlyFallback()}
+                                showLockIcon={!canWriteReportFields}
+                            />
+                        </View>
+                    </View>
+                    <MenuItemWithTopDescription
+                        title={currentValueName ?? oldValueName}
+                        description={translate('common.value')}
+                        shouldShowRightIcon={canWriteReportFields && !reportFieldID}
+                        interactive={canWriteReportFields && !reportFieldID}
+                        onPress={navigateToEditValue}
+                    />
+                    {canWriteReportFields && !hasAccountingConnections && (
+                        <MenuItem
+                            icon={icons.Trashcan}
+                            title={translate('common.delete')}
+                            onPress={confirmAndDeleteListValue}
+                        />
+                    )}
+                </View>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/WorkspaceReportsPage.tsx b/src/pages/workspace/reports/WorkspaceReportsPage.tsx
index 821ff50b3bb9..3d921fe63dda 100644
--- a/src/pages/workspace/reports/WorkspaceReportsPage.tsx
+++ b/src/pages/workspace/reports/WorkspaceReportsPage.tsx
@@ -1,61 +1,168 @@
+import {FlashList} from '@shopify/flash-list';
+import type {ListRenderItemInfo} from '@shopify/flash-list';
 import {Str} from 'expensify-common';
-import React from 'react';
+import React, {useEffect, useMemo} from 'react';
+import {View} from 'react-native';
 import ActivityIndicator from '@components/ActivityIndicator';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ImportedFromAccountingSoftware from '@components/ImportedFromAccountingSoftware';
+import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import {ModalActions} from '@components/Modal/Global/ModalContext';
 import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import Section from '@components/Section';
 import SectionSubtitleHTML from '@components/SectionSubtitleHTML';
+import type {ListItem} from '@components/SelectionList/types';
 import Text from '@components/Text';
-import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useConfirmModal from '@hooks/useConfirmModal';
+import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
+import useOnyx from '@hooks/useOnyx';
 import usePolicy from '@hooks/usePolicy';
 import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle';
+import {isConnectionInProgress, isConnectionUnverified} from '@libs/actions/connections';
 import {clearPolicyTitleFieldError, enablePolicyReportFields, setPolicyPreventMemberCreatedTitle} from '@libs/actions/Policy/Policy';
 import {getLatestErrorField} from '@libs/ErrorUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
-import {isControlPolicy} from '@libs/PolicyUtils';
+import {getConnectedIntegration, getCurrentConnectionName, hasAccountingConnections as hasAccountingConnectionsPolicyUtils, isControlPolicy, shouldShowSyncError} from '@libs/PolicyUtils';
 import {getTitleFieldWithFallback} from '@libs/ReportUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
+import {getReportFieldTypeTranslationKey} from '@libs/WorkspaceReportFieldUtils';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import WorkspaceFieldsSection from '@pages/workspace/fields/WorkspaceFieldsSection';
 import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow';
 import {openPolicyReportFieldsPage} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 
+type ReportFieldForList = ListItem & {
+    fieldID: string;
+    rightLabel: string;
+    isDisabled: boolean;
+};
+
 type WorkspaceReportFieldsPageProps = PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.REPORTS>;
 
+function keyExtractor(item: ReportFieldForList) {
+    return item.keyForList ?? '';
+}
+
 function WorkspaceReportFieldsPage({
     route: {
         params: {policyID},
     },
 }: WorkspaceReportFieldsPageProps) {
+    // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout for the small screen selection mode
+
     const {shouldUseNarrowLayout} = useResponsiveLayout();
     const styles = useThemeStyles();
-    const {translate} = useLocalize();
+    const {translate, localeCompare} = useLocalize();
     const policy = usePolicy(policyID);
+    const {showConfirmModal} = useConfirmModal();
     const {canWrite: canWriteReportFields, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
     useWorkspaceDocumentTitle(policy?.name, 'workspace.common.reports');
+    const [connectionSyncProgress] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policyID}`);
+    const isSyncInProgress = isConnectionInProgress(connectionSyncProgress, policy);
+    const syncingAccountingIntegration = CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES.find((connectionName) => connectionName === connectionSyncProgress?.connectionName);
+    const hasSyncError = shouldShowSyncError(policy, isSyncInProgress, CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES);
+    const connectedIntegration = getConnectedIntegration(policy) ?? syncingAccountingIntegration;
+    const isConnectionVerified = connectedIntegration && !isConnectionUnverified(policy, connectedIntegration);
+    const currentConnectionName = getCurrentConnectionName(policy);
+    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
 
     const illustrations = useMemoizedLazyIllustrations(['ReportReceipt']);
+    const icons = useMemoizedLazyExpensifyIcons(['Plus']);
+
+    const onDisabledOrganizeSwitchPress = () => {
+        if (!hasAccountingConnections) {
+            return;
+        }
 
-    const {isOffline} = useNetwork();
+        showConfirmModal({
+            title: translate('workspace.moreFeatures.connectionsWarningModal.featureEnabledTitle'),
+            prompt: translate('workspace.moreFeatures.connectionsWarningModal.featureEnabledText'),
+            confirmText: translate('workspace.moreFeatures.connectionsWarningModal.manageSettings'),
+            cancelText: translate('common.cancel'),
+        }).then((result) => {
+            if (result.action !== ModalActions.CONFIRM || !policyID) {
+                return;
+            }
+
+            Navigation.navigate(ROUTES.POLICY_ACCOUNTING.getRoute(policyID));
+        });
+    };
+
+    const {isOffline} = useNetwork({onReconnect: () => openPolicyReportFieldsPage(policyID)});
+
+    useEffect(() => {
+        openPolicyReportFieldsPage(policyID);
+    }, [policyID]);
 
     const titleField = getTitleFieldWithFallback(policy);
 
+    const reportFieldsSections: ReportFieldForList[] = policy?.fieldList
+        ? Object.entries(policy.fieldList)
+              .filter(([, value]) => value.fieldID !== 'text_title')
+              .map(([, reportField]) => ({
+                  text: reportField.name,
+                  keyForList: String(reportField.fieldID),
+                  fieldID: reportField.fieldID,
+                  pendingAction: reportField.pendingAction,
+                  isDisabled: reportField.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
+                  rightLabel: Str.recapitalize(translate(getReportFieldTypeTranslationKey(reportField.type ?? CONST.REPORT_FIELD_TYPES.TEXT))),
+              }))
+              .sort((a, b) => localeCompare(a.text, b.text))
+        : [];
+
+    const navigateToReportFieldsSettings = (reportField: ReportFieldForList) => {
+        if (!canWriteReportFields) {
+            return;
+        }
+
+        Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_SETTINGS.getRoute(policyID, reportField.fieldID));
+    };
+
+    const getHeaderText = () =>
+        !hasSyncError && isConnectionVerified && currentConnectionName ? (
+            <Text style={[styles.mr5, styles.mt1]}>
+                <ImportedFromAccountingSoftware
+                    policyID={policyID}
+                    currentConnectionName={currentConnectionName}
+                    connectedIntegration={connectedIntegration}
+                    translatedText={translate('workspace.reportFields.importedFromAccountingSoftware')}
+                />
+            </Text>
+        ) : (
+            <Text style={[styles.textNormal, styles.colorMuted, styles.mr5, styles.mt1]}>{translate('workspace.reportFields.subtitle')}</Text>
+        );
+
     const isLoading = !isOffline && policy === undefined;
     const reasonAttributes: SkeletonSpanReasonAttributes = {context: 'WorkspaceReportFieldsPage', isOffline, isPolicyUndefined: policy === undefined};
 
+    const renderItem = ({item}: ListRenderItemInfo<ReportFieldForList>) => (
+        <OfflineWithFeedback pendingAction={item.pendingAction}>
+            <MenuItem
+                style={shouldUseNarrowLayout ? styles.ph5 : styles.ph8}
+                onPress={() => navigateToReportFieldsSettings(item)}
+                description={item.text}
+                disabled={item.isDisabled}
+                shouldShowRightIcon={!item.isDisabled && canWriteReportFields}
+                interactive={!item.isDisabled && canWriteReportFields}
+                rightLabel={item.rightLabel}
+                descriptionTextStyle={[styles.popoverMenuText, styles.textStrong]}
+            />
+        </OfflineWithFeedback>
+    );
+
     const titleFieldError = policy?.errorFields?.fieldList?.[CONST.POLICY.FIELDS.FIELD_LIST_TITLE];
     const reportTitleErrors = getLatestErrorField({errorFields: titleFieldError ?? {}}, 'defaultValue');
 
@@ -88,6 +195,13 @@ function WorkspaceReportFieldsPage({
         </OfflineWithFeedback>
     );
 
+    const reportFieldsAccessibilityLabel = useMemo(() => {
+        if (!hasSyncError && isConnectionVerified && currentConnectionName) {
+            return `${translate('workspace.common.reportFields')}, ${translate('workspace.reportFields.importedFromAccountingSoftware')} ${currentConnectionName} ${translate('workspace.accounting.settings')}`;
+        }
+        return `${translate('workspace.common.reportFields')}, ${translate('workspace.reportFields.subtitle')}`;
+    }, [hasSyncError, isConnectionVerified, currentConnectionName, translate]);
+
     return (
         <AccessOrNotFoundWrapper
             policyID={policyID}
@@ -167,28 +281,70 @@ function WorkspaceReportFieldsPage({
                                 showLockIcon={!canWriteReportFields}
                             />
                         </Section>
-                        <WorkspaceFieldsSection
-                            policy={policy}
-                            policyID={policyID}
-                            isEnabled={!!policy?.areReportFieldsEnabled}
-                            pendingAction={policy?.pendingFields?.areReportFieldsEnabled}
-                            fieldFilter={(field) => field.fieldID !== CONST.REPORT_FIELD_TITLE_FIELD_ID && (!field.target || field.target === CONST.REPORT_FIELD_TARGETS.EXPENSE)}
-                            titleKey="workspace.common.reportFields"
-                            subtitleKey="workspace.reportFields.subtitle"
-                            importedFromAccountingSoftwareKey="workspace.reportFields.importedFromAccountingSoftware"
-                            disableTitleKey="workspace.reportFields.disableReportFields"
-                            disablePromptKey="workspace.reportFields.disableReportFieldsConfirmation"
-                            addFieldKey="workspace.reportFields.addField"
-                            createRoute={ROUTES.WORKSPACE_CREATE_REPORT_FIELD.getRoute(policyID)}
-                            getSettingsRoute={ROUTES.WORKSPACE_REPORT_FIELDS_SETTINGS.getRoute}
-                            upgradeFeatureAlias={CONST.UPGRADE_FEATURE_INTRO_MAPPING.reportFields.alias}
-                            upgradeBackToRoute={ROUTES.WORKSPACE_REPORTS.getRoute(policyID)}
-                            enableFields={enablePolicyReportFields}
-                            openFieldsPage={openPolicyReportFieldsPage}
-                            policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-                            syncErrorConnectionNames={CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES}
-                            titleAccessibilityRole={CONST.ROLE.HEADER}
-                        />
+                        <Section
+                            isCentralPane
+                            containerStyles={shouldUseNarrowLayout ? styles.p5 : styles.p8}
+                        >
+                            <ToggleSettingOptionRow
+                                pendingAction={policy?.pendingFields?.areReportFieldsEnabled}
+                                title={translate('workspace.common.reportFields')}
+                                switchAccessibilityLabel={reportFieldsAccessibilityLabel}
+                                subtitle={getHeaderText()}
+                                titleStyle={[styles.textHeadline, styles.cardSectionTitle, styles.accountSettingsSectionTitle, styles.mb1]}
+                                titleAccessibilityRole={CONST.ROLE.HEADER}
+                                isActive={!!policy?.areReportFieldsEnabled}
+                                onToggle={(isEnabled) => {
+                                    if (!isEnabled) {
+                                        showConfirmModal({
+                                            danger: true,
+                                            title: translate('workspace.reportFields.disableReportFields'),
+                                            prompt: translate('workspace.reportFields.disableReportFieldsConfirmation'),
+                                            confirmText: translate('common.disable'),
+                                            cancelText: translate('common.cancel'),
+                                        }).then((result) => {
+                                            if (result.action !== ModalActions.CONFIRM || !policyID) {
+                                                return;
+                                            }
+
+                                            enablePolicyReportFields(policyID, false);
+                                        });
+                                        return;
+                                    }
+                                    if (!isControlPolicy(policy)) {
+                                        Navigation.navigate(
+                                            ROUTES.WORKSPACE_UPGRADE.getRoute(policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.reportFields.alias, ROUTES.WORKSPACE_REPORTS.getRoute(policyID)),
+                                        );
+                                        return;
+                                    }
+                                    enablePolicyReportFields(policyID, isEnabled);
+                                }}
+                                disabled={hasAccountingConnections || !canWriteReportFields}
+                                disabledAction={withReadOnlyFallback(onDisabledOrganizeSwitchPress)}
+                                showLockIcon={!canWriteReportFields}
+                                subMenuItems={
+                                    !!policy?.areReportFieldsEnabled && (
+                                        <>
+                                            <View style={[shouldUseNarrowLayout ? styles.mhn5 : styles.mhn8, styles.mt6]}>
+                                                <FlashList
+                                                    data={reportFieldsSections}
+                                                    renderItem={renderItem}
+                                                    keyExtractor={keyExtractor}
+                                                    maintainVisibleContentPosition={{disabled: true}}
+                                                />
+                                            </View>
+                                            {!hasAccountingConnections && canWriteReportFields && (
+                                                <MenuItem
+                                                    onPress={() => Navigation.navigate(ROUTES.WORKSPACE_CREATE_REPORT_FIELD.getRoute(policyID))}
+                                                    title={translate('workspace.reportFields.addField')}
+                                                    icon={icons.Plus}
+                                                    style={[styles.sectionMenuItemTopDescription]}
+                                                />
+                                            )}
+                                        </>
+                                    )
+                                }
+                            />
+                        </Section>
                     </ScrollView>
                 )}
             </ScreenWrapper>
diff --git a/src/pages/workspace/rooms/WorkspaceRoomsPage.tsx b/src/pages/workspace/rooms/WorkspaceRoomsPage.tsx
index a605db3500fc..d1d38618e0aa 100644
--- a/src/pages/workspace/rooms/WorkspaceRoomsPage.tsx
+++ b/src/pages/workspace/rooms/WorkspaceRoomsPage.tsx
@@ -22,7 +22,6 @@ import {openPolicyRoomsPage} from '@libs/actions/Policy/Room';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
 import {isPolicyAdmin} from '@libs/PolicyUtils';
 import {getReportName} from '@libs/ReportNameUtils';
 import {getParticipantsAccountIDsForDisplay} from '@libs/ReportUtils';
@@ -64,22 +63,16 @@ function WorkspaceRoomsPage({route}: WorkspaceRoomsPageProps) {
     const [roomIDToHighlight] = useOnyx(ONYXKEYS.ROOM_ID_HIGHLIGHT_ON_ROOMS_PAGE);
     const highlightedReportID = roomIDToHighlight ?? undefined;
 
-    const rooms: WorkspaceRoomRowData[] = (policyReports ?? []).map((report) => {
-        const ownerDetails = report.ownerAccountID ? personalDetails?.[report.ownerAccountID] : undefined;
-        return {
-            keyForList: report.reportID,
-            reportID: report.reportID,
-            name: getReportName(report, reportAttributes),
-            ownerAccountID: report.ownerAccountID,
-            ownerAvatar: ownerDetails?.avatar,
-            ownerDisplayName: ownerDetails ? getDisplayNameOrDefault(ownerDetails) : '',
-            memberCount: getParticipantsAccountIDsForDisplay(report, true, false, false, undefined, personalDetails).length,
-            action: () => {
-                const targetRoute = isAdmin ? createDynamicRoute(DYNAMIC_ROUTES.REPORT_DETAILS.getRoute(report.reportID)) : ROUTES.REPORT_WITH_ID.getRoute(report.reportID);
-                Navigation.navigate(targetRoute);
-            },
-        };
-    });
+    const rooms: WorkspaceRoomRowData[] = (policyReports ?? []).map((report) => ({
+        keyForList: report.reportID,
+        reportID: report.reportID,
+        name: getReportName(report, reportAttributes),
+        memberCount: getParticipantsAccountIDsForDisplay(report, true, false, false, undefined, personalDetails).length,
+        action: () => {
+            const targetRoute = isAdmin ? createDynamicRoute(DYNAMIC_ROUTES.REPORT_DETAILS.getRoute(report.reportID)) : ROUTES.REPORT_WITH_ID.getRoute(report.reportID);
+            Navigation.navigate(targetRoute);
+        },
+    }));
 
     useFocusEffect(() => {
         openPolicyRoomsPage(policyID);
diff --git a/src/pages/workspace/rules/AIRules/AddAIRulePage.tsx b/src/pages/workspace/rules/AIRules/AddAIRulePage.tsx
index a5735f1ab4c6..68ba35e430ff 100644
--- a/src/pages/workspace/rules/AIRules/AddAIRulePage.tsx
+++ b/src/pages/workspace/rules/AIRules/AddAIRulePage.tsx
@@ -104,6 +104,7 @@ function AddAIRulePage({
                             textInputContainerStyles={[styles.flex1]}
                             inputStyle={[styles.flex1, styles.textAlignVerticalTop]}
                         />
+                        <Text style={[styles.textMicroSupporting, styles.textAlignCenter, styles.mt2]}>{translate('workspace.rules.aiRules.disclaimer')}</Text>
                     </View>
                 </FormProvider>
             </ScreenWrapper>
diff --git a/src/pages/workspace/rules/AIRules/EditAIRulePage.tsx b/src/pages/workspace/rules/AIRules/EditAIRulePage.tsx
index e06bf59e0c9b..de2096580043 100644
--- a/src/pages/workspace/rules/AIRules/EditAIRulePage.tsx
+++ b/src/pages/workspace/rules/AIRules/EditAIRulePage.tsx
@@ -151,6 +151,7 @@ function EditAIRulePage({
                             textInputContainerStyles={[styles.flex1]}
                             inputStyle={[styles.flex1, styles.textAlignVerticalTop]}
                         />
+                        <Text style={[styles.textMicroSupporting, styles.textAlignCenter, styles.mt2]}>{translate('workspace.rules.aiRules.disclaimer')}</Text>
                     </View>
                 </FormProvider>
             </ScreenWrapper>
diff --git a/src/pages/workspace/rules/AIRulesSection.tsx b/src/pages/workspace/rules/AIRulesSection.tsx
index e2f2929ac86f..ebbd5e586c25 100644
--- a/src/pages/workspace/rules/AIRulesSection.tsx
+++ b/src/pages/workspace/rules/AIRulesSection.tsx
@@ -52,7 +52,7 @@ function AIRulesSection({policyID, canWriteRules, showReadOnlyModal}: AIRulesSec
         <View style={[styles.flexRow, styles.alignItemsCenter]}>
             <Text style={[styles.textHeadline, styles.cardSectionTitle, styles.accountSettingsSectionTitle, {color: theme.text}]}>{translate('workspace.rules.aiRules.title')}</Text>
             <Badge
-                text={translate('common.newFeature')}
+                text={translate('common.beta')}
                 isCondensed
                 success
             />
@@ -78,7 +78,7 @@ function AIRulesSection({policyID, canWriteRules, showReadOnlyModal}: AIRulesSec
                                     onClose={() => clearPolicyAIRuleErrors(policyID, rule.ruleID, rule)}
                                 >
                                     <MenuItemWithTopDescription
-                                        title={rule.prompt.replaceAll(/\s+/g, ' ').trim()}
+                                        title={(rule.title ?? rule.prompt).replaceAll(/\s+/g, ' ').trim()}
                                         numberOfLinesTitle={1}
                                         wrapperStyle={[styles.borderedContentCard, styles.ph4, styles.pv4]}
                                         shouldShowRightIcon
diff --git a/src/pages/workspace/rules/PolicyRulesPage.tsx b/src/pages/workspace/rules/PolicyRulesPage.tsx
index 987514bf1b0a..a56f3e7db238 100644
--- a/src/pages/workspace/rules/PolicyRulesPage.tsx
+++ b/src/pages/workspace/rules/PolicyRulesPage.tsx
@@ -78,7 +78,13 @@ function PolicyRulesPage({route}: PolicyRulesPageProps) {
                             title={translate('workspace.rules.agentsPromoBanner.title')}
                             subtitle={translate('workspace.rules.agentsPromoBanner.subtitle')}
                             ctaText={translate('workspace.rules.agentsPromoBanner.cta')}
-                            onCtaPress={() => Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS.getRoute(policyID))}
+                            onCtaPress={() => {
+                                if (!canWriteRules) {
+                                    showReadOnlyModal();
+                                    return;
+                                }
+                                Navigation.navigate(ROUTES.RULES_AI_NEW.getRoute(policyID));
+                            }}
                             ctaSentryLabel={CONST.SENTRY_LABEL.AGENTS_RULES_BANNER.CTA}
                             onDismiss={() => dismissProductTraining(CONST.AGENTS_RULES_BANNER, true)}
                             dismissSentryLabel={CONST.SENTRY_LABEL.AGENTS_RULES_BANNER.DISMISS}
diff --git a/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx b/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx
index 0094a49c59da..e9064ea86fbb 100644
--- a/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx
+++ b/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx
@@ -11,6 +11,7 @@ import SelectionList from '@components/SelectionList';
 import CardListItem from '@components/SelectionList/ListItem/CardListItem';
 import type {AdditionalCardProps} from '@components/SelectionList/ListItem/CardListItem';
 import type {ListItem} from '@components/SelectionList/types';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import {useCompanyCardFeedIcons} from '@hooks/useCompanyCardIcons';
 import useDefaultFundID from '@hooks/useDefaultFundID';
 import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
@@ -78,6 +79,7 @@ function SpendRuleCardPage({route}: SpendRuleCardPageProps) {
     const {policyID, ruleID} = route.params;
     const styles = useThemeStyles();
     const {translate, localeCompare} = useLocalize();
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
     const defaultFundID = useDefaultFundID(policyID);
     const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE);
     const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
@@ -193,7 +195,8 @@ function SpendRuleCardPage({route}: SpendRuleCardPageProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!canWriteCardSpendRules}
         >
             {isCardSettingsLoading ? (
                 <FullScreenLoadingIndicator
diff --git a/src/pages/workspace/rules/SpendRules/SpendRuleCategoryPage.tsx b/src/pages/workspace/rules/SpendRules/SpendRuleCategoryPage.tsx
index feb1b4e84b51..05f1ee57725e 100644
--- a/src/pages/workspace/rules/SpendRules/SpendRuleCategoryPage.tsx
+++ b/src/pages/workspace/rules/SpendRules/SpendRuleCategoryPage.tsx
@@ -1,11 +1,21 @@
 import React from 'react';
 import SpendRuleCategoryBase from '@components/SpendRules/configuration/SpendRuleCategoryBase';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import useOnyx from '@hooks/useOnyx';
 import {updateDraftSpendRule} from '@libs/actions/User';
+import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import type SCREENS from '@src/SCREENS';
 import type {SpendRuleCategory} from '@src/types/form/SpendRuleForm';
 
-function SpendRuleCategoryPage() {
+type SpendRuleCategoryPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.RULES_SPEND_CATEGORY>;
+
+function SpendRuleCategoryPage({route}: SpendRuleCategoryPageProps) {
+    const {policyID} = route.params;
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
     const [spendRuleForm] = useOnyx(ONYXKEYS.FORMS.SPEND_RULE_FORM);
 
     const onCategoriesChange = (categories: SpendRuleCategory[]) => {
@@ -13,10 +23,17 @@ function SpendRuleCategoryPage() {
     };
 
     return (
-        <SpendRuleCategoryBase
-            categories={spendRuleForm?.categories ?? []}
-            onCategoriesChange={onCategoriesChange}
-        />
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!canWriteCardSpendRules}
+        >
+            <SpendRuleCategoryBase
+                categories={spendRuleForm?.categories ?? []}
+                onCategoriesChange={onCategoriesChange}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx b/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx
index 4c3aa2481c7a..a3ac7a5e86ca 100644
--- a/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx
+++ b/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx
@@ -10,6 +10,7 @@ import {ModalActions} from '@components/Modal/Global/ModalContext';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import Text from '@components/Text';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import useConfirmModal from '@hooks/useConfirmModal';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useDefaultFundID from '@hooks/useDefaultFundID';
@@ -63,7 +64,8 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
     const {translate} = useLocalize();
     const {showConfirmModal} = useConfirmModal();
     const policy = usePolicy(policyID);
-    const {canWrite: canWriteRules, showReadOnlyModal} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.RULES);
+    const {showReadOnlyModal} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.RULES);
+    const canWriteSpendRules = useCanWriteCardSpendRules(policyID);
     const domainAccountID = useDefaultFundID(policyID);
     const [spendRuleForm] = useOnyx(ONYXKEYS.FORMS.SPEND_RULE_FORM);
     const [expensifyCardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${domainAccountID}`);
@@ -154,7 +156,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
     const errorMessage = getErrorMessage(hasSelectedCards, hasAnyRuleApplied, translate);
 
     const handleSaveRule = () => {
-        if (!canWriteRules) {
+        if (!canWriteSpendRules) {
             return;
         }
         if (errorMessage) {
@@ -173,7 +175,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
     };
 
     const handleDeleteRule = () => {
-        if (!canWriteRules) {
+        if (!canWriteSpendRules) {
             return;
         }
         if (!existingRule) {
@@ -201,7 +203,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
         return <NotFoundPage />;
     }
 
-    if (!isEditing && !!policy && !canWriteRules) {
+    if (!isEditing && !!policy && !canWriteSpendRules) {
         return <NotFoundPage />;
     }
 
@@ -209,8 +211,8 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.RULES}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!!policy?.id && !canWriteSpendRules}
         >
             <ScreenWrapper
                 testID={testID}
@@ -223,15 +225,15 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                     <MenuItemWithTopDescription
                         description={translate('workspace.rules.spendRules.chooseCards')}
                         onPress={
-                            canWriteRules
+                            canWriteSpendRules
                                 ? () => {
                                       clearError();
                                       navigation.navigate(SCREENS.WORKSPACE.RULES_SPEND_CARD, {policyID, ruleID: currentRuleID});
                                   }
                                 : undefined
                         }
-                        shouldShowRightIcon={canWriteRules}
-                        interactive={canWriteRules}
+                        shouldShowRightIcon={canWriteSpendRules}
+                        interactive={canWriteSpendRules}
                         title={cardsMenuTitle}
                         numberOfLinesTitle={2}
                         titleStyle={styles.flex1}
@@ -242,7 +244,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                         <SpendRuleRestrictionTypeToggle
                             restrictionAction={restrictionAction}
                             onSelect={(action) => {
-                                if (!canWriteRules) {
+                                if (!canWriteSpendRules) {
                                     showReadOnlyModal();
                                     return;
                                 }
@@ -254,15 +256,15 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                     <MenuItemWithTopDescription
                         description={translate('common.merchant')}
                         onPress={
-                            canWriteRules
+                            canWriteSpendRules
                                 ? () => {
                                       clearError();
                                       navigation.navigate(SCREENS.WORKSPACE.RULES_SPEND_MERCHANTS, {policyID, ruleID: currentRuleID});
                                   }
                                 : undefined
                         }
-                        shouldShowRightIcon={canWriteRules}
-                        interactive={canWriteRules}
+                        shouldShowRightIcon={canWriteSpendRules}
+                        interactive={canWriteSpendRules}
                         title={getMerchantMenuTitle(spendRuleForm?.merchantNames)}
                         numberOfLinesTitle={2}
                         titleStyle={styles.flex1}
@@ -271,15 +273,15 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                     <MenuItemWithTopDescription
                         description={translate('workspace.rules.spendRules.spendCategory')}
                         onPress={
-                            canWriteRules
+                            canWriteSpendRules
                                 ? () => {
                                       clearError();
                                       navigation.navigate(SCREENS.WORKSPACE.RULES_SPEND_CATEGORY, {policyID, ruleID: currentRuleID});
                                   }
                                 : undefined
                         }
-                        shouldShowRightIcon={canWriteRules}
-                        interactive={canWriteRules}
+                        shouldShowRightIcon={canWriteSpendRules}
+                        interactive={canWriteSpendRules}
                         title={categoriesMenuTitle}
                         numberOfLinesTitle={2}
                         titleStyle={styles.flex1}
@@ -288,7 +290,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                     <MenuItemWithTopDescription
                         description={translate('workspace.rules.spendRules.maxAmount')}
                         onPress={
-                            canWriteRules
+                            canWriteSpendRules
                                 ? () => {
                                       clearError();
                                       if (!selectedCurrency) {
@@ -299,14 +301,14 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                                   }
                                 : undefined
                         }
-                        shouldShowRightIcon={canWriteRules}
-                        interactive={canWriteRules}
+                        shouldShowRightIcon={canWriteSpendRules}
+                        interactive={canWriteSpendRules}
                         title={maxAmountMenuTitle}
                         titleStyle={styles.flex1}
                         sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.RULES.MERCHANT_RULE_SECTION_ITEM}
                     />
                 </ScrollView>
-                {canWriteRules && (
+                {canWriteSpendRules && (
                     <FormAlertWithSubmitButton
                         buttonText={translate('workspace.rules.spendRules.saveRule')}
                         containerStyles={[styles.m4, styles.mb5]}
diff --git a/src/pages/workspace/taxes/WorkspaceCreateTaxValuePage.tsx b/src/pages/workspace/taxes/WorkspaceCreateTaxValuePage.tsx
index 6acc7d6dc7e1..b073dc8ab8c7 100644
--- a/src/pages/workspace/taxes/WorkspaceCreateTaxValuePage.tsx
+++ b/src/pages/workspace/taxes/WorkspaceCreateTaxValuePage.tsx
@@ -13,7 +13,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {setDraftValues} from '@libs/actions/FormActions';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-// eslint-disable-next-line no-restricted-imports -- The input ref doesn't exist at the navigate() call site, so we can't use Navigation's afterTransition callback
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import variables from '@styles/variables';
diff --git a/src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx b/src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx
index 5b7c496ea4fe..03024b295094 100644
--- a/src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx
+++ b/src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx
@@ -38,7 +38,6 @@ import {
     enablePolicyAutoReimbursementLimit,
     enablePolicyConnections,
     enablePolicyHR,
-    enablePolicyInvoiceFields,
     enablePolicyInvoicing,
     enablePolicyReportFields,
     enablePolicyRules,
@@ -153,8 +152,6 @@ function WorkspaceUpgradePage({route}: WorkspaceUpgradePageProps) {
                         return;
                     }
                 }
-            case CONST.UPGRADE_FEATURE_INTRO_MAPPING.invoiceFields.id:
-                return Navigation.goBack(ROUTES.WORKSPACE_INVOICES.getRoute(policyID));
             case CONST.UPGRADE_FEATURE_INTRO_MAPPING.companyCards.id:
                 Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_COMPANY_CARDS_ADD_NEW.path, ROUTES.WORKSPACE_COMPANY_CARDS_SELECT_FEED.getRoute(policyID)));
                 return;
@@ -235,9 +232,6 @@ function WorkspaceUpgradePage({route}: WorkspaceUpgradePageProps) {
                     }
                 }
                 break;
-            case CONST.UPGRADE_FEATURE_INTRO_MAPPING.invoiceFields.id:
-                enablePolicyInvoiceFields(policyID, true);
-                break;
             case CONST.UPGRADE_FEATURE_INTRO_MAPPING.rules.id:
                 enablePolicyRules(policy, true, false, policyDataRef.current);
                 break;
diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx
index 2093b0b19062..b28cb2dacfca 100644
--- a/src/pages/workspace/withPolicy.tsx
+++ b/src/pages/workspace/withPolicy.tsx
@@ -47,19 +47,9 @@ type PolicyRouteName =
     | typeof SCREENS.WORKSPACE.DISTANCE_RATE_TAX_RATE_EDIT
     | typeof SCREENS.WORKSPACE.DISTANCE_RATE_TAX_RECLAIMABLE_ON_EDIT
     | typeof SCREENS.WORKSPACE.REPORT_FIELDS_CREATE
-    | typeof SCREENS.WORKSPACE.REPORT_FIELDS_SETTINGS
     | typeof SCREENS.WORKSPACE.REPORT_FIELDS_LIST_VALUES
-    | typeof SCREENS.WORKSPACE.REPORT_FIELDS_ADD_VALUE
-    | typeof SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE
     | typeof SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE
     | typeof SCREENS.WORKSPACE.REPORT_FIELDS_VALUE_SETTINGS
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS
     | typeof SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION
     | typeof SCREENS.WORKSPACE.RULES
     | typeof SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW
diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
index 0949c5fdcd2a..7993669516d2 100644
--- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
+++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
@@ -3,9 +3,7 @@ import {Str} from 'expensify-common';
 import React, {useCallback, useEffect, useMemo} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import {InteractionManager, View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
 import type {TupleToUnion} from 'type-fest';
-import AgentPromotionalBanner from '@components/AgentPromotionalBanner';
 import ApprovalWorkflowSection from '@components/ApprovalWorkflowSection';
 import Icon from '@components/Icon';
 import getBankIcon from '@components/Icon/BankIcons';
@@ -20,12 +18,10 @@ import SearchBar from '@components/SearchBar';
 import Section from '@components/Section';
 import Text from '@components/Text';
 import TextLink from '@components/TextLink';
-import useAddAgentToApprovalWorkflow from '@hooks/useAddAgentToApprovalWorkflow';
 import useCardFeeds from '@hooks/useCardFeeds';
 import useConfirmModal from '@hooks/useConfirmModal';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDebouncedAccessibilityAnnouncement from '@hooks/useDebouncedAccessibilityAnnouncement';
-import useDeferredAgentWorkflowReconciliation from '@hooks/useDeferredAgentWorkflowReconciliation';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -38,7 +34,6 @@ import useSearchResults from '@hooks/useSearchResults';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle';
-import {clearPendingAgentFromApprovalWorkflow} from '@libs/actions/Agent';
 import {
     clearPolicyErrorField,
     isCurrencySupportedForDirectReimbursement,
@@ -48,7 +43,6 @@ import {
     setWorkspaceAutoHarvesting,
     setWorkspaceReimbursement,
 } from '@libs/actions/Policy/Policy';
-import {dismissProductTraining} from '@libs/actions/Welcome';
 import {clearApprovalWorkflow, selectApprovalWorkflowForEdit, setApprovalWorkflow} from '@libs/actions/Workflow';
 import {isBankAccountPartiallySetup} from '@libs/BankAccountUtils';
 import {getAllCardsForWorkspace, isSmartLimitEnabled as isSmartLimitEnabledUtil} from '@libs/CardUtils';
@@ -85,7 +79,6 @@ import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
-import type DismissedProductTraining from '@src/types/onyx/DismissedProductTraining';
 import type {ToggleSettingOptionRowProps} from './ToggleSettingsOptionRow';
 import ToggleSettingOptionRow from './ToggleSettingsOptionRow';
 import {getAutoReportingFrequencyDisplayNames} from './WorkspaceAutoReportingFrequencyPage';
@@ -93,8 +86,6 @@ import {getAutoReportingFrequencyDisplayNames} from './WorkspaceAutoReportingFre
 type WorkspaceWorkflowsPageProps = WithPolicyProps & PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.WORKFLOWS>;
 type CurrencyType = TupleToUnion<typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES>;
 
-const agentsWorkflowsBannerDismissedSelector = (value: OnyxEntry<DismissedProductTraining>): boolean => !!value?.[CONST.AGENTS_WORKFLOWS_BANNER];
-
 function WorkflowNoResultsView({message, shouldShow, searchValue}: {message: string; shouldShow: boolean; searchValue: string}) {
     const styles = useThemeStyles();
 
@@ -132,11 +123,8 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
     const [allReportNextSteps] = useOnyx(ONYXKEYS.COLLECTION.NEXT_STEP);
     const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
     const [betas] = useOnyx(ONYXKEYS.BETAS);
-    const [deferredAgentWorkflowSaves] = useOnyx(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES);
     const {isBetaEnabled} = usePermissions();
     const isSubmit2026BetaEnabled = isBetaEnabled(CONST.BETAS.SUBMIT_2026);
-    const isCustomAgentBetaEnabled = isBetaEnabled(CONST.BETAS.CUSTOM_AGENT);
-    const [isAgentsWorkflowsBannerDismissed = false] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {selector: agentsWorkflowsBannerDismissedSelector});
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
     const workspaceCards = getAllCardsForWorkspace(workspaceAccountID, cardList, cardFeeds);
     const {showConfirmModal} = useConfirmModal();
@@ -151,18 +139,17 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
     const delegateAccountID = useDelegateAccountID();
     const {accountID: currentUserAccountID, email: currentUserEmail = '', login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
     const isUserReimburser = policy?.achAccount?.reimburser !== undefined && account?.primaryLogin !== undefined && policy?.achAccount?.reimburser === account?.primaryLogin;
-    const {
-        approvalWorkflows: rawApprovalWorkflows,
-        availableMembers,
-        usedApproverEmails,
-    } = convertPolicyEmployeesToApprovalWorkflows({
-        policy,
-        personalDetails: personalDetails ?? {},
-        localeCompare,
-        currentUserLogin,
-    });
+    const {approvalWorkflows, availableMembers, usedApproverEmails} = useMemo(
+        () =>
+            convertPolicyEmployeesToApprovalWorkflows({
+                policy,
+                personalDetails: personalDetails ?? {},
+                localeCompare,
+                currentUserLogin,
+            }),
+        [policy, personalDetails, localeCompare, currentUserLogin],
+    );
 
-    const approvalWorkflows = useDeferredAgentWorkflowReconciliation(rawApprovalWorkflows, policy, route.params.policyID);
     const canAccessSubmit2026Features = canAccessSubmitWorkspaceFeatures(policy, isSubmit2026BetaEnabled);
     const hasValidExistingAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, policy?.outputCurrency, true).length > 0;
 
@@ -182,21 +169,10 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
 
     const onPressAutoReportingFrequency = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_AUTOREPORTING_FREQUENCY.getRoute(route.params.policyID)), [route.params.policyID]);
 
-    const hasPendingDeferredAgentSave = useMemo(
-        () => Object.values(deferredAgentWorkflowSaves ?? {}).some((entry) => entry?.policyID === route.params.policyID),
-        [deferredAgentWorkflowSaves, route.params.policyID],
-    );
-
     const fetchData = useCallback(() => {
-        // Skip the workflows refetch while a freshly-added offline agent's deferred workflow save is still
-        // pending reconciliation: the READ returns the pre-approval-update employeeList (workspace owner is
-        // still the approver), which would clobber the optimistic agent-as-approver overlay and briefly
-        // flicker the approver row when the connection is restored.
-        if (!hasPendingDeferredAgentSave) {
-            openPolicyWorkflowsPage(route.params.policyID, true);
-        }
+        openPolicyWorkflowsPage(route.params.policyID, true);
         getPaymentMethods();
-    }, [route.params.policyID, hasPendingDeferredAgentSave]);
+    }, [route.params.policyID]);
 
     const confirmCurrencyChangeAndHideModal = useCallback(() => {
         if (!policy) {
@@ -283,7 +259,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(route.params.policyID));
     }, [policy, route.params.policyID, availableMembers, usedApproverEmails, canAccessSubmit2026Features, navigateToSubmitWorkspaceApprovalsUpgrade]);
 
-    const handleAddAgentPress = useAddAgentToApprovalWorkflow(policy, route.params.policyID);
     const isHRAdvancedModeEnabled = isHRAdvancedMode(policy);
     const hrFinalApproverEmail = getHRFinalApprover(policy) ?? undefined;
 
@@ -485,15 +460,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
                                 </View>
                             </View>
                         )}
-                        {isCustomAgentBetaEnabled && !isAgentsWorkflowsBannerDismissed && (
-                            <AgentPromotionalBanner
-                                title={translate('workflowsPage.automateApprovalsWithAgentsTitle')}
-                                subtitle={translate('workflowsPage.automateApprovalsWithAgentsSubtitle')}
-                                onDismiss={() => dismissProductTraining(CONST.AGENTS_WORKFLOWS_BANNER, true)}
-                                dismissSentryLabel={CONST.SENTRY_LABEL.AGENTS_WORKFLOWS_BANNER.DISMISS}
-                                style={styles.mt6}
-                            />
-                        )}
                         {filteredApprovalWorkflows.length > CONST.SEARCH_BAR_THRESHOLD && (
                             <SearchBar
                                 label={translate('workflowsPage.findWorkflow')}
@@ -507,56 +473,47 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
                             shouldShow={searchFilteredWorkflows.length === 0 && workflowSearchInput.length > 0}
                             searchValue={workflowSearchInput}
                         />
-                        {searchFilteredWorkflows.map((workflow) => (
-                            <OfflineWithFeedback
-                                key={workflow.routingFirstApproverEmail}
-                                pendingAction={workflow.pendingAction}
-                            >
-                                <ApprovalWorkflowSection
-                                    approvalWorkflow={workflow}
-                                    onPress={
-                                        shouldBlockApprovalWorkflowEditing || !canWriteApprovals
-                                            ? undefined
-                                            : () => {
-                                                  // Discard stale onyx edits or the Edit page's resume check would surface a prior abandoned session.
-                                                  clearApprovalWorkflow();
-                                                  Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, workflow.routingFirstApproverEmail));
-                                              }
-                                    }
-                                    onShowAllMembersPress={
-                                        shouldBlockApprovalWorkflowEditing
-                                            ? undefined
-                                            : () => {
-                                                  // Use the raw workflow (pre-overlay) — a deferred-agent overlay can blank approvers[0].email, breaking ExpensesFromPage's Edit-route backTo.
-                                                  const rawWorkflow = rawApprovalWorkflows.find((w) => w.approvers.at(0)?.email === workflow.routingFirstApproverEmail);
-                                                  if (!rawWorkflow) {
-                                                      return;
+                        {searchFilteredWorkflows.map((workflow) => {
+                            const firstApproverEmail = workflow.approvers.at(0)?.email ?? '';
+
+                            return (
+                                <OfflineWithFeedback
+                                    key={firstApproverEmail}
+                                    pendingAction={workflow.pendingAction}
+                                >
+                                    <ApprovalWorkflowSection
+                                        approvalWorkflow={workflow}
+                                        onPress={
+                                            shouldBlockApprovalWorkflowEditing || !canWriteApprovals
+                                                ? undefined
+                                                : () => {
+                                                      // Discard stale onyx edits or the Edit page's resume check would surface a prior abandoned session.
+                                                      clearApprovalWorkflow();
+                                                      Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, firstApproverEmail));
                                                   }
-                                                  selectApprovalWorkflowForEdit({workflow: rawWorkflow, defaultWorkflowMembers: availableMembers, usedApproverEmails});
-                                                  Navigation.navigate(
-                                                      ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(
-                                                          route.params.policyID,
-                                                          ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID),
-                                                      ),
-                                                  );
-                                              }
-                                    }
-                                    onAddAgentPress={() => handleAddAgentPress(workflow)}
-                                    onDismissApproverError={(approver) => {
-                                        if (approver.accountID === undefined) {
-                                            return;
                                         }
-                                        clearPendingAgentFromApprovalWorkflow(route.params.policyID, workflow.routingFirstApproverEmail, approver.accountID);
-                                    }}
-                                    canAddAgent={!shouldBlockApprovalWorkflowEditing && isPolicyAdmin}
-                                    currency={policy?.outputCurrency}
-                                    isDisabled={shouldBlockApprovalWorkflowEditing || !canWriteApprovals}
-                                    hrProviderName={isHRConnected ? hrProviderName : undefined}
-                                    isHRAdvancedMode={isHRAdvancedModeEnabled}
-                                    hrFinalApproverEmail={isHRAdvancedModeEnabled ? hrFinalApproverEmail : undefined}
-                                />
-                            </OfflineWithFeedback>
-                        ))}
+                                        onShowAllMembersPress={
+                                            shouldBlockApprovalWorkflowEditing
+                                                ? undefined
+                                                : () => {
+                                                      selectApprovalWorkflowForEdit({workflow, defaultWorkflowMembers: availableMembers, usedApproverEmails});
+                                                      Navigation.navigate(
+                                                          ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(
+                                                              route.params.policyID,
+                                                              ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID),
+                                                          ),
+                                                      );
+                                                  }
+                                        }
+                                        currency={policy?.outputCurrency}
+                                        isDisabled={shouldBlockApprovalWorkflowEditing || !canWriteApprovals}
+                                        hrProviderName={isHRConnected ? hrProviderName : undefined}
+                                        isHRAdvancedMode={isHRAdvancedModeEnabled}
+                                        hrFinalApproverEmail={isHRAdvancedModeEnabled ? hrFinalApproverEmail : undefined}
+                                    />
+                                </OfflineWithFeedback>
+                            );
+                        })}
                         {!shouldBlockApprovalWorkflowEditing && canWriteApprovals && (
                             <MenuItem
                                 title={translate('workflowsPage.addApprovalButton')}
@@ -781,7 +738,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
         approvalSubtitle,
         availableMembers,
         usedApproverEmails,
-        rawApprovalWorkflows,
         navigateToSubmitWorkspaceApprovalsUpgrade,
         promptConfigureApprovalsInHR,
         isDEWEnabled,
@@ -789,8 +745,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
         expensifyIcons.Info,
         expensifyIcons.Plus,
         expensifyIcons.DotIndicator,
-        isCustomAgentBetaEnabled,
-        isAgentsWorkflowsBannerDismissed,
         theme.textSupporting,
         accountManagerReportID,
         filteredApprovalWorkflows.length,
@@ -828,7 +782,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
         withPaymentsReadOnlyFallback,
         withWorkflowsReadOnlyFallback,
         showReadOnlyModal,
-        handleAddAgentPress,
     ]);
 
     const renderOptionItem = (item: ToggleSettingOptionRowProps, index: number) => (
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
index ce7eaa4c09ae..a5e96772d802 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
@@ -17,25 +17,15 @@ import {isAnyHRReadOnlyWorkflowMode} from '@libs/HRUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
-import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils';
-import {canEditWorkspaceSettings, goBackFromInvalidPolicy, isControlPolicy, isPendingDeletePolicy} from '@libs/PolicyUtils';
-import {convertPolicyEmployeesToApprovalWorkflows, resolveOptimisticAgent} from '@libs/WorkflowUtils';
+import {canEditWorkspaceSettings, goBackFromInvalidPolicy, isPendingDeletePolicy} from '@libs/PolicyUtils';
+import {convertPolicyEmployeesToApprovalWorkflows} from '@libs/WorkflowUtils';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import {
-    clearApprovalWorkflow,
-    queueDeferredAgentWorkflowSave,
-    removeApprovalWorkflow,
-    selectApprovalWorkflowForEdit,
-    setApprovalWorkflow,
-    updateApprovalWorkflow,
-    validateApprovalWorkflow,
-} from '@userActions/Workflow';
+import {clearApprovalWorkflow, removeApprovalWorkflow, selectApprovalWorkflowForEdit, updateApprovalWorkflow, validateApprovalWorkflow} from '@userActions/Workflow';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
-import type {Approver} from '@src/types/onyx/ApprovalWorkflow';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
@@ -50,34 +40,12 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
     const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
     const [approvalWorkflow, approvalWorkflowMetadata] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW);
     const isLoadingApprovalWorkflow = isLoadingOnyxValue(approvalWorkflowMetadata);
-    const [agentPrompts] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT);
-    const [optimisticAgentAccountIDMapping] = useOnyx(ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING);
     const currentUserPersonalDetails = useCurrentUserPersonalDetails();
     const [initialApprovalWorkflow, setInitialApprovalWorkflow] = useState<ApprovalWorkflow | undefined>();
     const formRef = useRef<ScrollView>(null);
     const {showConfirmModal} = useConfirmModal();
     const isDeleting = useRef(false);
 
-    // Capture the pending agent's prompt the moment we see it on the optimistic record. The
-    // `SHARED_NVP_AGENT_PROMPT_<optimisticID>` entry is wiped from Onyx as part of CREATE_AGENT's
-    // successData, so once the server responds we'd lose the chance to read it. Stash it in a
-    // ref keyed by the optimistic accountID so the reconciliation effect (and the deferred-save
-    // queue) can match the resolved agent by prompt — a stable identifier that doesn't collide
-    // the way displayName does in workspaces with duplicate names.
-    const capturedPendingAgentPromptsRef = useRef<Map<number, string>>(new Map());
-    const pendingApproverAccountID = approvalWorkflow?.approvers.find((approver) => approver?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD)?.accountID;
-    const pendingAgentPromptKey = pendingApproverAccountID !== undefined ? `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${pendingApproverAccountID}` : undefined;
-    const livePendingAgentPrompt = pendingAgentPromptKey ? agentPrompts?.[pendingAgentPromptKey]?.prompt : undefined;
-    useEffect(() => {
-        if (pendingApproverAccountID === undefined || !livePendingAgentPrompt) {
-            return;
-        }
-        if (capturedPendingAgentPromptsRef.current.has(pendingApproverAccountID)) {
-            return;
-        }
-        capturedPendingAgentPromptsRef.current.set(pendingApproverAccountID, livePendingAgentPrompt);
-    }, [pendingApproverAccountID, livePendingAgentPrompt]);
-
     const updateApprovalWorkflowCallback = () => {
         if (!approvalWorkflow || !initialApprovalWorkflow) {
             return;
@@ -87,21 +55,6 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
             return;
         }
 
-        // If any approver is still being created (seeded from Workflows > Add agent with an
-        // optimistic accountID), defer the actual save. We can't push it to the server yet —
-        // the approver's email is empty until CREATE_AGENT resolves — but the admin shouldn't
-        // be trapped on this screen either. Stash the workflow in `DEFERRED_AGENT_WORKFLOW_SAVES`
-        // and dismiss; WorkspaceWorkflowsPage will render the workflow with the faded agent
-        // and fire the real save once the agent's email lands.
-        const pendingApprover = approvalWorkflow.approvers.find((approver) => approver?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
-        if (pendingApprover?.accountID !== undefined && route.params.firstApproverEmail) {
-            const pendingPromptKey = `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${pendingApprover.accountID}` as const;
-            const pendingPrompt = capturedPendingAgentPromptsRef.current.get(pendingApprover.accountID) ?? agentPrompts?.[pendingPromptKey]?.prompt ?? '';
-            queueDeferredAgentWorkflowSave(route.params.policyID, route.params.firstApproverEmail, approvalWorkflow, initialApprovalWorkflow, pendingApprover.accountID, pendingPrompt);
-            Navigation.dismissModal();
-            return;
-        }
-
         // We need to remove members and approvers that are no longer in the updated workflow
         const membersToRemove = initialApprovalWorkflow.members.filter((initialMember) => !approvalWorkflow.members.some((member) => member.email === initialMember.email));
         const approversToRemove = initialApprovalWorkflow.approvers.filter((initialApprover) => !approvalWorkflow.approvers.some((approver) => approver.email === initialApprover.email));
@@ -175,73 +128,18 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
             return clearApprovalWorkflow();
         }
 
-        // Resume after a sub-page round-trip: keep onyx state to avoid wiping the user's pending edits (seed params force a fresh init).
-        const hasSeedRequest = !!route.params.seedApproverEmail || !!route.params.seedApproverAccountID;
-        const isResumingEdit =
-            !hasSeedRequest && approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT && approvalWorkflow?.originalApprovers?.at(0)?.email === route.params.firstApproverEmail;
+        // Resume after a sub-page round-trip: keep onyx state to avoid wiping the user's pending edits.
+        const isResumingEdit = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT && approvalWorkflow?.originalApprovers?.at(0)?.email === route.params.firstApproverEmail;
         if (isResumingEdit) {
             // eslint-disable-next-line react-hooks/set-state-in-effect -- one-time snapshot guarded by isResumingEdit + early return; runs at most once per mount
             setInitialApprovalWorkflow(currentApprovalWorkflow);
             return;
         }
 
-        // Seed approver[0] when opened from Workflows > Add agent (skip if already in the workflow).
-        // Two entry points are supported:
-        //   1. `seedApproverEmail` — used when the new agent already has a server-assigned login
-        //      (the original happy path: AddAgentPage used to wait for CREATE_AGENT before navigating).
-        //   2. `seedApproverAccountID` — used when AddAgentPage navigates immediately with the
-        //      optimistic accountID from `createAgent`. The optimistic personal detail has a display
-        //      name and an avatar but no `login` yet; we seed the approver anyway, mark it as
-        //      pending so the row renders with opacity, and rely on the reconciliation effect below
-        //      to upgrade it to the real email/accountID once CREATE_AGENT resolves.
-        const seedApproverEmail = route.params.seedApproverEmail;
-        const seedApproverAccountID = route.params.seedApproverAccountID ? Number(route.params.seedApproverAccountID) : undefined;
-        const hasSeedApproverEmail = seedApproverEmail !== undefined && seedApproverEmail !== '';
-        let seedPersonalDetails;
-        if (hasSeedApproverEmail) {
-            seedPersonalDetails = getPersonalDetailByEmail(seedApproverEmail);
-        } else if (seedApproverAccountID !== undefined) {
-            seedPersonalDetails = personalDetails?.[seedApproverAccountID];
-        }
-
-        // `createAgent` queues the optimistic personal detail merge and AddAgentPage navigates
-        // here on the next tick — so on the first render the optimistic detail may still be
-        // undefined. Bail out without locking `initialApprovalWorkflow` so the effect re-runs
-        // when `personalDetails` next updates; that's when we'll actually find the seed and
-        // commit the seeded workflow. Without this guard the un-seeded workflow gets committed
-        // and the seed is lost forever (the bug that just showed up in testing).
-        if (hasSeedRequest && !seedPersonalDetails) {
-            return;
-        }
-
-        let approvers: Approver[] = currentApprovalWorkflow.approvers;
-        if (seedPersonalDetails) {
-            const seededEmail = seedApproverEmail ?? seedPersonalDetails.login ?? '';
-            const seededAccountID = seedPersonalDetails.accountID ?? seedApproverAccountID;
-            const isApproverAlreadyInWorkflow = currentApprovalWorkflow.approvers.some(
-                (approver) => (!!seededEmail && approver.email === seededEmail) || (seededAccountID !== undefined && approver.accountID === seededAccountID),
-            );
-            if (!isApproverAlreadyInWorkflow) {
-                const seededApprover: Approver = {
-                    email: seededEmail,
-                    accountID: seededAccountID,
-                    displayName: seedPersonalDetails.displayName ?? seededEmail,
-                    avatar: seedPersonalDetails.avatar,
-                    approvalLimit: null,
-                    overLimitForwardsTo: '',
-                    // Mark as pending only when the personal detail is optimistic (no login yet) so
-                    // the row renders with reduced opacity while CREATE_AGENT is in flight.
-                    ...(seedPersonalDetails.isOptimisticPersonalDetail ? {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD} : {}),
-                };
-                approvers = isControlPolicy(policy) ? [seededApprover, ...currentApprovalWorkflow.approvers] : [seededApprover, ...currentApprovalWorkflow.approvers.slice(1)];
-            }
-        }
-
         selectApprovalWorkflowForEdit({
             workflow: currentApprovalWorkflow,
             defaultWorkflowMembers,
             usedApproverEmails,
-            approvers,
         });
         // Snapshot for diffing on save; runs alongside selectApprovalWorkflowForEdit above.
         setInitialApprovalWorkflow(currentApprovalWorkflow);
@@ -253,81 +151,11 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
         policy,
         route.params.policyID,
         route.params.firstApproverEmail,
-        route.params.seedApproverEmail,
-        route.params.seedApproverAccountID,
-        personalDetails,
         approvalWorkflow?.action,
         approvalWorkflow?.originalApprovers,
         isLoadingApprovalWorkflow,
     ]);
 
-    // Reconcile a pending (optimistic) seeded approver with the real personal detail once
-    // CREATE_AGENT resolves. The optimistic personal detail is deleted in `createAgent`'s
-    // successData and a new one with a positive accountID + real login is added by the
-    // server response. The server also echoes a `{optimisticID: realID}` mapping in
-    // `OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING` — the primary resolution path — so we can look up
-    // the real accountID without guessing. Prompt matching stays as a cross-tab fallback:
-    // the mapping write only lands on the originating tab's Onyx, so a different tab still
-    // needs the prompt heuristic to reconcile (with the caveat that it's ambiguous when two
-    // agents share the same prompt text — captured in `capturedPendingAgentPromptsRef` while
-    // the optimistic entry was still live).
-    useEffect(() => {
-        if (!approvalWorkflow || !policy?.employeeList || !personalDetails || !agentPrompts) {
-            return;
-        }
-        const pendingApprover = approvalWorkflow.approvers.find((approver) => approver?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
-        if (!pendingApprover?.accountID) {
-            return;
-        }
-
-        const knownApproverEmails = new Set(approvalWorkflow.approvers.map((approver) => approver?.email).filter((email): email is string => !!email));
-        const resolved = resolveOptimisticAgent({
-            optimisticAccountID: pendingApprover.accountID,
-            pendingAgentPrompt: capturedPendingAgentPromptsRef.current.get(pendingApprover.accountID),
-            personalDetails,
-            employeeList: policy.employeeList,
-            agentPrompts,
-            optimisticAccountIDMapping: optimisticAgentAccountIDMapping,
-            knownApproverEmails,
-        });
-        if (!resolved) {
-            return;
-        }
-        const {personalDetail: resolvedPersonalDetail, email: resolvedEmail} = resolved;
-
-        const upgradedApprovers = approvalWorkflow.approvers.map((approver) =>
-            approver === pendingApprover
-                ? {
-                      ...approver,
-                      email: resolvedEmail,
-                      accountID: resolvedPersonalDetail.accountID,
-                      avatar: resolvedPersonalDetail.avatar ?? approver.avatar,
-                      displayName: resolvedPersonalDetail.displayName ?? approver.displayName,
-                      pendingAction: undefined,
-                  }
-                : approver,
-        );
-
-        // Mirror the deferred-save reconciliation in WorkspaceWorkflowsPage: when the new agent
-        // becomes the default approver, inject it into `members` so the subsequent save updates
-        // their `submitsTo` to point at themselves. Without this, `convertApprovalWorkflowToPolicyEmployees`
-        // never rewrites the agent's `submitsTo` (set to the previous default approver by
-        // `shareWithEmployees` in CreateAgent.cpp), leaving an orphan "Expenses from agent → previous
-        // approver" workflow card on the workflows page.
-        const upgradedMembers =
-            approvalWorkflow.isDefault && !approvalWorkflow.members.some((member) => member.email === resolvedEmail)
-                ? [
-                      ...approvalWorkflow.members,
-                      {
-                          email: resolvedEmail,
-                          displayName: resolvedPersonalDetail.displayName ?? resolvedEmail,
-                          avatar: resolvedPersonalDetail.avatar,
-                      },
-                  ]
-                : approvalWorkflow.members;
-        setApprovalWorkflow({...approvalWorkflow, approvers: upgradedApprovers, members: upgradedMembers});
-    }, [approvalWorkflow, policy?.employeeList, personalDetails, agentPrompts, optimisticAgentAccountIDMapping]);
-
     const submitButtonContainerStyles = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mb5, styles.mh5]});
 
     return (
diff --git a/src/selectors/AgentZeroChat.ts b/src/selectors/AgentZeroChat.ts
index b38bd74b731a..57dd959b2d24 100644
--- a/src/selectors/AgentZeroChat.ts
+++ b/src/selectors/AgentZeroChat.ts
@@ -1,31 +1,31 @@
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {AgentPrompt, ConciergePendingFollowupList} from '@src/types/onyx';
+import type {OnyxEntry} from 'react-native-onyx';
+import type {ConciergePendingFollowupList, PersonalDetailsList} from '@src/types/onyx';
 import type Report from '@src/types/onyx/Report';
 
 const getReportParticipantAccountIDs = (report: OnyxEntry<Report>): number[] => (report?.participants ? Object.keys(report.participants).map(Number) : []);
 
 /**
- * Reduces the SHARED_NVP_AGENT_PROMPT collection to a `Record<accountID, true>` so callers
- * can do O(1) lookups without re-rendering on every prompt-content edit.
+ * Returns the first participant accountID flagged as a custom agent (`isCustomAgent` on its
+ * personalDetails entry, stamped server-side in `Account::formatNewDotPersonalDetails`), or
+ * `undefined` when no participant is an agent.
+ *
+ * Parameterized so the closure captures only the report's small `participantAccountIDs` array —
+ * the selector iterates those (small N) against `personalDetailsList`, not the full list. Output
+ * is a primitive `number | undefined`, so `deepEqual` short-circuits cheaply and re-renders fire
+ * only when an agent participant's flag flips.
  */
-const getAgentAccountIDFlags = (agentPrompts: OnyxCollection<AgentPrompt>): Record<number, true> => {
-    if (!agentPrompts) {
-        return {};
-    }
-    const flags: Record<number, true> = {};
-    for (const key of Object.keys(agentPrompts)) {
-        const accountID = Number(key.slice(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT.length));
-        if (!Number.isNaN(accountID)) {
-            flags[accountID] = true;
+const getCustomAgentParticipantAccountID =
+    (participantAccountIDs: number[] | undefined) =>
+    (personalDetails: OnyxEntry<PersonalDetailsList>): number | undefined => {
+        if (!participantAccountIDs?.length || !personalDetails) {
+            return undefined;
         }
-    }
-    return flags;
-};
+        return participantAccountIDs.find((accountID) => !!personalDetails[accountID]?.isCustomAgent);
+    };
 
 const hasPendingFollowupListSkeletonSelector =
     (reportActionID: string) =>
     (pending: OnyxEntry<ConciergePendingFollowupList>): boolean =>
         !pending?.hidden && pending?.reportActionID === reportActionID;
 
-export {getReportParticipantAccountIDs, getAgentAccountIDFlags, hasPendingFollowupListSkeletonSelector};
+export {getReportParticipantAccountIDs, getCustomAgentParticipantAccountID, hasPendingFollowupListSkeletonSelector};
diff --git a/src/selectors/Onboarding.ts b/src/selectors/Onboarding.ts
index 651578b5778d..26077e9e5cc6 100644
--- a/src/selectors/Onboarding.ts
+++ b/src/selectors/Onboarding.ts
@@ -1,4 +1,5 @@
 import type {OnyxValue} from 'react-native-onyx';
+import isTrackOnboardingChoice from '@libs/OnboardingUtils';
 import type ONYXKEYS from '@src/ONYXKEYS';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
 
@@ -79,4 +80,11 @@ function guidedSetupAndTourStatusSelector(onboarding: OnyxValue<typeof ONYXKEYS.
     };
 }
 
-export {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector, hasSeenTourSelector, wasInvitedToNewDotSelector, guidedSetupAndTourStatusSelector};
+/**
+ * Selector to check if the user selected a track-intent onboarding choice
+ */
+function isTrackIntentUserSelector(introSelected: OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>): boolean {
+    return isTrackOnboardingChoice(introSelected?.choice);
+}
+
+export {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector, hasSeenTourSelector, wasInvitedToNewDotSelector, guidedSetupAndTourStatusSelector, isTrackIntentUserSelector};
diff --git a/src/selectors/Report.ts b/src/selectors/Report.ts
index 4a28c5bb4149..c573b3608107 100644
--- a/src/selectors/Report.ts
+++ b/src/selectors/Report.ts
@@ -1,7 +1,7 @@
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import type {TupleToUnion, ValueOf} from 'type-fest';
 import {getOriginalMessage, isClosedAction} from '@libs/ReportActionsUtils';
-import {canShowReportRecipientLocalTime, getPolicyIDsWithEmptyReportsForAccount, isChatRoom, isOpenExpenseReport, isPolicyExpenseChat, isThread} from '@libs/ReportUtils';
+import {canShowReportRecipientLocalTime, getPolicyIDsWithEmptyReportsForAccount, isChatRoom, isClosedReport, isOpenExpenseReport, isPolicyExpenseChat, isThread} from '@libs/ReportUtils';
 import type {ArchivedReportsIDSet} from '@libs/SearchUIUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -58,6 +58,9 @@ const policyChatRoomsSelector =
             if (!isChatRoom(report) && !isPolicyExpenseChat(report)) {
                 continue;
             }
+            if (isClosedReport(report)) {
+                continue;
+            }
             if (archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`)) {
                 continue;
             }
diff --git a/src/selectors/ReportNameValuePairs.ts b/src/selectors/ReportNameValuePairs.ts
index 939aba91fd62..008a814e09c3 100644
--- a/src/selectors/ReportNameValuePairs.ts
+++ b/src/selectors/ReportNameValuePairs.ts
@@ -2,6 +2,12 @@ import type {OnyxEntry} from 'react-native-onyx';
 import CONST from '@src/CONST';
 import type {ReportNameValuePairs} from '@src/types/onyx';
 
+type AgentZeroProcessingIndicator = NonNullable<ReportNameValuePairs['agentZeroProcessingRequestIndicator']>;
+
+function isAgentZeroProcessingIndicatorMap(indicator: AgentZeroProcessingIndicator): indicator is Record<string, string | null> {
+    return typeof indicator === 'object' && indicator !== null && !Array.isArray(indicator);
+}
+
 /**
  * Reads the AgentZero processing-indicator label for a single agent, trimmed.
  *
@@ -16,7 +22,11 @@ function getAgentZeroProcessingLabel(reportNameValuePairs: OnyxEntry<ReportNameV
     if (typeof indicator === 'string') {
         return agentAccountID === CONST.ACCOUNT_ID.CONCIERGE ? indicator.trim() : '';
     }
-    return indicator[String(agentAccountID)]?.trim() ?? '';
+    if (!isAgentZeroProcessingIndicatorMap(indicator)) {
+        return '';
+    }
+    const label = indicator[String(agentAccountID)];
+    return typeof label === 'string' ? label.trim() : '';
 }
 
 /**
@@ -31,9 +41,12 @@ function agentZeroProcessingAgentIDsSelector(reportNameValuePairs: OnyxEntry<Rep
     if (typeof indicator === 'string') {
         return indicator.trim() ? [CONST.ACCOUNT_ID.CONCIERGE] : [];
     }
-    return Object.keys(indicator)
-        .filter((key) => !!indicator[key]?.trim())
-        .map(Number)
+    if (!isAgentZeroProcessingIndicatorMap(indicator)) {
+        return [];
+    }
+    return Object.entries(indicator)
+        .filter(([, label]) => typeof label === 'string' && !!label.trim())
+        .map(([key]) => Number(key))
         .filter((accountID) => !Number.isNaN(accountID))
         .sort((a, b) => a - b);
 }
diff --git a/src/selectors/Todos.ts b/src/selectors/Todos.ts
index a1108233c703..b0a628f1ed5a 100644
--- a/src/selectors/Todos.ts
+++ b/src/selectors/Todos.ts
@@ -1,7 +1,7 @@
 import {shallowEqual} from 'fast-equals';
 import type {OnyxEntry} from 'react-native-onyx';
 import CONST from '@src/CONST';
-import type {TodosDerivedValue} from '@src/types/onyx';
+import type {FlaggedExpensesDerivedValue, TodosDerivedValue} from '@src/types/onyx';
 
 const EMPTY_TODOS_SINGLE_REPORT_IDS = Object.freeze({
     [CONST.SEARCH.SEARCH_KEYS.SUBMIT]: undefined,
@@ -66,5 +66,62 @@ const todosSingleReportIDsSelector = (todos: OnyxEntry<TodosDerivedValue>) => {
     return newValue;
 };
 
+type FlaggedExpensesReview = {
+    /** Total number of flagged expenses */
+    count: number;
+    /** Transaction ID of the first flagged expense, used to seed the carousel handoff */
+    firstTransactionID: string | undefined;
+    /** Parent report ID of the first flagged expense */
+    firstReportID: string | undefined;
+    /** Ordered list of every flagged transaction ID, used to drive the prev/next review carousel */
+    transactionIDs: string[];
+};
+
+const EMPTY_FLAGGED_EXPENSES_REVIEW: FlaggedExpensesReview = Object.freeze({
+    count: 0,
+    firstTransactionID: undefined,
+    firstReportID: undefined,
+    transactionIDs: [],
+}) as FlaggedExpensesReview;
+
+// Manual memoization mirrors `todosSingleReportIDsSelector`: ForYouSection's useMemo dependency
+// list consumes the returned object as a whole, so we need referential stability across
+// equivalent derived snapshots to avoid cascading re-renders on every Onyx churn.
+let previousFlaggedExpensesReview: FlaggedExpensesReview = EMPTY_FLAGGED_EXPENSES_REVIEW;
+
+const flaggedExpensesReviewSelector = (flaggedExpensesValue: OnyxEntry<FlaggedExpensesDerivedValue>): FlaggedExpensesReview => {
+    const flaggedExpenses = flaggedExpensesValue?.flaggedExpenses;
+    if (!flaggedExpenses || flaggedExpenses.length === 0) {
+        previousFlaggedExpensesReview = EMPTY_FLAGGED_EXPENSES_REVIEW;
+        return EMPTY_FLAGGED_EXPENSES_REVIEW;
+    }
+
+    const first = flaggedExpenses.at(0);
+    const transactionIDs = flaggedExpenses.map((flaggedExpense) => flaggedExpense.transactionID);
+    const newValue: FlaggedExpensesReview = {
+        count: flaggedExpenses.length,
+        firstTransactionID: first?.transactionID,
+        firstReportID: first?.reportID,
+        transactionIDs,
+    };
+
+    // shallowEqual would always report a difference because `transactionIDs` is a fresh array each call,
+    // so we compare the scalar fields shallowly and the IDs element-by-element to preserve referential stability.
+    const previousTransactionIDs = previousFlaggedExpensesReview.transactionIDs;
+    const areTransactionIDsEqual =
+        previousTransactionIDs.length === transactionIDs.length && previousTransactionIDs.every((transactionID, index) => transactionID === transactionIDs.at(index));
+    if (
+        previousFlaggedExpensesReview.count === newValue.count &&
+        previousFlaggedExpensesReview.firstTransactionID === newValue.firstTransactionID &&
+        previousFlaggedExpensesReview.firstReportID === newValue.firstReportID &&
+        areTransactionIDsEqual
+    ) {
+        return previousFlaggedExpensesReview;
+    }
+
+    previousFlaggedExpensesReview = newValue;
+    return newValue;
+};
+
 export default todosReportCountsSelector;
-export {todosSingleReportIDsSelector, EMPTY_TODOS_SINGLE_REPORT_IDS};
+export {EMPTY_FLAGGED_EXPENSES_REVIEW, EMPTY_TODOS_SINGLE_REPORT_IDS, flaggedExpensesReviewSelector, todosSingleReportIDsSelector};
diff --git a/src/stories/InteractiveStepSubHeader.stories.tsx b/src/stories/InteractiveStepSubHeader.stories.tsx
index e3a4e9b77da4..5a9f339ee9ff 100644
--- a/src/stories/InteractiveStepSubHeader.stories.tsx
+++ b/src/stories/InteractiveStepSubHeader.stories.tsx
@@ -43,12 +43,14 @@ const Default: StoryType = Template.bind({});
 Default.args = {
     stepNames: ['Initial', 'Step 1', 'Step 2', 'Step 3'],
     startStepIndex: 1,
+    currentStepAccessibilityDescription: 'Step 1',
     onStepSelected: () => {},
 };
 
 BaseInteractiveStepSubHeader.args = {
     stepNames: ['Initial', 'Step 1', 'Step 2', 'Step 3', 'Confirmation'],
     startStepIndex: 0,
+    currentStepAccessibilityDescription: 'Initial',
     onStepSelected: () => {},
 };
 
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 2ca46949f522..4b609d82ddcd 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -3611,6 +3611,24 @@ const staticStyles = (theme: ThemeColors) =>
             paddingBottom: 8,
         },
 
+        searchListHeaderTableStickyOverlap: {
+            position: 'relative',
+            zIndex: 10,
+        },
+
+        searchListHeaderBorderCover: {
+            position: 'absolute',
+            bottom: -2,
+            left: 0,
+            right: 0,
+            height: 1,
+            backgroundColor: theme.highlightBG,
+        },
+
+        groupSubHeaderBorderOverlap: {
+            marginTop: -1,
+        },
+
         groupSearchListTableContainerStyle: {
             minHeight: variables.h28,
             paddingBottom: 0,
@@ -4470,6 +4488,13 @@ const staticStyles = (theme: ThemeColors) =>
             paddingHorizontal: 20,
         },
 
+        inboxTabBadge: {
+            minWidth: 18,
+            height: 16,
+            marginLeft: 8,
+            justifyContent: 'center',
+        },
+
         scrollableTabSelector: {
             flexGrow: 0,
         },
@@ -6441,14 +6466,13 @@ const dynamicStyles = (theme: ThemeColors) =>
                 top: fileTopPosition,
             }) satisfies ViewStyle,
 
-        tabText: (isSelected: boolean, hasIcon = false) =>
-            ({
-                marginLeft: hasIcon ? 8 : 0,
-                ...FontUtils.fontFamily.platform.EXP_NEUE_BOLD,
-                color: isSelected ? theme.text : theme.textSupporting,
-                lineHeight: variables.lineHeightLarge,
-                fontSize: variables.fontSizeLabel,
-            }) satisfies TextStyle,
+        tabText: (isSelected: boolean, hasIcon = false): TextStyle => ({
+            marginLeft: hasIcon ? 8 : 0,
+            ...FontUtils.fontFamily.platform.EXP_NEUE_BOLD,
+            color: isSelected ? theme.text : theme.textSupporting,
+            lineHeight: variables.lineHeightLarge,
+            fontSize: variables.fontSizeLabel,
+        }),
 
         tabBackground: (hovered: boolean, isFocused: boolean, isDisabled: boolean, background: string | Animated.AnimatedInterpolation<string>) => {
             if (isDisabled) {
diff --git a/src/styles/variables.ts b/src/styles/variables.ts
index 0e9eaee8ec44..60a17fe596aa 100644
--- a/src/styles/variables.ts
+++ b/src/styles/variables.ts
@@ -128,13 +128,14 @@ export default {
     optionRowHeightCompact: 52,
     tableHeaderContentHeight: 20,
     tableRowHeight: 56,
-    tableRowHeightCompact: 60,
+    tableRowHeightCompact: 72,
     tableRowPaddingVertical: 8,
     tableRowPaddingHorizontal: 12,
     tableGroupRowPaddingVertical: 4,
     tableGroupRowHeight: 36,
     tableSkeletonHeight: 32,
     tableCheckboxColumnWidth: 20,
+    tableStatusColumnWidth: 56,
     tableSwitchColumnWidth: 58,
     tableCaretColumnWidth: 20,
     domainTableActionColumnWidth: 64,
diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts
index 3fcc72cdb4ad..b52ba9fac852 100644
--- a/src/types/onyx/Account.ts
+++ b/src/types/onyx/Account.ts
@@ -35,6 +35,9 @@ type DelegateErrors = {
     /** Errors while removing a delegate keyed by email */
     removeDelegate?: Record<string, OnyxCommon.Errors>;
 
+    /** Errors while removing a delegator keyed by email */
+    removeDelegator?: Record<string, OnyxCommon.Errors>;
+
     /** Errors while connecting as a delegate keyed by email */
     connect?: Record<string, OnyxCommon.Errors>;
 
diff --git a/src/types/onyx/DeferredAgentWorkflowSave.ts b/src/types/onyx/DeferredAgentWorkflowSave.ts
deleted file mode 100644
index de31043ce8dd..000000000000
--- a/src/types/onyx/DeferredAgentWorkflowSave.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import type ApprovalWorkflow from './ApprovalWorkflow';
-import type {ApprovalWorkflowOnyx} from './ApprovalWorkflow';
-
-/**
- * A workflow save the admin committed while a freshly-created agent was still pending. We
- * stash the edited workflow here when the user clicks "Save" on the Edit Approvers page
- * before `CREATE_AGENT` resolves; the WorkspaceWorkflowsPage watcher reconciles each entry
- * once the agent gets its real email/accountID and fires the actual API write.
- */
-type DeferredAgentWorkflowSave = {
-    /** Workspace this save belongs to */
-    policyID: string;
-
-    /** Email of the workflow's primary approver (the route's `firstApproverEmail`) */
-    firstApproverEmail: string;
-
-    /**
-     * Snapshot of the workflow as it appeared in the editor at the time of save (using the
-     * Onyx editor shape — approvers may include `undefined` placeholders for empty rows).
-     */
-    approvalWorkflow: ApprovalWorkflowOnyx;
-
-    /**
-     * Snapshot of the workflow BEFORE the edit. Matches the shape of the value stored in
-     * `useState<ApprovalWorkflow>` on the Edit Approvers page (approvers required).
-     */
-    initialApprovalWorkflow: ApprovalWorkflow;
-
-    /**
-     * Optimistic accountID of the pending agent we're waiting on. When the personal detail
-     * at this accountID gains a `login` (or a corresponding employeeList entry shows up on
-     * the policy), the watcher swaps that login into the workflow and fires the real save.
-     */
-    pendingAgentAccountID: number;
-
-    /**
-     * Prompt of the pending agent, captured at save time from the optimistic
-     * `SHARED_NVP_AGENT_PROMPT` entry. The reconciliation watcher uses this as a stable
-     * identifier to find the resolved agent (a new collection entry with the same prompt at
-     * a different, server-assigned accountID) instead of falling back to a displayName match,
-     * which can collide in workspaces with duplicate names.
-     */
-    pendingAgentPrompt: string;
-};
-
-export default DeferredAgentWorkflowSave;
diff --git a/src/types/onyx/DerivedValues.ts b/src/types/onyx/DerivedValues.ts
index bbcecb4f4d6f..46128996dce1 100644
--- a/src/types/onyx/DerivedValues.ts
+++ b/src/types/onyx/DerivedValues.ts
@@ -266,6 +266,23 @@ type TodosDerivedValue = {
     transactionsByReportID: Record<string, Transaction[]>;
 };
 
+/**
+ * The derived value for flagged expenses.
+ *
+ * Aggregates transactions on the current user's `OPEN`/`OPEN` expense reports that have
+ * at least one transaction-level violation (excluding `showInReview === false` entries and
+ * `REPORT_VIOLATIONS.FIELD_REQUIRED` entries that may slip into the collection).
+ */
+type FlaggedExpensesDerivedValue = {
+    /** Ordered list of flagged transactions with their parent report IDs */
+    flaggedExpenses: Array<{
+        /** ID of the flagged transaction */
+        transactionID: string;
+        /** ID of the parent expense report */
+        reportID: string;
+    }>;
+};
+
 /**
  * The derived value for sorted report actions, last report actions, and cached transaction thread report IDs.
  */
@@ -297,6 +314,7 @@ export type {
     CardFeedErrorsDerivedValue,
     TodosDerivedValue,
     TodoMetadata,
+    FlaggedExpensesDerivedValue,
     CardFeedErrorsObject,
     CardFeedErrorState,
     CardFeedErrors,
diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts
index 1a186f0534c1..640d97ccc883 100644
--- a/src/types/onyx/DismissedProductTraining.ts
+++ b/src/types/onyx/DismissedProductTraining.ts
@@ -59,11 +59,6 @@ type DismissedProductTraining = {
      */
     [CONST.CHANGE_POLICY_TRAINING_MODAL]: DismissedProductTrainingElement;
 
-    /**
-     * When user dismisses the agents workflows promo banner, we store the timestamp here.
-     */
-    [CONST.AGENTS_WORKFLOWS_BANNER]: DismissedProductTrainingElement;
-
     /**
      * When user dismisses the agents rules promo banner, we store the timestamp here.
      */
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index 1585f70afe29..bc7ed2640881 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -7,7 +7,7 @@ import type {Attendee} from './IOU';
 import type {OldDotOriginalMessageMap} from './OldDotAction';
 import type {AllConnectionName} from './Policy';
 import type ReportActionName from './ReportActionName';
-import type {Reservation} from './Transaction';
+import type {Reservation, TransactionCommentVendor} from './Transaction';
 import type TransactionPending3DSReview from './TransactionPending3DSReview';
 
 /** Types of join workspace resolutions */
@@ -606,12 +606,18 @@ type OriginalMessagePolicyChangeLog = {
     /** Previous end date of the custom unit rate (yyyy-MM-dd) */
     oldEndDate?: string;
 
-    /** Tax percentage of the new tax rate linked to distance rate */
+    /** Tax percentage of the new tax rate linked to distance rate or category */
     newTaxPercentage?: string;
 
-    /** Tax percentage of the old tax rate linked to distance rate */
+    /** Tax percentage of the old tax rate linked to distance rate or category */
     oldTaxPercentage?: string;
 
+    /** Name of the new tax rate (without percentage) for category default tax rate */
+    newTaxName?: string;
+
+    /** Name of the old tax rate (without percentage) for category default tax rate */
+    oldTaxName?: string;
+
     /** Added/Updated tag name */
     tagName?: string;
 
@@ -952,6 +958,12 @@ type OriginalMessageModifiedExpense = {
     /** Old expense reimbursable */
     oldReimbursable?: string;
 
+    /** Edited accounting-system vendor on the transaction's comment NVP. `null` means the vendor was cleared. */
+    vendor?: TransactionCommentVendor | null;
+
+    /** Previous accounting-system vendor on the transaction's comment NVP. `null` means there was no prior vendor. */
+    oldVendor?: TransactionCommentVendor | null;
+
     /** Collection of accountIDs of users mentioned in expense report */
     whisperedTo?: number[];
 
@@ -986,6 +998,15 @@ type OriginalMessageModifiedExpense = {
     reasoning?: string;
 };
 
+/** Model of `concierge auto match vendor` report action — emitted on the transaction thread when the PHP fuzzy matcher auto-matches a non-reimbursable expense to a QBO vendor. */
+type OriginalMessageConciergeAutoMatchVendor = {
+    /** Display name of the matched vendor */
+    vendorName?: string;
+
+    /** LLM-consumable explanation of why this vendor was matched — surfaced behind the "Explain" link */
+    reasoning?: string;
+};
+
 /** Policy rules modified fields */
 type PolicyRulesModifiedFields = {
     /** The value that the merchant was changed to */
@@ -1624,6 +1645,7 @@ type OriginalMessageMap = {
     [CONST.REPORT.ACTIONS.TYPE.MARKED_REIMBURSED]: OriginalMessageMarkedReimbursed;
     [CONST.REPORT.ACTIONS.TYPE.MERGED_WITH_CASH_TRANSACTION]: never;
     [CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE]: OriginalMessageModifiedExpense;
+    [CONST.REPORT.ACTIONS.TYPE.CONCIERGE_AUTO_MATCH_VENDOR]: OriginalMessageConciergeAutoMatchVendor;
     [CONST.REPORT.ACTIONS.TYPE.MOVED]: OriginalMessageMoved;
     [CONST.REPORT.ACTIONS.TYPE.MOVED_TRANSACTION]: OriginalMessageMovedTransaction;
     [CONST.REPORT.ACTIONS.TYPE.UNREPORTED_TRANSACTION]: OriginalMessageUnreportedTransaction;
diff --git a/src/types/onyx/PersonalDetails.ts b/src/types/onyx/PersonalDetails.ts
index 6d41b6a0d2cc..6f1f85e4ce3b 100644
--- a/src/types/onyx/PersonalDetails.ts
+++ b/src/types/onyx/PersonalDetails.ts
@@ -74,6 +74,15 @@ type PersonalDetails = OnyxCommon.OnyxValueWithOfflineFeedback<{
     /** Flag for checking if data is from optimistic data */
     isOptimisticPersonalDetail?: boolean;
 
+    /**
+     * True when this account is a registered custom agent (server-side `private_agentOwnerID`
+     * NVP set). Stamped by Auth in `Account::formatNewDotPersonalDetails`, so it travels with
+     * every personalDetails payload returned to the client (OpenReport, OpenApp, ReconnectApp,
+     * GetPersonalDetailsForEmails, etc.). Lets chat surfaces detect custom-agent participants
+     * without subscribing to the wider `SHARED_NVP_AGENT_PROMPT` collection.
+     */
+    isCustomAgent?: boolean;
+
     /** Field-specific server side errors keyed by microtime */
     errorFields?: OnyxCommon.ErrorFields<'avatar'>;
 
diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts
index bed2edb0e752..479ee1ba51fd 100644
--- a/src/types/onyx/Policy.ts
+++ b/src/types/onyx/Policy.ts
@@ -2052,6 +2052,9 @@ type AIRule = {
     /** The AI prompt (i.e. the rule defined with natural language) */
     prompt: string;
 
+    /** Short one-line summary generated server-side from the prompt */
+    title?: string;
+
     /** When this rule was created */
     created: string;
 
@@ -2328,9 +2331,6 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback<
         /** Whether the Report Fields feature is enabled */
         areReportFieldsEnabled?: boolean;
 
-        /** Whether the Invoice Fields feature is enabled */
-        areInvoiceFieldsEnabled?: boolean;
-
         /** Whether the Connections feature is enabled */
         areConnectionsEnabled?: boolean;
 
diff --git a/src/types/onyx/ReportNameValuePairs.ts b/src/types/onyx/ReportNameValuePairs.ts
index f96c140e37bb..8a193c2fa67a 100644
--- a/src/types/onyx/ReportNameValuePairs.ts
+++ b/src/types/onyx/ReportNameValuePairs.ts
@@ -85,10 +85,11 @@ type ReportNameValuePairs = OnyxCommon.OnyxValueWithOfflineFeedback<{
     /**
      * Agent Zero processing-indicator labels, keyed by the persona accountID (Concierge or a
      * custom agent) so a room with several agents shows one bubble per actively-thinking agent.
-     * Each value is the status string for that agent. A legacy scalar string may still arrive
-     * during a backend/client deploy overlap and is attributed to Concierge.
+     * Each value is the status string for that agent. A null value clears that agent's slot during
+     * local Onyx merge transitions. A legacy scalar string may still arrive during a backend/client
+     * deploy overlap and is attributed to Concierge.
      */
-    agentZeroProcessingRequestIndicator?: Record<string, string> | string;
+    agentZeroProcessingRequestIndicator?: Record<string, string | null> | string;
 
     /** Parent report ID */
     parentReportID?: string;
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index c43e09063466..066411806e22 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -129,13 +129,7 @@ type Comment = {
      * (`isManuallySet=true`). The flag prevents auto-match from overwriting a
      * deliberate selection.
      */
-    vendor?: {
-        /** Vendor ID in the connected accounting integration (e.g. QBO vendor ID) */
-        externalID: string;
-
-        /** `true` when set by the user or a merchant rule; `false` when set by the PHP fuzzy auto-matcher */
-        isManuallySet: boolean;
-    };
+    vendor?: TransactionCommentVendor;
 
     /** Timestamp when auto-categorization was initiated (format: "YYYY-MM-DD HH:MM:SS") */
     pendingAutoCategorizationTime?: string;
@@ -469,6 +463,15 @@ type SplitShare = {
 /** Record of participant split data, indexed by their `accountID` */
 type SplitShares = Record<number, SplitShare | null>;
 
+/** Accounting-system vendor stored on a transaction's comment NVP */
+type TransactionCommentVendor = {
+    /** External ID of the vendor in the connected accounting system */
+    externalID: string;
+
+    /** Whether the vendor was set manually by a user (vs. auto-matched by the fuzzy matcher) */
+    isManuallySet: boolean;
+};
+
 /** Model of transaction */
 type Transaction = OnyxCommon.OnyxValueWithOfflineFeedback<
     {
@@ -717,6 +720,9 @@ type AdditionalTransactionChanges = {
 
     /** The unit for the distance/quantity */
     quantity?: number;
+
+    /** Accounting-system vendor on the transaction's comment NVP. `null` clears the vendor. */
+    vendor?: TransactionCommentVendor | null;
 };
 
 /** Model of transaction changes  */
@@ -749,5 +755,6 @@ export type {
     TransactionCollectionDataSet,
     SplitShares,
     TransactionCustomUnit,
+    TransactionCommentVendor,
     UnreportedTransaction,
 };
diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts
index 73d114a88216..de1e76f91ff6 100644
--- a/src/types/onyx/index.ts
+++ b/src/types/onyx/index.ts
@@ -46,9 +46,9 @@ import type Credentials from './Credentials';
 import type Currency from './Currency';
 import type {CurrencyList} from './Currency';
 import type CustomStatusDraft from './CustomStatusDraft';
-import type DeferredAgentWorkflowSave from './DeferredAgentWorkflowSave';
 import type {
     CardFeedErrorsDerivedValue,
+    FlaggedExpensesDerivedValue,
     NonPersonalAndWorkspaceCardListDerivedValue,
     OpenAndSubmittedReportsByPolicyIDDerivedValue,
     OutstandingReportsByPolicyIDDerivedValue,
@@ -366,7 +366,6 @@ export type {
     BillingStatus,
     CancellationDetails,
     ApprovalWorkflowOnyx,
-    DeferredAgentWorkflowSave,
     CardFeeds,
     CardFeedsStatus,
     CardFeedsStatusByDomainID,
@@ -405,6 +404,7 @@ export type {
     CardFeedErrorsDerivedValue,
     TodosDerivedValue,
     TodoMetadata,
+    FlaggedExpensesDerivedValue,
     ScheduleCallDraft,
     ValidateUserAndGetAccessiblePolicies,
     VacationDelegate,
diff --git a/tests/actions/IOU/CreateDraftTransactionTest.ts b/tests/actions/IOU/CreateDraftTransactionTest.ts
index 4b0446cf0f89..f4110376bd22 100644
--- a/tests/actions/IOU/CreateDraftTransactionTest.ts
+++ b/tests/actions/IOU/CreateDraftTransactionTest.ts
@@ -96,6 +96,7 @@ jest.mock('@src/libs/SearchQueryUtils', () => {
 jest.mock('@libs/PolicyUtils', () => ({
     ...jest.requireActual<typeof PolicyUtils>('@libs/PolicyUtils'),
     isPaidGroupPolicy: jest.fn().mockReturnValue(true),
+    isGroupPolicy: jest.fn().mockReturnValue(true),
     isPolicyOwner: jest.fn().mockImplementation((policy?: OnyxEntry<Policy>, currentUserAccountID?: number) => !!currentUserAccountID && policy?.ownerAccountID === currentUserAccountID),
 }));
 
diff --git a/tests/actions/IOU/RequestMoneyTest.ts b/tests/actions/IOU/RequestMoneyTest.ts
index 2daf540888e6..5669507fd325 100644
--- a/tests/actions/IOU/RequestMoneyTest.ts
+++ b/tests/actions/IOU/RequestMoneyTest.ts
@@ -6,7 +6,8 @@ import type {SearchQueryJSON, SearchStatus} from '@components/Search/types';
 import {clearAllRelatedReportActionErrors} from '@libs/actions/ClearReportActionErrors';
 import {requestMoney, trackExpense} from '@libs/actions/IOU/TrackExpense';
 import initOnyxDerivedValues from '@libs/actions/OnyxDerived';
-import {deleteReport, notifyNewAction} from '@libs/actions/Report';
+import {notifyNewAction} from '@libs/actions/Report';
+import deleteReport from '@libs/actions/Report/DeleteReport';
 import {subscribeToUserEvents} from '@libs/actions/User';
 import type {ApiCommand} from '@libs/API/types';
 import {WRITE_COMMANDS} from '@libs/API/types';
diff --git a/tests/actions/IOUTest/DuplicateTest.ts b/tests/actions/IOUTest/DuplicateTest.ts
index 62b04ae44878..fc387144c05a 100644
--- a/tests/actions/IOUTest/DuplicateTest.ts
+++ b/tests/actions/IOUTest/DuplicateTest.ts
@@ -663,6 +663,93 @@ describe('actions/Duplicate', () => {
                 }),
             );
         });
+
+        it('should handle cross-report duplicates by cleaning up IOU actions and totals in each source report', async () => {
+            // Given: Duplicate transactions in different reports
+            const keptReportID = 'reportA';
+            const crossReportID = 'reportB';
+            const mainTransactionID = 'mainTx';
+            const crossReportDuplicateID = 'crossDupTx';
+            const childReportIDMain = 'childMain';
+            const childReportIDCross = 'childCross';
+
+            const mainTransaction = createMockTransaction(mainTransactionID, keptReportID, 100);
+            const crossDuplicateTransaction = createMockTransaction(crossReportDuplicateID, crossReportID, 100);
+
+            const keptReport = createMockReport(keptReportID, 200);
+            const crossReport = createMockReport(crossReportID, 200);
+
+            const mainViolations = createMockViolations();
+            const crossDuplicateViolations = createMockViolations();
+
+            const mainIouAction = createMockIouAction(mainTransactionID, 'actionMain', childReportIDMain);
+            const crossIouAction = createMockIouAction(crossReportDuplicateID, 'actionCross', childReportIDCross);
+
+            await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${mainTransactionID}`, mainTransaction);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${crossReportDuplicateID}`, crossDuplicateTransaction);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${keptReportID}`, keptReport);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${crossReportID}`, crossReport);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${mainTransactionID}`, mainViolations);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${crossReportDuplicateID}`, crossDuplicateViolations);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${keptReportID}`, {
+                actionMain: mainIouAction,
+            });
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${crossReportID}`, {
+                actionCross: crossIouAction,
+            });
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${childReportIDMain}`, {});
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${childReportIDCross}`, {});
+            await waitForBatchedUpdates();
+
+            const mergeParams: MergeDuplicatesParams = {
+                transactionID: mainTransactionID,
+                transactionIDList: [crossReportDuplicateID],
+                created: '2024-01-01 12:00:00',
+                merchant: 'Updated Merchant',
+                amount: 100,
+                currency: CONST.CURRENCY.EUR,
+                category: 'Travel',
+                comment: 'Updated comment',
+                billable: true,
+                reimbursable: false,
+                tag: 'UpdatedProject',
+                receiptID: 123,
+                reportID: keptReportID,
+            };
+
+            // When: Call mergeDuplicates with cross-report duplicates
+            mergeDuplicates({...mergeParams, currentUserLogin: RORY_EMAIL, currentUserAccountID: RORY_ACCOUNT_ID});
+            await waitForBatchedUpdates();
+
+            // Then: cross-report IOU action was soft-deleted
+            const crossReportActions = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${crossReportID}`);
+            expect(getOriginalMessage(crossReportActions?.actionCross)).toHaveProperty('deleted');
+
+            // Then: kept report total was NOT decremented (kept transaction stays)
+            const updatedKeptReport = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${keptReportID}`);
+            expect(updatedKeptReport?.total).toBe(200);
+
+            // Then: cross-report total WAS decremented
+            const updatedCrossReport = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${crossReportID}`);
+            expect(updatedCrossReport?.total).toBe(100); // 200 - 100 = 100
+
+            // Then: duplicate transaction was removed
+            const removedDuplicate = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${crossReportDuplicateID}`);
+            expect(removedDuplicate).toBeFalsy();
+
+            // Then: Verify API was called with correct parameters
+            expect(writeSpy).toHaveBeenCalledWith(
+                WRITE_COMMANDS.MERGE_DUPLICATES,
+                expect.objectContaining({
+                    transactionID: mainTransactionID,
+                    transactionIDList: [crossReportDuplicateID],
+                }),
+                expect.objectContaining({
+                    optimisticData: expect.arrayContaining([]),
+                    failureData: expect.arrayContaining([]),
+                }),
+            );
+        });
     });
 
     describe('resolveDuplicates', () => {
diff --git a/tests/actions/IOUTest/UpdateMoneyRequestTest.ts b/tests/actions/IOUTest/UpdateMoneyRequestTest.ts
index 62027a76bf45..c4112c98cd19 100644
--- a/tests/actions/IOUTest/UpdateMoneyRequestTest.ts
+++ b/tests/actions/IOUTest/UpdateMoneyRequestTest.ts
@@ -683,7 +683,7 @@ describe('actions/IOU/UpdateMoneyRequest', () => {
             });
             await waitForBatchedUpdates();
 
-            // Then the recent attendees should be updated with a maximum of 5 attendees
+            // Then all 6 recent attendees should be stored (below the max of 40)
             const recentAttendees = await new Promise<OnyxEntry<Attendee[]>>((resolve) => {
                 const connection = Onyx.connectWithoutView({
                     key: ONYXKEYS.NVP_RECENT_ATTENDEES,
@@ -693,7 +693,7 @@ describe('actions/IOU/UpdateMoneyRequest', () => {
                     },
                 });
             });
-            expect(recentAttendees?.length).toBe(CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW);
+            expect(recentAttendees?.length).toBe(6);
         });
 
         it('should keep displayName-only attendees in recent attendees', async () => {
diff --git a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
index 273857b89b8c..451ac4e316ca 100644
--- a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
+++ b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
@@ -3,7 +3,7 @@ import {updateMoneyRequestVendor} from '@libs/actions/IOU/UpdateMoneyRequest';
 import * as API from '@libs/API';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {Transaction, TransactionViolation} from '@src/types/onyx';
+import type {Report, Transaction, TransactionViolation} from '@src/types/onyx';
 import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates';
 
 const TRANSACTION_ID = 'txn-vendor-test';
@@ -46,7 +46,11 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.clear();
     });
 
-    type OnyxDataArg = {optimisticData: Array<{key: string; value: unknown}>; failureData: Array<{key: string; value: unknown}>};
+    type OnyxDataArg = {
+        optimisticData: Array<{key: string; value: unknown}>;
+        successData: Array<{key: string; value: unknown}>;
+        failureData: Array<{key: string; value: unknown}>;
+    };
     const getOnyxDataArg = (): OnyxDataArg | undefined => {
         const firstCall = writeSpy.mock.calls.at(0) as unknown[] | undefined;
         return firstCall?.at(2) as OnyxDataArg | undefined;
@@ -56,7 +60,7 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`, [otherViolation, inactiveVendorViolation]);
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-active', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-active', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const violationsUpdate = onyxData?.optimisticData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`);
@@ -68,7 +72,7 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`, [inactiveVendorViolation]);
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, '', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: '', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const violationsUpdate = onyxData?.optimisticData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`);
@@ -81,7 +85,7 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`, original);
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-active', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-active', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const failureViolations = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`);
@@ -92,7 +96,7 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`, [otherViolation]);
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-active', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-active', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const violationsUpdate = onyxData?.optimisticData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`);
@@ -107,20 +111,152 @@ describe('updateMoneyRequestVendor', () => {
         });
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new');
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
-        const vendorRollback = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
-        expect(vendorRollback?.value).toEqual({comment: {vendor: previousVendor}});
+        const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect(transactionFailure?.value).toEqual({
+            pendingFields: {vendor: null},
+            comment: {vendor: previousVendor},
+        });
     });
 
     it('omits vendor rollback from failureData when no prior transaction snapshot exists', async () => {
         // No transaction arg + nothing in Onyx — the prior vendor is unknown, so we must not
-        // write `vendor: null` and silently clear whatever the server actually has.
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new');
+        // write `vendor: null` and silently clear whatever the server actually has. The
+        // pendingFields-clear entry still runs (so the offline indicator clears on rejection).
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
-        const vendorRollback = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
-        expect(vendorRollback).toBeUndefined();
+        const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect(transactionFailure?.value).toEqual({pendingFields: {vendor: null}});
+    });
+
+    it('writes pendingFields.vendor = UPDATE in optimisticData so the offline indicator surfaces', () => {
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', transaction: baseTransaction, delegateAccountID: undefined});
+
+        const onyxData = getOnyxDataArg();
+        const transactionOptimistic = onyxData?.optimisticData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect(transactionOptimistic?.value).toEqual({
+            comment: {vendor: {externalID: 'v-new', isManuallySet: true}},
+            pendingFields: {vendor: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
+        });
+    });
+
+    it('clears pendingFields.vendor in successData when the server confirms the write', () => {
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', transaction: baseTransaction, delegateAccountID: undefined});
+
+        const onyxData = getOnyxDataArg();
+        const transactionSuccess = onyxData?.successData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect(transactionSuccess?.value).toEqual({pendingFields: {vendor: null}});
+    });
+
+    it('clears pendingFields.vendor in failureData when the server rejects the write', () => {
+        // Even without a prior snapshot to roll the vendor itself back, the pending indicator must
+        // clear on failure — otherwise the row stays stuck in "pending" forever after a server reject.
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', delegateAccountID: undefined});
+
+        const onyxData = getOnyxDataArg();
+        const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect(transactionFailure?.value).toMatchObject({pendingFields: {vendor: null}});
+    });
+
+    describe('optimistic MODIFIED_EXPENSE report action', () => {
+        // The optimistic action only goes onto the transaction thread when the caller passes the
+        // thread report — `IOURequestStepVendor` does this when the user picks a vendor row. The
+        // action drives the "set the vendor to X" / "changed the vendor from X to Y" / "removed the
+        // vendor" system messages that show up in the thread before the server roundtrips. Without
+        // it the user sees the generic "changed the expense" fallback.
+        const TRANSACTION_THREAD_REPORT_ID = 'txn-thread-vendor-test';
+        const transactionThreadReport: Report = {
+            reportID: TRANSACTION_THREAD_REPORT_ID,
+            reportName: 'Transaction thread',
+        } as Report;
+
+        type ReportActionMap = Record<string, {actionName?: string; originalMessage?: {vendor?: unknown; oldVendor?: unknown}}>;
+
+        const findOptimisticModifiedExpense = (): {actionName?: string; originalMessage?: {vendor?: unknown; oldVendor?: unknown}} | undefined => {
+            const onyxData = getOnyxDataArg();
+            const reportActionsKey = `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${TRANSACTION_THREAD_REPORT_ID}`;
+            const update = onyxData?.optimisticData.find((entry) => entry.key === reportActionsKey);
+            const value = update?.value as ReportActionMap | undefined;
+            return value ? Object.values(value).find((action) => action?.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE) : undefined;
+        };
+
+        it('builds an optimistic MODIFIED_EXPENSE with `vendor` set and `oldVendor` null when adding a vendor (no prior)', () => {
+            updateMoneyRequestVendor({
+                transactionID: TRANSACTION_ID,
+                vendorID: 'v-new',
+                transaction: baseTransaction,
+                transactionThreadReport,
+                delegateAccountID: undefined,
+            });
+
+            const optimisticAction = findOptimisticModifiedExpense();
+            expect(optimisticAction).toBeDefined();
+            // `oldVendor: null` signals "no prior vendor". Onyx strips nested nulls on merge, which
+            // is fine — `ModifiedExpenseMessage` treats either key's presence as a vendor change.
+            expect(optimisticAction?.originalMessage).toMatchObject({
+                vendor: {externalID: 'v-new', isManuallySet: true},
+                oldVendor: null,
+            });
+        });
+
+        it('builds an optimistic MODIFIED_EXPENSE with both `vendor` and `oldVendor` set when changing the vendor', () => {
+            const previousVendor = {externalID: 'v-old', isManuallySet: false};
+            const transactionWithVendor: Transaction = {
+                ...baseTransaction,
+                comment: {vendor: previousVendor},
+            };
+
+            updateMoneyRequestVendor({
+                transactionID: TRANSACTION_ID,
+                vendorID: 'v-new',
+                transaction: transactionWithVendor,
+                transactionThreadReport,
+                delegateAccountID: undefined,
+            });
+
+            const optimisticAction = findOptimisticModifiedExpense();
+            expect(optimisticAction?.originalMessage).toMatchObject({
+                oldVendor: previousVendor,
+                vendor: {externalID: 'v-new', isManuallySet: true},
+            });
+        });
+
+        it('builds an optimistic MODIFIED_EXPENSE with `vendor` null and `oldVendor` set when clearing the vendor', () => {
+            const previousVendor = {externalID: 'v-old', isManuallySet: true};
+            const transactionWithVendor: Transaction = {
+                ...baseTransaction,
+                comment: {vendor: previousVendor},
+            };
+
+            updateMoneyRequestVendor({
+                transactionID: TRANSACTION_ID,
+                vendorID: '',
+                transaction: transactionWithVendor,
+                transactionThreadReport,
+                delegateAccountID: undefined,
+            });
+
+            const optimisticAction = findOptimisticModifiedExpense();
+            expect(optimisticAction?.originalMessage).toMatchObject({
+                oldVendor: previousVendor,
+                vendor: null,
+            });
+        });
+
+        it('does NOT build an optimistic MODIFIED_EXPENSE when no transactionThreadReport is passed (defensive — no thread to write to)', () => {
+            updateMoneyRequestVendor({
+                transactionID: TRANSACTION_ID,
+                vendorID: 'v-new',
+                transaction: baseTransaction,
+                delegateAccountID: undefined,
+            });
+
+            const onyxData = getOnyxDataArg();
+            const reportActionsUpdate = onyxData?.optimisticData.find((entry) => entry.key.startsWith(ONYXKEYS.COLLECTION.REPORT_ACTIONS));
+            expect(reportActionsUpdate).toBeUndefined();
+        });
     });
 });
diff --git a/tests/actions/PolicyMemberTest.ts b/tests/actions/PolicyMemberTest.ts
index 414995f62ed0..db7be5d7e88d 100644
--- a/tests/actions/PolicyMemberTest.ts
+++ b/tests/actions/PolicyMemberTest.ts
@@ -399,7 +399,7 @@ describe('actions/PolicyMember', () => {
             await mockFetch?.resume?.();
         });
 
-        it('Add new members with admin/auditor role to the #admins room', async () => {
+        it('Add new members with admin/scoped admin role to the #admins room', async () => {
             // Given a policy and an #admins room
             const policyID = '1';
             const adminRoomID = '1';
@@ -407,8 +407,8 @@ describe('actions/PolicyMember', () => {
             const ownerAccountID = 1;
             const adminAccountID = 1234;
             const adminEmail = 'admin@example.com';
-            const auditorAccountID = 1235;
-            const auditorEmail = 'auditor@example.com';
+            const cardAdminAccountID = 1235;
+            const cardAdminEmail = 'card-admin@example.com';
             const userAccountID = 1236;
             const userEmail = 'user@example.com';
             const policy = {
@@ -425,18 +425,18 @@ describe('actions/PolicyMember', () => {
                 },
             });
             await Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {
-                [auditorAccountID]: {login: auditorEmail},
+                [cardAdminAccountID]: {login: cardAdminEmail},
             });
 
-            // When adding a new admin, auditor, and user members
+            // When adding a new admin, scoped admin, and user members
             mockFetch?.pause?.();
             Member.addMembersToWorkspace({[adminEmail]: adminAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.ADMIN, TestHelper.formatPhoneNumber, currentUser, {});
-            Member.addMembersToWorkspace({[auditorEmail]: auditorAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.AUDITOR, TestHelper.formatPhoneNumber, currentUser, {});
+            Member.addMembersToWorkspace({[cardAdminEmail]: cardAdminAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.CARD_ADMIN, TestHelper.formatPhoneNumber, currentUser, {});
             Member.addMembersToWorkspace({[userEmail]: userAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.USER, TestHelper.formatPhoneNumber, currentUser, {});
 
             await waitForBatchedUpdates();
 
-            // Then only the admin and auditor should be added to the #admins room optimistically
+            // Then only the admin and scoped admin should be added to the #admins room optimistically
             const adminRoom = await new Promise<OnyxEntry<Report>>((resolve) => {
                 const connection = Onyx.connect({
                     key: `${ONYXKEYS.COLLECTION.REPORT}${adminRoomID}`,
@@ -447,7 +447,7 @@ describe('actions/PolicyMember', () => {
                 });
             });
             expect(adminRoom?.participants?.[adminAccountID]).toBeTruthy();
-            expect(adminRoom?.participants?.[auditorAccountID]).toBeTruthy();
+            expect(adminRoom?.participants?.[cardAdminAccountID]).toBeTruthy();
             expect(adminRoom?.participants?.[userAccountID]).toBeUndefined();
 
             // and removed if the account is optimistic
@@ -462,7 +462,7 @@ describe('actions/PolicyMember', () => {
                 });
             });
             expect(adminRoomSuccess?.participants?.[adminAccountID]).toBeUndefined();
-            expect(adminRoomSuccess?.participants?.[auditorAccountID]).toBeTruthy();
+            expect(adminRoomSuccess?.participants?.[cardAdminAccountID]).toBeTruthy();
         });
 
         it('overrides the invited role to Editor on Submit workspaces, regardless of what the caller passes', async () => {
@@ -737,7 +737,7 @@ describe('actions/PolicyMember', () => {
     });
 
     describe('removeMembers', () => {
-        it('Remove members with admin/auditor role from the #admins room', async () => {
+        it('Remove members with admin role from the #admins room', async () => {
             // Given a policy and an #admins room
             const policyID = '1';
             const adminRoomID = '1';
@@ -777,7 +777,7 @@ describe('actions/PolicyMember', () => {
                 },
             });
 
-            // When removing am admin, auditor, and user members
+            // When removing an admin, auditor, and user members
             mockFetch?.pause?.();
             const memberEmailsToAccountIDs = {
                 [adminEmail]: adminAccountID,
@@ -788,7 +788,7 @@ describe('actions/PolicyMember', () => {
 
             await waitForBatchedUpdates();
 
-            // Then only the admin and auditor should be removed from the #admins room
+            // Then only the admin should be removed from the #admins room
             const optimisticAdminRoomMetadata = await new Promise<OnyxEntry<ReportMetadata>>((resolve) => {
                 const connection = Onyx.connect({
                     key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${adminRoomID}`,
@@ -798,13 +798,11 @@ describe('actions/PolicyMember', () => {
                     },
                 });
             });
-            expect(optimisticAdminRoomMetadata?.pendingChatMembers?.length).toBe(2);
+            expect(optimisticAdminRoomMetadata?.pendingChatMembers?.length).toBe(1);
             expect(optimisticAdminRoomMetadata?.pendingChatMembers?.find((pendingMember) => pendingMember.accountID === String(adminAccountID))?.pendingAction).toBe(
                 CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
             );
-            expect(optimisticAdminRoomMetadata?.pendingChatMembers?.find((pendingMember) => pendingMember.accountID === String(auditorAccountID))?.pendingAction).toBe(
-                CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
-            );
+            expect(optimisticAdminRoomMetadata?.pendingChatMembers?.find((pendingMember) => pendingMember.accountID === String(auditorAccountID))).toBeUndefined();
             await mockFetch?.resume?.();
 
             const successAdminRoomMetadata = await new Promise<OnyxEntry<ReportMetadata>>((resolve) => {
diff --git a/tests/actions/ReplaceOptimisticReportWithActualReportTest.ts b/tests/actions/ReplaceOptimisticReportWithActualReportTest.ts
index f879c4dcb8cb..6bf71df0c476 100644
--- a/tests/actions/ReplaceOptimisticReportWithActualReportTest.ts
+++ b/tests/actions/ReplaceOptimisticReportWithActualReportTest.ts
@@ -917,6 +917,71 @@ describe('replaceOptimisticReportWithActualReport', () => {
         subscription.remove();
     });
 
+    it('should swap to preexisting thread when focused on the search RHP transaction-thread carousel', async () => {
+        // Given an optimistic transaction thread under a multi-transaction IOU report opened in the
+        // "Review X expenses" carousel, i.e. the focused route is the SEARCH_REPORT RHP (search/view/:reportID)
+        const iouReportID = '9999';
+        const optimisticReportID = '1234';
+        const preexistingReportID = '5555';
+
+        mockIsReady.mockReturnValue(true);
+        // The carousel route is search/view/<id>, NOT /r/<id>
+        mockGetActiveRoute.mockReturnValue(`/search/view/${optimisticReportID}`);
+        mockGetCurrentRoute.mockReturnValue({name: SCREENS.RIGHT_MODAL.SEARCH_REPORT, params: {reportID: optimisticReportID}});
+
+        const reportActionID1 = '1';
+        const reportActionID2 = '2';
+        await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, {
+            reportID: iouReportID,
+            type: CONST.REPORT.TYPE.IOU,
+            transactionCount: 2,
+        });
+        await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, {
+            [reportActionID1]: {
+                reportActionID: reportActionID1,
+                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+                originalMessage: {type: CONST.IOU.REPORT_ACTION_TYPE.CREATE, IOUTransactionID: 'trans1'},
+            },
+            [reportActionID2]: {
+                reportActionID: reportActionID2,
+                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+                originalMessage: {type: CONST.IOU.REPORT_ACTION_TYPE.CREATE, IOUTransactionID: 'trans2'},
+            },
+        });
+
+        const optimisticReport = {
+            reportID: optimisticReportID,
+            type: CONST.REPORT.TYPE.CHAT,
+            parentReportID: iouReportID,
+            parentReportActionID: reportActionID1,
+            preexistingReportID,
+        };
+
+        await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${optimisticReportID}`, optimisticReport);
+        await waitForBatchedUpdates();
+
+        let capturedEventData: SwitchReportEventData | undefined;
+        const subscription = DeviceEventEmitter.addListener(`switchToPreExistingReport_${optimisticReportID}`, (data: SwitchReportEventData) => {
+            capturedEventData = data;
+        });
+
+        // When replaceOptimisticReportWithActualReport is called and the callback is executed
+        replaceOptimisticReportWithActualReport(optimisticReport, undefined);
+        await waitForBatchedUpdates();
+
+        // Then the switch event is emitted (the focused optimistic report is recognized on the RHP route)
+        expect(capturedEventData).toBeDefined();
+
+        capturedEventData?.callback();
+        await waitForBatchedUpdates();
+
+        // And the carousel is swapped to the preexisting thread via setParams (staying in the RHP),
+        // instead of being cleared out and bounced to the parent report
+        expect(mockSetParams).toHaveBeenCalledWith({reportID: preexistingReportID.toString()});
+
+        subscription.remove();
+    });
+
     it('should update backTo route when optimistic report is in background on expense report screen', async () => {
         // Given an optimistic report in the background while user is on expense report screen with backTo pointing to it
         const reportID = '1';
diff --git a/tests/actions/ReportFieldTest.ts b/tests/actions/ReportFieldTest.ts
index 836af094171b..a3d605a4304a 100644
--- a/tests/actions/ReportFieldTest.ts
+++ b/tests/actions/ReportFieldTest.ts
@@ -91,7 +91,7 @@ describe('actions/ReportField', () => {
                 initialValue: 'Default Value',
                 listValues: [],
                 disabledListValues: [],
-                policyReportIDs: [],
+                policyExpenseReportIDs: [],
             };
 
             ReportField.createReportField(createReportFieldArguments);
@@ -146,7 +146,7 @@ describe('actions/ReportField', () => {
                 initialValue: defaultDate,
                 listValues: [],
                 disabledListValues: [],
-                policyReportIDs: [],
+                policyExpenseReportIDs: [],
             };
 
             ReportField.createReportField(createReportFieldArguments);
@@ -203,7 +203,7 @@ describe('actions/ReportField', () => {
                 initialValue: '',
                 listValues: ['Value 1', 'Value 2'],
                 disabledListValues: [false, true],
-                policyReportIDs: [],
+                policyExpenseReportIDs: [],
             };
 
             ReportField.createReportField(createReportFieldArguments);
@@ -259,7 +259,7 @@ describe('actions/ReportField', () => {
             initialValue: formulaInitialValue,
             listValues: [],
             disabledListValues: [],
-            policyReportIDs: [],
+            policyExpenseReportIDs: [],
         };
 
         ReportField.createReportField(createReportFieldArguments);
@@ -496,7 +496,7 @@ describe('actions/ReportField', () => {
                 initialValue: '{report:id}',
                 listValues: [],
                 disabledListValues: [],
-                policyReportIDs: [],
+                policyExpenseReportIDs: [],
             });
             await waitForBatchedUpdates();
 
diff --git a/tests/ui/AIRulesSectionTest.tsx b/tests/ui/AIRulesSectionTest.tsx
new file mode 100644
index 000000000000..7bbc4e913b2f
--- /dev/null
+++ b/tests/ui/AIRulesSectionTest.tsx
@@ -0,0 +1,294 @@
+import {render} from '@testing-library/react-native';
+import React from 'react';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import useNetwork from '@hooks/useNetwork';
+import usePolicy from '@hooks/usePolicy';
+import Navigation from '@libs/Navigation/Navigation';
+import AIRulesSection from '@pages/workspace/rules/AIRulesSection';
+import CONST from '@src/CONST';
+import ROUTES from '@src/ROUTES';
+
+jest.mock('@components/Badge', () => jest.fn(() => null));
+jest.mock('@components/MenuItem', () => jest.fn(() => null));
+jest.mock('@components/MenuItemWithTopDescription', () => jest.fn(() => null));
+jest.mock(
+    '@components/OfflineWithFeedback',
+    () =>
+        ({children}: {children: React.ReactNode}) =>
+            children,
+);
+jest.mock(
+    '@components/Section',
+    () =>
+        ({children}: {children: React.ReactNode}) =>
+            children,
+);
+jest.mock('@components/Text', () => jest.fn(() => null));
+
+jest.mock('@hooks/useLazyAsset', () => ({
+    useMemoizedLazyExpensifyIcons: jest.fn(() => ({Plus: null})),
+}));
+jest.mock('@hooks/useLocalize', () =>
+    jest.fn(() => ({
+        translate: (key: string) => key,
+    })),
+);
+jest.mock('@hooks/useNetwork', () => jest.fn(() => ({isOffline: false})));
+jest.mock('@hooks/usePolicy', () => jest.fn());
+jest.mock('@hooks/useTheme', () => jest.fn(() => ({text: '#000'})));
+jest.mock('@hooks/useThemeStyles', () =>
+    jest.fn(
+        () =>
+            new Proxy(
+                {},
+                {
+                    get: () => ({}),
+                },
+            ),
+    ),
+);
+
+jest.mock('@libs/Navigation/Navigation', () => ({
+    navigate: jest.fn(),
+}));
+
+jest.mock('@userActions/Policy/Rules', () => ({
+    clearPolicyAIRuleErrors: jest.fn(),
+}));
+
+const mockedUsePolicy = jest.mocked(usePolicy);
+const mockedUseNetwork = jest.mocked(useNetwork);
+const mockedMenuItemWithTopDescription = jest.mocked(MenuItemWithTopDescription);
+const mockedMenuItem = jest.mocked(MenuItem);
+const mockedNavigate = jest.mocked(Navigation.navigate);
+
+const POLICY_ID = 'POLICY_ID_1';
+
+function setPolicyAIRules(aiRules: Record<string, unknown> | undefined) {
+    (mockedUsePolicy as jest.Mock).mockReturnValue({rules: {aiRules}});
+}
+
+function getRuleTitles(): string[] {
+    return mockedMenuItemWithTopDescription.mock.calls.map((call) => String(call.at(0)?.title ?? ''));
+}
+
+const mockKeyboardEvent = new KeyboardEvent('keydown');
+
+describe('AIRulesSection', () => {
+    beforeEach(() => {
+        jest.clearAllMocks();
+        mockedUseNetwork.mockReturnValue({isOffline: false} as ReturnType<typeof useNetwork>);
+    });
+
+    describe('title rendering', () => {
+        it('uses rule.title when set', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'Long prompt text', title: 'Short title', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['Short title']);
+        });
+
+        it('falls back to rule.prompt when title is missing', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'Prompt only', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['Prompt only']);
+        });
+
+        it('collapses whitespace and trims', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: '  hello\n\n  world  \t!  ', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['hello world !']);
+        });
+    });
+
+    describe('rule list filtering and sorting', () => {
+        it('sorts rules by created desc', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'first', title: 'A', created: '2026-01-01 00:00:00'},
+                r2: {ruleID: 'r2', prompt: 'second', title: 'B', created: '2026-02-01 00:00:00'},
+                r3: {ruleID: 'r3', prompt: 'third', title: 'C', created: '2026-03-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['C', 'B', 'A']);
+        });
+
+        it('hides pending-delete rules when online', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'keep', title: 'Keep', created: '2026-01-01 00:00:00'},
+                r2: {
+                    ruleID: 'r2',
+                    prompt: 'goner',
+                    title: 'Goner',
+                    created: '2026-02-01 00:00:00',
+                    pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
+                },
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['Keep']);
+        });
+
+        it('keeps pending-delete rules when offline so OfflineWithFeedback can style them', () => {
+            mockedUseNetwork.mockReturnValue({isOffline: true} as ReturnType<typeof useNetwork>);
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'keep', title: 'Keep', created: '2026-01-01 00:00:00'},
+                r2: {
+                    ruleID: 'r2',
+                    prompt: 'goner',
+                    title: 'Goner',
+                    created: '2026-02-01 00:00:00',
+                    pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
+                },
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['Goner', 'Keep']);
+        });
+
+        it('renders no rule items when policy has none', () => {
+            setPolicyAIRules(undefined);
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(mockedMenuItemWithTopDescription).not.toHaveBeenCalled();
+        });
+    });
+
+    describe('add rule button', () => {
+        it('navigates to RULES_AI_NEW when user has write access', () => {
+            setPolicyAIRules(undefined);
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            const onPress = mockedMenuItem.mock.calls.at(0)?.at(0)?.onPress;
+            onPress?.(mockKeyboardEvent);
+
+            expect(mockedNavigate).toHaveBeenCalledWith(ROUTES.RULES_AI_NEW.getRoute(POLICY_ID));
+        });
+
+        it('calls showReadOnlyModal when user lacks write access', () => {
+            const showReadOnlyModal = jest.fn();
+            setPolicyAIRules(undefined);
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules={false}
+                    showReadOnlyModal={showReadOnlyModal}
+                />,
+            );
+
+            const onPress = mockedMenuItem.mock.calls.at(0)?.at(0)?.onPress;
+            onPress?.(mockKeyboardEvent);
+
+            expect(showReadOnlyModal).toHaveBeenCalledTimes(1);
+            expect(mockedNavigate).not.toHaveBeenCalled();
+        });
+    });
+
+    describe('rule item press', () => {
+        it('navigates to RULES_AI_EDIT when user has write access', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'p', title: 'T', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            const onPress = mockedMenuItemWithTopDescription.mock.calls.at(0)?.at(0)?.onPress;
+            onPress?.(mockKeyboardEvent);
+
+            expect(mockedNavigate).toHaveBeenCalledWith(ROUTES.RULES_AI_EDIT.getRoute(POLICY_ID, 'r1'));
+        });
+
+        it('calls showReadOnlyModal when user lacks write access', () => {
+            const showReadOnlyModal = jest.fn();
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'p', title: 'T', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules={false}
+                    showReadOnlyModal={showReadOnlyModal}
+                />,
+            );
+
+            const onPress = mockedMenuItemWithTopDescription.mock.calls.at(0)?.at(0)?.onPress;
+            onPress?.(mockKeyboardEvent);
+
+            expect(showReadOnlyModal).toHaveBeenCalledTimes(1);
+            expect(mockedNavigate).not.toHaveBeenCalled();
+        });
+    });
+});
diff --git a/tests/ui/AgentsPromoBannersTest.tsx b/tests/ui/AgentsPromoBannersTest.tsx
index fda49af792dd..fcf2531e33a5 100644
--- a/tests/ui/AgentsPromoBannersTest.tsx
+++ b/tests/ui/AgentsPromoBannersTest.tsx
@@ -5,7 +5,6 @@ import ComposeProviders from '@components/ComposeProviders';
 import {LocaleContextProvider} from '@components/LocaleContextProvider';
 import OnyxListItemProvider from '@components/OnyxListItemProvider';
 import PolicyRulesPage from '@pages/workspace/rules/PolicyRulesPage';
-import WorkspaceWorkflowsPage from '@pages/workspace/workflows/WorkspaceWorkflowsPage';
 import CONST from '@src/CONST';
 import en from '@src/languages/en';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -38,16 +37,6 @@ jest.mock('@libs/Navigation/Navigation', () => ({
     setNavigationActionToMicrotaskQueue: (cb: () => void) => cb(),
 }));
 
-jest.mock('@libs/actions/Policy/Policy', () => {
-    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
-    const actual = jest.requireActual('@libs/actions/Policy/Policy');
-    // eslint-disable-next-line @typescript-eslint/no-unsafe-return
-    return {
-        ...actual,
-        openPolicyWorkflowsPage: jest.fn(),
-    };
-});
-
 jest.mock('@libs/actions/Policy/Rules', () => {
     // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
     const actual = jest.requireActual('@libs/actions/Policy/Rules');
@@ -58,10 +47,6 @@ jest.mock('@libs/actions/Policy/Rules', () => {
     };
 });
 
-jest.mock('@userActions/PaymentMethods', () => ({
-    getPaymentMethods: jest.fn(),
-}));
-
 jest.mock('@components/RenderHTML', () => {
     const ReactMock = require('react') as typeof React;
 
@@ -99,26 +84,12 @@ function buildPolicy(): Policy {
     } as Policy;
 }
 
-const workflowsRoute = {
-    key: 'workflows-route',
-    name: SCREENS.WORKSPACE.WORKFLOWS,
-    params: {policyID: POLICY_ID},
-} as never;
-
 const rulesRoute = {
     key: 'rules-route',
     name: SCREENS.WORKSPACE.RULES,
     params: {policyID: POLICY_ID},
 } as never;
 
-const renderWorkflowsPage = () =>
-    render(
-        <ComposeProviders components={[OnyxListItemProvider, LocaleContextProvider]}>
-            {/* @ts-expect-error - navigation prop is not used by the page in tests */}
-            <WorkspaceWorkflowsPage route={workflowsRoute} />
-        </ComposeProviders>,
-    );
-
 const renderRulesPage = () =>
     render(
         <ComposeProviders components={[OnyxListItemProvider, LocaleContextProvider]}>
@@ -154,28 +125,6 @@ describe('Agents promo banners', () => {
         });
     });
 
-    it('renders agentsWorkflowsBanner inside Approvals subMenuItems when customAgent beta is active, and hides it after dismissal', async () => {
-        await act(async () => {
-            await setupOnyxBaseline({withCustomAgentBeta: true});
-            await waitForBatchedUpdatesWithAct();
-        });
-
-        renderWorkflowsPage();
-        await waitForBatchedUpdatesWithAct();
-
-        // Title includes a nested "New" badge, so match on subtitle instead of the full title string.
-        expect(screen.getByText(en.workflowsPage.automateApprovalsWithAgentsSubtitle)).toBeTruthy();
-
-        await act(async () => {
-            await Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
-                [CONST.AGENTS_WORKFLOWS_BANNER]: {timestamp: '2026-05-20', dismissedMethod: 'x'},
-            });
-            await waitForBatchedUpdatesWithAct();
-        });
-
-        expect(screen.queryByText(en.workflowsPage.automateApprovalsWithAgentsSubtitle)).toBeNull();
-    });
-
     it('renders agentsRulesBanner above IndividualExpenseRulesSection when customAgent beta is active, and hides it after dismissal', async () => {
         await act(async () => {
             await setupOnyxBaseline({withCustomAgentBeta: true});
@@ -200,17 +149,12 @@ describe('Agents promo banners', () => {
         expect(screen.queryByText(en.workspace.rules.agentsPromoBanner.subtitle)).toBeNull();
     });
 
-    it('renders neither banner when customAgent beta is inactive', async () => {
+    it('does not render the agents rules banner when customAgent beta is inactive', async () => {
         await act(async () => {
             await setupOnyxBaseline({withCustomAgentBeta: false});
             await waitForBatchedUpdatesWithAct();
         });
 
-        const {unmount} = renderWorkflowsPage();
-        await waitForBatchedUpdatesWithAct();
-        expect(screen.queryByText(en.workflowsPage.automateApprovalsWithAgentsSubtitle)).toBeNull();
-        unmount();
-
         renderRulesPage();
         await waitForBatchedUpdatesWithAct();
         expect(screen.queryByText(en.workspace.rules.agentsPromoBanner.subtitle)).toBeNull();
diff --git a/tests/ui/AuthScreensInitHandlerTest.tsx b/tests/ui/AuthScreensInitHandlerTest.tsx
index 5a2732f79c41..9f2d8f927d07 100644
--- a/tests/ui/AuthScreensInitHandlerTest.tsx
+++ b/tests/ui/AuthScreensInitHandlerTest.tsx
@@ -72,10 +72,6 @@ jest.mock('@userActions/App', () => ({
     setLocale: jest.fn(),
 }));
 
-jest.mock('@userActions/Agent', () => ({
-    openAgentsPage: jest.fn(),
-}));
-
 jest.mock('@userActions/Download', () => ({
     clearDownloads: jest.fn(),
 }));
diff --git a/tests/ui/ForYouSectionTest.tsx b/tests/ui/ForYouSectionTest.tsx
index ebdcf1ce65ca..14877cc43c75 100644
--- a/tests/ui/ForYouSectionTest.tsx
+++ b/tests/ui/ForYouSectionTest.tsx
@@ -4,9 +4,10 @@ import Onyx from 'react-native-onyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import Navigation from '@libs/Navigation/Navigation';
 import ForYouSection from '@pages/home/ForYouSection';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
-import type {TodosDerivedValue} from '@src/types/onyx';
+import type {FlaggedExpensesDerivedValue, TodosDerivedValue} from '@src/types/onyx';
 import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct';
 
 jest.mock('@libs/Navigation/Navigation', () => ({
@@ -17,6 +18,9 @@ jest.mock('@libs/Navigation/Navigation', () => ({
 
 jest.mock('@hooks/useResponsiveLayout', () => jest.fn());
 
+const mockNavigateToTransactionThread = jest.fn();
+jest.mock('@hooks/useNavigateToTransactionThread', () => jest.fn(() => mockNavigateToTransactionThread));
+
 jest.mock('@hooks/useLocalize', () =>
     jest.fn(() => ({
         translate: jest.fn((key: string, params?: Record<string, unknown>) => {
@@ -44,12 +48,15 @@ jest.mock('@hooks/useThemeStyles', () =>
 
 jest.mock('@hooks/useTheme', () => jest.fn(() => ({})));
 
+const RECEIPT_SEARCH_ASSET = {testID: 'receipt-search-icon'};
+
 jest.mock('@hooks/useLazyAsset', () => ({
     useMemoizedLazyExpensifyIcons: jest.fn(() => ({
         MoneyBag: null,
         Send: null,
         ThumbsUp: null,
         Export: null,
+        ReceiptSearch: RECEIPT_SEARCH_ASSET,
     })),
     useMemoizedLazyIllustrations: jest.fn(() => ({
         ThumbsUpStars: null,
@@ -75,6 +82,8 @@ const BASE_TODOS: TodosDerivedValue = {
     transactionsByReportID: {},
 };
 
+const EMPTY_FLAGGED_EXPENSES: FlaggedExpensesDerivedValue = {flaggedExpenses: []};
+
 function renderForYouSection() {
     return render(<ForYouSection />);
 }
@@ -125,6 +134,7 @@ describe('ForYouSection', () => {
         it('renders EmptyState when there are no todos', async () => {
             await act(async () => {
                 await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, EMPTY_FLAGGED_EXPENSES);
             });
             await waitForBatchedUpdatesWithAct();
 
@@ -135,6 +145,177 @@ describe('ForYouSection', () => {
         });
     });
 
+    describe('review row', () => {
+        it('is not rendered when there are no flagged expenses', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, {
+                    ...BASE_TODOS,
+                    reportsToSubmit: [{reportID: '1'} as TodosDerivedValue['reportsToSubmit'][number]],
+                });
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, EMPTY_FLAGGED_EXPENSES);
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            expect(screen.queryByText(/homePage\.forYouSection\.reviewExpenses/)).not.toBeOnTheScreen();
+        });
+
+        it('renders with the count-1 string when exactly one expense is flagged', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [{transactionID: 't1', reportID: 'r1'}],
+                });
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            expect(screen.getByText('homePage.forYouSection.reviewExpenses:{"count":1}')).toBeOnTheScreen();
+        });
+
+        it('renders with the count-N string when multiple expenses are flagged', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [
+                        {transactionID: 't1', reportID: 'r1'},
+                        {transactionID: 't2', reportID: 'r2'},
+                        {transactionID: 't3', reportID: 'r3'},
+                    ],
+                });
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            expect(screen.getByText('homePage.forYouSection.reviewExpenses:{"count":3}')).toBeOnTheScreen();
+        });
+
+        it('renders the review row above submit/approve/pay/export rows', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, {
+                    ...BASE_TODOS,
+                    reportsToSubmit: [{reportID: 's1'} as TodosDerivedValue['reportsToSubmit'][number]],
+                    reportsToApprove: [{reportID: 'a1'} as TodosDerivedValue['reportsToApprove'][number]],
+                    reportsToPay: [{reportID: 'p1'} as TodosDerivedValue['reportsToPay'][number]],
+                    reportsToExport: [{reportID: 'e1'} as TodosDerivedValue['reportsToExport'][number]],
+                });
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [{transactionID: 't1', reportID: 'r1'}],
+                });
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            const reviewTitle = screen.getByText('homePage.forYouSection.reviewExpenses:{"count":1}');
+            const submitTitle = screen.getByText('homePage.forYouSection.submit:{"count":1}');
+            const approveTitle = screen.getByText('homePage.forYouSection.approve:{"count":1}');
+            const payTitle = screen.getByText('homePage.forYouSection.pay:{"count":1}');
+            const exportTitle = screen.getByText('homePage.forYouSection.export:{"count":1}');
+
+            // jest-native renderer assigns sequential _nativeTag-like positions; we rely on
+            // the order returned by getAllByText to verify rendering order.
+            const allTitles = screen.getAllByText(/homePage\.forYouSection\.(reviewExpenses|submit|approve|pay|export):/);
+            const getChildren = (node: {props: {children?: unknown}}) => node.props.children;
+            const titleOrder = allTitles.map(getChildren);
+
+            expect(titleOrder.at(0)).toBe(getChildren(reviewTitle));
+            expect(titleOrder).toEqual([getChildren(reviewTitle), getChildren(submitTitle), getChildren(approveTitle), getChildren(payTitle), getChildren(exportTitle)]);
+        });
+
+        it('exposes a Begin CTA and uses the ReceiptSearch icon asset', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [{transactionID: 't1', reportID: 'r1'}],
+                });
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            const {UNSAFE_root: unsafeRoot} = renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            expect(screen.getByText('Begin')).toBeOnTheScreen();
+
+            // The ReceiptSearch asset should be passed as the `icon` prop on at least one BaseWidgetItem.
+            // We look for any rendered element whose `icon` prop is the RECEIPT_SEARCH_ASSET reference.
+            const matchingNodes = unsafeRoot.findAll((node) => node.props && (node.props as {icon?: unknown}).icon === RECEIPT_SEARCH_ASSET);
+            expect(matchingNodes.length).toBeGreaterThan(0);
+        });
+    });
+
+    describe('review row navigation', () => {
+        it('delegates to useNavigateToTransactionThread with the first flagged expense and all sibling transaction IDs', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [
+                        {transactionID: 't1', reportID: 'r1'},
+                        {transactionID: 't2', reportID: 'r2'},
+                    ],
+                });
+                await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}r1`, {reportID: 'r1'});
+                await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}r1`, {
+                    action1: {
+                        reportActionID: 'action1',
+                        actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+                        childReportID: 'thread-r1',
+                        message: {IOUTransactionID: 't1'},
+                    },
+                });
+                await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}t1`, {transactionID: 't1', reportID: 'r1'});
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            pressFirstBeginButton();
+
+            expect(mockNavigateToTransactionThread).toHaveBeenCalledTimes(1);
+            expect(mockNavigateToTransactionThread).toHaveBeenCalledWith(
+                expect.objectContaining({
+                    transactionID: 't1',
+                    report: expect.objectContaining({reportID: 'r1'}),
+                    transaction: expect.objectContaining({transactionID: 't1'}),
+                    reportActions: expect.arrayContaining([expect.objectContaining({reportActionID: 'action1', childReportID: 'thread-r1'})]),
+                    siblingTransactionIDs: ['t1', 't2'],
+                    backTo: ROUTES.HOME,
+                }),
+            );
+            // The standard report routes should not be used for the review row anymore.
+            expect(mockNavigate).not.toHaveBeenCalled();
+        });
+
+        it('does not call the hook when there is no flagged transaction or report', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                // count > 0 keeps the row rendered, but the first transaction/report are missing
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [{transactionID: '', reportID: ''}],
+                });
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            const beginButton = screen.queryByText('Begin');
+            if (beginButton) {
+                fireEvent.press(beginButton);
+            }
+
+            expect(mockNavigateToTransactionThread).not.toHaveBeenCalled();
+        });
+    });
+
     describe('navigation with multiple reports (search route)', () => {
         it('navigates to SEARCH_ROOT when submit has multiple reports', async () => {
             await act(async () => {
diff --git a/tests/unit/AgentActionTest.ts b/tests/unit/AgentActionTest.ts
index 6b5c0847442d..051fc71dd932 100644
--- a/tests/unit/AgentActionTest.ts
+++ b/tests/unit/AgentActionTest.ts
@@ -178,26 +178,6 @@ describe('createAgent', () => {
         expect(result.avatarURI).toBeTruthy();
     });
 
-    it('mirrors pending/error state onto the policy so the workspace shows a brick road indicator', () => {
-        createAgent('Bot', 'My prompt', undefined, undefined, undefined, 'POLICY_42');
-
-        const {optimisticData, successData, failureData} = getWriteOptions();
-        const policyKey = `${ONYXKEYS.COLLECTION.POLICY}POLICY_42`;
-        const addAgentKey = CONST.POLICY.COLLECTION_KEYS.ADD_AGENT;
-
-        const optimisticPolicy = optimisticData.find((u) => u.key === policyKey);
-        expect((optimisticPolicy?.value as Record<string, Record<string, unknown>>)?.pendingFields?.[addAgentKey]).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
-        expect((optimisticPolicy?.value as Record<string, Record<string, unknown>>)?.errorFields?.[addAgentKey]).toBeNull();
-
-        const successPolicy = successData.find((u) => u.key === policyKey);
-        expect((successPolicy?.value as Record<string, Record<string, unknown>>)?.pendingFields?.[addAgentKey]).toBeNull();
-        expect((successPolicy?.value as Record<string, Record<string, unknown>>)?.errorFields?.[addAgentKey]).toBeNull();
-
-        const failurePolicy = failureData.find((u) => u.key === policyKey);
-        expect((failurePolicy?.value as Record<string, Record<string, unknown>>)?.pendingFields?.[addAgentKey]).toBeNull();
-        expect((failurePolicy?.value as Record<string, Record<string, unknown>>)?.errorFields?.[addAgentKey]).toBeTruthy();
-    });
-
     it('does not touch the policy when no policyID is provided', () => {
         createAgent('Bot', 'My prompt');
 
@@ -247,18 +227,6 @@ describe('createAgent', () => {
         expect(mockWrite).toHaveBeenCalledWith(WRITE_COMMANDS.CREATE_AGENT, expect.objectContaining({optimisticAccountID: String(result.optimisticAccountID)}), expect.any(Object));
     });
 
-    it('success and failure data clear the optimistic→real ID mapping entry', () => {
-        const result = createAgent('Bot', 'My prompt');
-        const {successData, failureData} = getWriteOptions();
-        const optID = String(result.optimisticAccountID);
-
-        const successMappingUpdate = successData.find((u) => u.key === ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING);
-        const failureMappingUpdate = failureData.find((u) => u.key === ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING);
-
-        expect((successMappingUpdate?.value as Record<string, unknown>)[optID]).toBeNull();
-        expect((failureMappingUpdate?.value as Record<string, unknown>)[optID]).toBeNull();
-    });
-
     it('failure data preserves optimistic personal detail and merges errors onto the prompt entry', () => {
         createAgent('Bot', 'My prompt');
 
diff --git a/tests/unit/ApprovalWorkflowSectionTest.tsx b/tests/unit/ApprovalWorkflowSectionTest.tsx
index 109c6ee95534..d13ea570de11 100644
--- a/tests/unit/ApprovalWorkflowSectionTest.tsx
+++ b/tests/unit/ApprovalWorkflowSectionTest.tsx
@@ -4,14 +4,10 @@ import ApprovalWorkflowSection from '@components/ApprovalWorkflowSection';
 import OnyxListItemProvider from '@components/OnyxListItemProvider';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
 
-let mockIsCustomAgentBetaEnabled = false;
-
 function mockTranslate(key: string): string {
     switch (key) {
         case 'workflowsPage.editWorkflowAction':
             return 'Edit';
-        case 'workflowsPage.addAgentAction':
-            return 'Add agent';
         case 'workflowsPage.approver':
             return 'Approver';
         case 'workflowsPage.addApprovalTip':
@@ -35,13 +31,6 @@ jest.mock('@hooks/useLocalize', () =>
     })),
 );
 
-jest.mock('@hooks/usePermissions', () => ({
-    __esModule: true,
-    default: () => ({
-        isBetaEnabled: () => mockIsCustomAgentBetaEnabled,
-    }),
-}));
-
 const baseWorkflow: ApprovalWorkflow = {
     isDefault: false,
     members: [
@@ -68,13 +57,12 @@ function renderSection(props: React.ComponentProps<typeof ApprovalWorkflowSectio
 
 describe('ApprovalWorkflowSection', () => {
     afterEach(() => {
-        mockIsCustomAgentBetaEnabled = false;
         jest.clearAllMocks();
     });
 
     it('renders the Edit pill that triggers the onPress handler', () => {
         const onPress = jest.fn();
-        renderSection({approvalWorkflow: baseWorkflow, onPress, onAddAgentPress: jest.fn(), canAddAgent: true});
+        renderSection({approvalWorkflow: baseWorkflow, onPress});
 
         const editButton = screen.getByLabelText('Edit');
         expect(editButton).toBeTruthy();
@@ -82,41 +70,9 @@ describe('ApprovalWorkflowSection', () => {
         expect(onPress).toHaveBeenCalledTimes(1);
     });
 
-    it('does not show the Add agent pill when the customAgent beta is disabled', () => {
-        mockIsCustomAgentBetaEnabled = false;
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress: jest.fn(), canAddAgent: true});
-
-        expect(screen.queryByLabelText('Add agent')).toBeNull();
-    });
-
-    it('shows the Add agent pill when the customAgent beta is enabled and the caller allows it', () => {
-        mockIsCustomAgentBetaEnabled = true;
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress: jest.fn(), canAddAgent: true});
-
-        expect(screen.getByLabelText('Add agent')).toBeTruthy();
-    });
-
-    it('does not show the Add agent pill when canAddAgent is false even if the beta is on', () => {
-        mockIsCustomAgentBetaEnabled = true;
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress: jest.fn(), canAddAgent: false});
-
-        expect(screen.queryByLabelText('Add agent')).toBeNull();
-    });
-
-    it('invokes onAddAgentPress when the Add agent pill is pressed', () => {
-        mockIsCustomAgentBetaEnabled = true;
-        const onAddAgentPress = jest.fn();
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress, canAddAgent: true});
-
-        fireEvent.press(screen.getByLabelText('Add agent'));
-        expect(onAddAgentPress).toHaveBeenCalledTimes(1);
-    });
-
-    it('hides both pill actions when the section is disabled (no-op for read-only workflows)', () => {
-        mockIsCustomAgentBetaEnabled = true;
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress: jest.fn(), canAddAgent: true, isDisabled: true});
+    it('hides the Edit pill when the section is disabled (no-op for read-only workflows)', () => {
+        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), isDisabled: true});
 
         expect(screen.queryByLabelText('Edit')).toBeNull();
-        expect(screen.queryByLabelText('Add agent')).toBeNull();
     });
 });
diff --git a/tests/unit/DefaultP2PMileageRateTest.ts b/tests/unit/DefaultP2PMileageRateTest.ts
index 820a10480f01..c077cbbe9b9c 100644
--- a/tests/unit/DefaultP2PMileageRateTest.ts
+++ b/tests/unit/DefaultP2PMileageRateTest.ts
@@ -1,4 +1,5 @@
 import Onyx from 'react-native-onyx';
+import {startMoneyRequest} from '@libs/actions/IOU/MoneyRequest';
 import {getDefaultP2PMileageRate} from '@libs/actions/Transaction';
 import * as API from '@libs/API';
 import {READ_COMMANDS} from '@libs/API/types';
@@ -9,6 +10,9 @@ import ONYXKEYS from '@src/ONYXKEYS';
 import createRandomTransaction from '../utils/collections/transaction';
 import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
 
+jest.mock('@libs/Navigation/Navigation');
+jest.mock('@libs/telemetry/activeSpans');
+
 describe('Default P2P mileage rate', () => {
     beforeAll(() => {
         Onyx.init({
@@ -34,6 +38,29 @@ describe('Default P2P mileage rate', () => {
         });
     });
 
+    describe('startMoneyRequest', () => {
+        // Splitting a distance expense goes through startMoneyRequest, so it must prefetch the default P2P mileage rate
+        // (the same way startDistanceRequest does) or the Distance tab loads with a malformed rate.
+        it('prefetches the default P2P mileage rate when starting a split distance request', () => {
+            // eslint-disable-next-line rulesdir/no-multiple-api-calls
+            const readSpy = jest.spyOn(API, 'read').mockImplementation(() => {});
+
+            startMoneyRequest(CONST.IOU.TYPE.SPLIT, '1', [], CONST.IOU.REQUEST_TYPE.DISTANCE);
+
+            expect(readSpy).toHaveBeenCalledWith(READ_COMMANDS.GET_DEFAULT_P2P_MILEAGE_RATE, null);
+        });
+
+        // Non-split flows never expose a Distance tab, so they must not issue the (uncached) prefetch read.
+        it('does not prefetch the default P2P mileage rate for non-split requests', () => {
+            // eslint-disable-next-line rulesdir/no-multiple-api-calls
+            const readSpy = jest.spyOn(API, 'read').mockImplementation(() => {});
+
+            startMoneyRequest(CONST.IOU.TYPE.SUBMIT, '1', [], CONST.IOU.REQUEST_TYPE.MANUAL);
+
+            expect(readSpy).not.toHaveBeenCalledWith(READ_COMMANDS.GET_DEFAULT_P2P_MILEAGE_RATE, null);
+        });
+    });
+
     describe('getRateForP2P', () => {
         it('falls back to USD 67¢/mile when no rate has been stored in Onyx', () => {
             const result = DistanceRequestUtils.getRateForP2P('EUR', undefined);
diff --git a/tests/unit/DeleteReportTest.ts b/tests/unit/DeleteReportTest.ts
new file mode 100644
index 000000000000..adeeb4b275c8
--- /dev/null
+++ b/tests/unit/DeleteReportTest.ts
@@ -0,0 +1,114 @@
+import Onyx from 'react-native-onyx';
+import deleteReport from '@libs/actions/Report/DeleteReport';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {ReportAction} from '@src/types/onyx';
+import createRandomReportAction from '../utils/collections/reportActions';
+import {createRandomReport} from '../utils/collections/reports';
+import createRandomTransaction from '../utils/collections/transaction';
+import getOnyxValue from '../utils/getOnyxValue';
+import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
+
+// Mock Log to avoid noise in tests
+jest.mock('@libs/Log');
+
+describe('actions/Report/DeleteReport', () => {
+    beforeAll(() => {
+        Onyx.init({
+            keys: ONYXKEYS,
+        });
+    });
+
+    beforeEach(() => {
+        return Onyx.clear();
+    });
+
+    it('should delete a report, its actions, and linked transactions', async () => {
+        // Given a report with an IOU action and a linked transaction
+        const reportID = '1';
+        const transactionID = '123';
+        const report = createRandomReport(1, undefined);
+        const transaction = createRandomTransaction(Number(transactionID));
+        const reportAction: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> = {
+            ...createRandomReportAction(100),
+            actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+            previousMessage: [],
+            message: [{text: '', html: 'iou', type: 'COMMENT'}],
+            originalMessage: {
+                type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
+                IOUTransactionID: transaction.transactionID,
+                IOUDetails: {
+                    amount: transaction.amount,
+                    currency: transaction.currency,
+                    comment: '',
+                },
+            },
+        };
+
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report);
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {
+            [reportAction.reportActionID]: reportAction,
+        });
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, transaction);
+
+        // When we delete the report
+        deleteReport(reportID);
+
+        await waitForBatchedUpdates();
+
+        // Then the report, its actions, and the linked transaction should be deleted
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`)).toBeUndefined();
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`)).toBeUndefined();
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`)).toBeUndefined();
+    });
+
+    it('should delete child reports recursively when shouldDeleteChildReports is true', async () => {
+        // Given a parent report with a child report
+        const parentReportID = '1';
+        const childReportID = '2';
+        const parentReport = createRandomReport(Number(parentReportID), undefined);
+        const childReport = createRandomReport(Number(childReportID), undefined);
+        const parentAction = {
+            ...createRandomReportAction(100),
+            childReportID,
+        };
+
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`, parentReport);
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${childReportID}`, childReport);
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`, {
+            [parentAction.reportActionID]: parentAction,
+        });
+
+        // When we delete the parent report with shouldDeleteChildReports set to true
+        deleteReport(parentReportID, true);
+
+        await waitForBatchedUpdates();
+
+        // Then both the parent and child reports should be deleted
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`)).toBeUndefined();
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${childReportID}`)).toBeUndefined();
+    });
+
+    it('should delete linked IOU reports recursively', async () => {
+        // Given a report with a linked IOU report
+        const reportID = '1';
+        const iouReportID = '2';
+        const report = {
+            ...createRandomReport(Number(reportID), undefined),
+            iouReportID,
+        };
+        const iouReport = createRandomReport(Number(iouReportID), undefined);
+
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report);
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, iouReport);
+
+        // When we delete the report
+        deleteReport(reportID);
+
+        await waitForBatchedUpdates();
+
+        // Then both reports should be deleted
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`)).toBeUndefined();
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`)).toBeUndefined();
+    });
+});
diff --git a/tests/unit/ModifiedExpenseMessageTest.ts b/tests/unit/ModifiedExpenseMessageTest.ts
index 4459f3cee9f9..e423ec007d7d 100644
--- a/tests/unit/ModifiedExpenseMessageTest.ts
+++ b/tests/unit/ModifiedExpenseMessageTest.ts
@@ -2156,5 +2156,118 @@ describe('ModifiedExpenseMessage', () => {
                 expect(result).toEqual(expectedResult);
             });
         });
+
+        describe('vendor changes', () => {
+            // QBO policy with two named vendors used by the resolver. The third case below
+            // omits a vendor from the list to exercise the externalID fallback path.
+            const policyWithVendors: Policy = {
+                id: 'p-1',
+                name: 'My Workspace',
+                role: CONST.POLICY.ROLE.ADMIN,
+                type: CONST.POLICY.TYPE.TEAM,
+                owner: 'test@example.com',
+                outputCurrency: CONST.CURRENCY.USD,
+                isPolicyExpenseChatEnabled: true,
+                connections: {
+                    quickbooksOnline: {
+                        data: {
+                            vendors: [
+                                {id: 'v-acme', name: 'Acme', currency: 'USD', email: ''},
+                                {id: 'v-office', name: 'Office Supplies', currency: 'USD', email: ''},
+                            ],
+                        },
+                    },
+                },
+            } as Policy;
+
+            describe('when the vendor is set for the first time (oldVendor key stripped by Onyx null-merge)', () => {
+                // Onyx merges with `shouldRemoveNestedNulls: true`, so the optimistic
+                // `oldVendor: null` we write is stripped from storage. The rendered action
+                // must still treat the missing key as a "set" rather than falling back to
+                // the generic "changed the expense" message.
+                const reportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE,
+                    originalMessage: {
+                        vendor: {externalID: 'v-acme', isManuallySet: true},
+                    },
+                };
+
+                it('renders "set the vendor to X"', () => {
+                    const result = getForReportAction({
+                        translate: translateLocal,
+                        reportAction,
+                        policy: policyWithVendors,
+                        policyTags: undefined,
+                        currentUserLogin: CURRENT_USER_LOGIN,
+                    });
+                    expect(result).toEqual('set the vendor to "Acme"');
+                });
+            });
+
+            describe('when the vendor is changed from one to another', () => {
+                const reportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE,
+                    originalMessage: {
+                        oldVendor: {externalID: 'v-acme', isManuallySet: false},
+                        vendor: {externalID: 'v-office', isManuallySet: true},
+                    },
+                };
+
+                it('renders "changed the vendor to Y (previously X)"', () => {
+                    const result = getForReportAction({
+                        translate: translateLocal,
+                        reportAction,
+                        policy: policyWithVendors,
+                        policyTags: undefined,
+                        currentUserLogin: CURRENT_USER_LOGIN,
+                    });
+                    expect(result).toEqual('changed the vendor to "Office Supplies" (previously "Acme")');
+                });
+            });
+
+            describe('when the vendor is removed (vendor key stripped by Onyx null-merge)', () => {
+                const reportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE,
+                    originalMessage: {
+                        oldVendor: {externalID: 'v-acme', isManuallySet: true},
+                    },
+                };
+
+                it('renders "removed the vendor X"', () => {
+                    const result = getForReportAction({
+                        translate: translateLocal,
+                        reportAction,
+                        policy: policyWithVendors,
+                        policyTags: undefined,
+                        currentUserLogin: CURRENT_USER_LOGIN,
+                    });
+                    expect(result).toEqual('removed the vendor (previously "Acme")');
+                });
+            });
+
+            describe('when the vendor is set to an ID no longer in the QBO vendor list (e.g. deleted from QBO)', () => {
+                const reportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE,
+                    originalMessage: {
+                        vendor: {externalID: 'v-deleted', isManuallySet: false},
+                    },
+                };
+
+                it('falls back to rendering the externalID so the fragment still identifies which vendor was set', () => {
+                    const result = getForReportAction({
+                        translate: translateLocal,
+                        reportAction,
+                        policy: policyWithVendors,
+                        policyTags: undefined,
+                        currentUserLogin: CURRENT_USER_LOGIN,
+                    });
+                    expect(result).toEqual('set the vendor to "v-deleted"');
+                });
+            });
+        });
     });
 });
diff --git a/tests/unit/OnboardingSelectorsTest.ts b/tests/unit/OnboardingSelectorsTest.ts
index f568760d06a8..c0fc5b52bce2 100644
--- a/tests/unit/OnboardingSelectorsTest.ts
+++ b/tests/unit/OnboardingSelectorsTest.ts
@@ -1,4 +1,4 @@
-import {hasCompletedGuidedSetupFlowSelector, hasSeenTourSelector} from '@selectors/Onboarding';
+import {hasCompletedGuidedSetupFlowSelector, hasSeenTourSelector, isTrackIntentUserSelector} from '@selectors/Onboarding';
 import type {OnyxValue} from 'react-native-onyx';
 import CONST from '@src/CONST';
 import type ONYXKEYS from '@src/ONYXKEYS';
@@ -59,4 +59,34 @@ describe('onboardingSelectors', () => {
             expect(hasSeenTourSelector(onboarding)).toBe(false);
         });
     });
+    describe('isTrackIntentUserSelector', () => {
+        it('Should return true for PERSONAL_SPEND choice', () => {
+            const introSelected = {choice: CONST.ONBOARDING_CHOICES.PERSONAL_SPEND} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(true);
+        });
+
+        it('Should return true for TRACK_BUSINESS choice', () => {
+            const introSelected = {choice: CONST.ONBOARDING_CHOICES.TRACK_BUSINESS} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(true);
+        });
+
+        it('Should return true for TRACK_PERSONAL choice', () => {
+            const introSelected = {choice: CONST.ONBOARDING_CHOICES.TRACK_PERSONAL} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(true);
+        });
+
+        it('Should return false for MANAGE_TEAM choice', () => {
+            const introSelected = {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(false);
+        });
+
+        it('Should return false for undefined introSelected', () => {
+            expect(isTrackIntentUserSelector(undefined)).toBe(false);
+        });
+
+        it('Should return false when choice is undefined', () => {
+            const introSelected = {} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(false);
+        });
+    });
 });
diff --git a/tests/unit/OnyxDerived/flaggedExpensesTest.ts b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
new file mode 100644
index 000000000000..12628862c3c0
--- /dev/null
+++ b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
@@ -0,0 +1,300 @@
+import type {OnyxCollection} from 'react-native-onyx';
+import flaggedExpensesConfig from '@libs/actions/OnyxDerived/configs/flaggedExpenses';
+import type {DerivedValueContext} from '@libs/actions/OnyxDerived/types';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report, Session, Transaction, TransactionViolations} from '@src/types/onyx';
+import {createMockReport} from '../../utils/ReportTestUtils';
+
+const CURRENT_USER_ACCOUNT_ID = 1;
+const CURRENT_USER_EMAIL = 'user@example.com';
+const OTHER_USER_ACCOUNT_ID = 2;
+const POLICY_ID_1 = 'policy1';
+const POLICY_ID_2 = 'policy2';
+
+function createExpenseReport(reportID: string, overrides: Partial<Report> = {}): Report {
+    return createMockReport({
+        reportID,
+        type: CONST.REPORT.TYPE.EXPENSE,
+        ownerAccountID: CURRENT_USER_ACCOUNT_ID,
+        policyID: POLICY_ID_1,
+        stateNum: CONST.REPORT.STATE_NUM.OPEN,
+        statusNum: CONST.REPORT.STATUS_NUM.OPEN,
+        ...overrides,
+    });
+}
+
+function createTransaction(transactionID: string, reportID: string, overrides: Partial<Transaction> = {}): Transaction {
+    return {
+        transactionID,
+        reportID,
+        amount: 100,
+        currency: 'USD',
+        created: '2024-01-01',
+        merchant: 'Test Merchant',
+        ...overrides,
+    } as Transaction;
+}
+
+function buildReports(...reports: Report[]): OnyxCollection<Report> {
+    const result: OnyxCollection<Report> = {};
+    for (const report of reports) {
+        result[`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`] = report;
+    }
+    return result;
+}
+
+function buildTransactions(...transactions: Transaction[]): OnyxCollection<Transaction> {
+    const result: OnyxCollection<Transaction> = {};
+    for (const transaction of transactions) {
+        result[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = transaction;
+    }
+    return result;
+}
+
+function buildViolations(violationsByTransactionID: Record<string, TransactionViolations>): OnyxCollection<TransactionViolations> {
+    const result: OnyxCollection<TransactionViolations> = {};
+    for (const [transactionID, violations] of Object.entries(violationsByTransactionID)) {
+        result[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`] = violations;
+    }
+    return result;
+}
+
+function createSession(accountID: number = CURRENT_USER_ACCOUNT_ID, email: string = CURRENT_USER_EMAIL): Session {
+    return {accountID, email} as Session;
+}
+
+const {compute} = flaggedExpensesConfig;
+const emptyContext = {} as DerivedValueContext<
+    typeof ONYXKEYS.DERIVED.FLAGGED_EXPENSES,
+    [typeof ONYXKEYS.COLLECTION.REPORT, typeof ONYXKEYS.COLLECTION.TRANSACTION, typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, typeof ONYXKEYS.COLLECTION.POLICY, typeof ONYXKEYS.SESSION]
+>;
+
+describe('flaggedExpenses derived value', () => {
+    describe('presence and count', () => {
+        it('reports zero flagged expenses and an empty list when no transactions have violations', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const result = compute([buildReports(report), buildTransactions(transaction), {}, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+
+        it('counts two flagged transactions on OPEN/OPEN expense reports across two workspaces', () => {
+            const report1 = createExpenseReport('r1', {policyID: POLICY_ID_1});
+            const report2 = createExpenseReport('r2', {policyID: POLICY_ID_2});
+            const transaction1 = createTransaction('t1', 'r1');
+            const transaction2 = createTransaction('t2', 'r2');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(report1, report2), buildTransactions(transaction1, transaction2), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(2);
+            const ids = result.flaggedExpenses.map((entry) => entry.transactionID).sort();
+            expect(ids).toEqual(['t1', 't2']);
+            const reportIDs = result.flaggedExpenses.map((entry) => entry.reportID).sort();
+            expect(reportIDs).toEqual(['r1', 'r2']);
+        });
+
+        it('counts a single transaction with multiple violations as 1 expense', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const violations = buildViolations({
+                t1: [
+                    {type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY},
+                    {type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_TAG},
+                ],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(1);
+            expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
+        });
+
+        it('counts every non-report-field violation type that OpenApp returns', () => {
+            const report = createExpenseReport('r1');
+            const transactions = [createTransaction('tA', 'r1'), createTransaction('tB', 'r1'), createTransaction('tC', 'r1')];
+            const violations = buildViolations({
+                tA: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.OVER_CATEGORY_LIMIT}],
+                tB: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_TAG}],
+                tC: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_COMMENT}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(...transactions), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(3);
+            expect(result.flaggedExpenses.map((entry) => entry.transactionID).sort()).toEqual(['tA', 'tB', 'tC']);
+        });
+
+        it('excludes violations with showInReview === false', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY, showInReview: false}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+
+        it('excludes warning/notice violations unless showInReview is explicitly true', () => {
+            const report = createExpenseReport('r1');
+            const transactions = [createTransaction('tWarn', 'r1'), createTransaction('tNotice', 'r1'), createTransaction('tShown', 'r1')];
+            const violations = buildViolations({
+                tWarn: [{type: CONST.VIOLATION_TYPES.WARNING, name: CONST.VIOLATIONS.RTER}],
+                tNotice: [{type: CONST.VIOLATION_TYPES.NOTICE, name: CONST.VIOLATIONS.RECEIPT_REQUIRED}],
+                tShown: [{type: CONST.VIOLATION_TYPES.NOTICE, name: CONST.VIOLATIONS.RECEIPT_REQUIRED, showInReview: true}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(...transactions), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([{transactionID: 'tShown', reportID: 'r1'}]);
+        });
+    });
+
+    describe('Draft-report scope and resolution', () => {
+        it('excludes flagged transactions on submitted expense reports', () => {
+            const draftReport = createExpenseReport('r1');
+            const submittedReport = createExpenseReport('r2', {
+                stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+                statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
+            });
+            const draftTransaction = createTransaction('t1', 'r1');
+            const submittedTransaction = createTransaction('t2', 'r2');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(draftReport, submittedReport), buildTransactions(draftTransaction, submittedTransaction), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(1);
+            expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
+        });
+
+        it('excludes flagged transactions whose parent report is not an expense report', () => {
+            const expenseReport = createExpenseReport('r1');
+            const chatReport = createMockReport({
+                reportID: 'r2',
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: CURRENT_USER_ACCOUNT_ID,
+                stateNum: CONST.REPORT.STATE_NUM.OPEN,
+                statusNum: CONST.REPORT.STATUS_NUM.OPEN,
+            });
+            const t1 = createTransaction('t1', 'r1');
+            const t2 = createTransaction('t2', 'r2');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(expenseReport, chatReport), buildTransactions(t1, t2), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(1);
+            expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
+        });
+
+        it('does not count report-field violations as flagged expenses', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.REPORT_VIOLATIONS.FIELD_REQUIRED} as TransactionViolations[number]],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+
+        it('drops a transaction from the list when its last violation is cleared', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const flaggedViolations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const flaggedResult = compute([buildReports(report), buildTransactions(transaction), flaggedViolations, {}, createSession()], emptyContext);
+            expect(flaggedResult.flaggedExpenses).toHaveLength(1);
+
+            const clearedViolations = buildViolations({t1: []});
+            const clearedResult = compute([buildReports(report), buildTransactions(transaction), clearedViolations, {}, createSession()], emptyContext);
+            expect(clearedResult.flaggedExpenses).toEqual([]);
+        });
+
+        it('restores a previously cleaned transaction once it is re-flagged', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+
+            const clearedResult = compute([buildReports(report), buildTransactions(transaction), buildViolations({t1: []}), {}, createSession()], emptyContext);
+            expect(clearedResult.flaggedExpenses).toEqual([]);
+
+            const reFlaggedResult = compute(
+                [
+                    buildReports(report),
+                    buildTransactions(transaction),
+                    buildViolations({
+                        t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                    }),
+                    {},
+                    createSession(),
+                ],
+                emptyContext,
+            );
+            expect(reFlaggedResult.flaggedExpenses).toHaveLength(1);
+            expect(reFlaggedResult.flaggedExpenses.at(0)?.transactionID).toBe('t1');
+        });
+
+        it('excludes flagged transactions on expense reports the current user does not own', () => {
+            const ownReport = createExpenseReport('r1');
+            const foreignReport = createExpenseReport('r2', {ownerAccountID: OTHER_USER_ACCOUNT_ID});
+            const ownTransaction = createTransaction('t1', 'r1');
+            const foreignTransaction = createTransaction('t2', 'r2');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(ownReport, foreignReport), buildTransactions(ownTransaction, foreignTransaction), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(1);
+            expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
+        });
+
+        it('excludes all flagged transactions when the session has no accountID', () => {
+            const report = createExpenseReport('r1', {ownerAccountID: OTHER_USER_ACCOUNT_ID});
+            const transaction = createTransaction('t1', 'r1');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, {} as Session], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+
+        it('excludes transactions when the current user dismissed the only reviewable violation', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1', {
+                comment: {
+                    dismissedViolations: {
+                        [CONST.VIOLATIONS.MISSING_CATEGORY]: {
+                            [CURRENT_USER_EMAIL]: '2024-01-01',
+                        },
+                    },
+                },
+            });
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+    });
+});
diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx
index 9c03d142793a..02aaacaff4f4 100644
--- a/tests/unit/OptionsListUtilsTest.tsx
+++ b/tests/unit/OptionsListUtilsTest.tsx
@@ -5343,6 +5343,38 @@ describe('OptionsListUtils', () => {
                 );
             });
         });
+        describe('UPDATE_CATEGORY_TAX_RATE action', () => {
+            it('should surface the rendered category default tax rate change in the last-message preview', async () => {
+                const report: Report = createRandomReport(0, undefined);
+                const changelogAction: ReportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                    message: [{type: 'COMMENT', text: ''}],
+                    originalMessage: {
+                        categoryName: 'Office Supplies',
+                        oldTaxName: 'Tax Exempt',
+                        oldTaxPercentage: '0%',
+                        newTaxName: 'Tax Rate 1',
+                        newTaxPercentage: '5%',
+                    },
+                };
+                await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {
+                    [changelogAction.reportActionID]: changelogAction,
+                });
+
+                const lastMessage = getLastMessageTextForReport({
+                    translate: translateLocal,
+                    report,
+                    lastActorDetails: null,
+                    policy: undefined,
+                    isReportArchived: false,
+                    currentUserLogin: CURRENT_USER_EMAIL,
+                });
+
+                expect(lastMessage).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Tax Exempt (0%)")');
+            });
+        });
+
         describe('UPDATE_MCC_GROUP_CATEGORY action', () => {
             it('should surface the friendly MCC group label in the last-message preview', async () => {
                 const report: Report = createRandomReport(0, undefined);
@@ -7767,6 +7799,41 @@ describe('OptionsListUtils', () => {
         });
     });
 
+    describe('getValidOptions() with recentAttendees', () => {
+        const recentAttendees = Array.from({length: 8}, (_, index) => ({
+            login: `john${index}@example.com`,
+            text: `John ${index}`,
+            accountID: 1000 + index,
+        }));
+
+        it('caps recent attendees to maxRecentReportElements when there is no search term', () => {
+            // When we call getValidOptions with more recent attendees than the display cap and no search term
+            const {options: results} = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, {
+                includeRecentReports: false,
+                recentAttendees,
+                maxRecentReportElements: 5,
+                sortedActions: undefined,
+            });
+
+            // Then only the first 5 recent attendees are shown
+            expect(results.recentReports.length).toBe(5);
+        });
+
+        it('shows all matching recent attendees beyond the cap when there is a search term', () => {
+            // When we call getValidOptions with a search term that matches all recent attendees
+            const {options: results} = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, {
+                includeRecentReports: false,
+                recentAttendees,
+                maxRecentReportElements: 5,
+                searchString: 'john',
+                sortedActions: undefined,
+            });
+
+            // Then all matching recent attendees are shown, not just the first 5
+            expect(results.recentReports.length).toBe(8);
+        });
+    });
+
     describe('policy parameter passing', () => {
         it('createOptionList should accept policiesCollection parameter', () => {
             const result = createOptionList(PERSONAL_DETAILS, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS, allPolicies, MOCK_REPORT_ATTRIBUTES_DERIVED);
diff --git a/tests/unit/PolicyUtilsTest.ts b/tests/unit/PolicyUtilsTest.ts
index 02c76022fb8f..bfed2eda7ec7 100644
--- a/tests/unit/PolicyUtilsTest.ts
+++ b/tests/unit/PolicyUtilsTest.ts
@@ -34,6 +34,7 @@ import {
     hasConfiguredRules,
     hasDependentTags,
     hasDynamicExternalWorkflow,
+    hasEligibleActiveAdminFromWorkspaces,
     hasIndependentTags,
     hasOnlyPersonalPolicies,
     hasOtherControlWorkspaces,
@@ -128,6 +129,8 @@ const employeeEmail = 'employee@test.com';
 const adminEmail = 'admin@test.com';
 const categoryApprover1Email = 'categoryapprover1@test.com';
 const approverEmail = 'approver@test.com';
+const guideEmail = 'guide@expensify.com';
+const guideAccountID = 9;
 
 const personalDetails: PersonalDetailsList = {
     '1': {
@@ -162,6 +165,10 @@ const personalDetails: PersonalDetailsList = {
         accountID: approverAccountID,
         login: approverEmail,
     },
+    '9': {
+        accountID: guideAccountID,
+        login: guideEmail,
+    },
 };
 
 const rules = {
@@ -1754,6 +1761,108 @@ describe('PolicyUtils', () => {
             const result = getEligibleBankAccountShareRecipients(policies, adminEmail, bankAccountID);
             expect(result).toHaveLength(1);
         });
+        it('should not return Expensify guide when policy owner is not Expensify team', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'normalowner@test.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = getEligibleBankAccountShareRecipients(policies, adminEmail, '1');
+            expect(result).toHaveLength(0);
+        });
+        it('should return Expensify guide when policy owner is Expensify team', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'owner@expensify.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = getEligibleBankAccountShareRecipients(policies, adminEmail, '1');
+            expect(result).toHaveLength(1);
+        });
+        it('should return Expensify guide when current user is Expensify team', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'normalowner@test.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = getEligibleBankAccountShareRecipients(policies, 'someone@expensify.com', '1');
+            expect(result).toHaveLength(1);
+        });
+    });
+
+    describe('hasEligibleActiveAdminFromWorkspaces', () => {
+        beforeEach(() => {
+            wrapOnyxWithWaitForBatchedUpdates(Onyx);
+            Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails);
+        });
+        afterEach(async () => {
+            await Onyx.clear();
+            await waitForBatchedUpdatesWithAct();
+        });
+        it('should return false when the only admin is an Expensify guide on a non-Expensify policy', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'normalowner@test.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = hasEligibleActiveAdminFromWorkspaces(policies, adminEmail, '1');
+            expect(result).toBe(false);
+        });
+        it('should return true when there is a non-guide admin', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'normalowner@test.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                        [approverEmail]: {email: approverEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = hasEligibleActiveAdminFromWorkspaces(policies, adminEmail, '1');
+            expect(result).toBe(true);
+        });
+        it('should return true when the guide is on an Expensify-owned policy', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'owner@expensify.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = hasEligibleActiveAdminFromWorkspaces(policies, adminEmail, '1');
+            expect(result).toBe(true);
+        });
     });
 
     describe('hasOtherControlWorkspaces', () => {
diff --git a/tests/unit/RefreshCardFeedConnectionPageTest.tsx b/tests/unit/RefreshCardFeedConnectionPageTest.tsx
index 8796f542a701..44141978541f 100644
--- a/tests/unit/RefreshCardFeedConnectionPageTest.tsx
+++ b/tests/unit/RefreshCardFeedConnectionPageTest.tsx
@@ -10,6 +10,11 @@ import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
 // Bypass the HOC and render the inner component directly
 jest.mock('@pages/workspace/withPolicyAndFullscreenLoading', () => (Component: React.ComponentType) => Component);
 
+jest.mock('@pages/workspace/AccessOrNotFoundWrapper', () => ({
+    __esModule: true,
+    default: ({children}: {children: React.ReactNode}) => children,
+}));
+
 const mockCloseRHPFlow = jest.fn();
 
 jest.mock('@hooks/useCardFeeds', () => ({
diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts
index c3627eaa6cfe..5c8932c64831 100644
--- a/tests/unit/ReportActionsUtilsTest.ts
+++ b/tests/unit/ReportActionsUtilsTest.ts
@@ -18,6 +18,7 @@ import {
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
     getCardIssuedMessage,
+    getCategoryTaxRateMessage,
     getCombinedReportActions,
     getCompanyAddressUpdateMessage,
     getCreatedReportForUnapprovedTransactionsMessage,
@@ -4031,6 +4032,75 @@ describe('ReportActionsUtils', () => {
             const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
             expect(actual).toBe('renamed the Distance rate "Default Rate" to "Custom Rate"');
         });
+
+        it('should return the correct message when a start date is set on a rate without dates', () => {
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE> = {
+                reportActionID: '1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE,
+                created: '',
+                originalMessage: {
+                    customUnitName: 'Distance',
+                    customUnitRateName: 'Default Rate',
+                    updatedField: 'dateRange',
+                    newStartDate: '2026-04-01',
+                },
+            };
+            const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
+            expect(actual).toBe('updated the distance rate "Default Rate" to apply from April 1, 2026 (previously for all dates)');
+        });
+
+        it('should return the correct message when both start and end dates are changed', () => {
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE> = {
+                reportActionID: '1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE,
+                created: '',
+                originalMessage: {
+                    customUnitName: 'Distance',
+                    customUnitRateName: 'Default Rate',
+                    updatedField: 'dateRange',
+                    newStartDate: '2026-04-01',
+                    newEndDate: '2026-05-31',
+                    oldStartDate: '2026-03-01',
+                    oldEndDate: '2026-04-30',
+                },
+            };
+            const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
+            expect(actual).toBe('updated the distance rate "Default Rate" to apply from April 1, 2026 - May 31, 2026 (previously March 1, 2026 - April 30, 2026)');
+        });
+
+        it('should return the correct message when an end date is changed', () => {
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE> = {
+                reportActionID: '1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE,
+                created: '',
+                originalMessage: {
+                    customUnitName: 'Distance',
+                    customUnitRateName: 'Default Rate',
+                    updatedField: 'dateRange',
+                    newEndDate: '2026-05-31',
+                    oldEndDate: '2026-04-30',
+                },
+            };
+            const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
+            expect(actual).toBe('updated the distance rate "Default Rate" to apply until May 31, 2026 (previously until April 30, 2026)');
+        });
+
+        it('should return the correct message when all dates are cleared', () => {
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE> = {
+                reportActionID: '1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE,
+                created: '',
+                originalMessage: {
+                    customUnitName: 'Distance',
+                    customUnitRateName: 'Default Rate',
+                    updatedField: 'dateRange',
+                    oldStartDate: '2026-03-01',
+                    oldEndDate: '2026-04-30',
+                },
+            };
+            const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
+            expect(actual).toBe('updated the distance rate "Default Rate" to apply for all dates (previously March 1, 2026 - April 30, 2026)');
+        });
     });
 
     describe('didMessageMentionCurrentUser', () => {
@@ -4540,6 +4610,46 @@ describe('ReportActionsUtils', () => {
         });
     });
 
+    describe('getCategoryTaxRateMessage', () => {
+        it('should render the changed-tax-rate message with both name and percentage on each side', () => {
+            const action = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                reportActionID: '1',
+                created: '',
+                originalMessage: {
+                    categoryName: 'Office Supplies',
+                    oldTaxName: 'Tax Exempt',
+                    oldTaxPercentage: '0%',
+                    newTaxName: 'Tax Rate 1',
+                    newTaxPercentage: '5%',
+                },
+                message: [],
+            } as ReportAction;
+
+            const result = getCategoryTaxRateMessage(translateLocal, action);
+            expect(result).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Tax Exempt (0%)")');
+        });
+
+        it('should drop the parens on the side with an empty percentage (e.g. previous tax was deleted)', () => {
+            const action = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                reportActionID: '1',
+                created: '',
+                originalMessage: {
+                    categoryName: 'Office Supplies',
+                    oldTaxName: 'Deleted Tax Rate',
+                    oldTaxPercentage: '',
+                    newTaxName: 'Tax Rate 1',
+                    newTaxPercentage: '5%',
+                },
+                message: [],
+            } as ReportAction;
+
+            const result = getCategoryTaxRateMessage(translateLocal, action);
+            expect(result).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Deleted Tax Rate")');
+        });
+    });
+
     describe('getMccGroupCategoryMessage', () => {
         it('should render the friendly MCC group label that the emitter already resolved', () => {
             const action = {
diff --git a/tests/unit/ReportNameUtilsTest.ts b/tests/unit/ReportNameUtilsTest.ts
index 233536b66095..0c52047d6c47 100644
--- a/tests/unit/ReportNameUtilsTest.ts
+++ b/tests/unit/ReportNameUtilsTest.ts
@@ -648,6 +648,46 @@ describe('ReportNameUtils', () => {
             expect(disabledName).toBe('disabled the company card purchases requirement');
         });
 
+        test('UPDATE_CATEGORY_TAX_RATE parent action renders the rendered category default tax rate change', () => {
+            const thread: Report = createWorkspaceThread(160);
+            const parentAction: ReportAction = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                reportActionID: String(thread.parentReportActionID),
+                message: [],
+                created: '',
+                lastModified: '',
+                actorAccountID: 1,
+                person: [],
+                originalMessage: {
+                    categoryName: 'Office Supplies',
+                    oldTaxName: 'Tax Exempt',
+                    oldTaxPercentage: '0%',
+                    newTaxName: 'Tax Rate 1',
+                    newTaxPercentage: '5%',
+                },
+            } as unknown as ReportAction;
+
+            const parentId = String(thread.parentReportID);
+            const actionId = String(thread.parentReportActionID);
+            const reportActionsCollection: Record<string, ReportActions> = {
+                [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentId}`]: {
+                    [actionId]: parentAction,
+                },
+            };
+
+            const name = computeReportName(
+                thread,
+                emptyCollections.reports,
+                emptyCollections.policies,
+                undefined,
+                undefined,
+                participantsPersonalDetails,
+                reportActionsCollection,
+                currentUserAccountID,
+            );
+            expect(name).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Tax Exempt (0%)")');
+        });
+
         test('DELETE_CARD_FEED parent action', () => {
             const thread: Report = createWorkspaceThread(101);
             const parentAction: ReportAction = {
diff --git a/tests/unit/ReportSelectorTest.ts b/tests/unit/ReportSelectorTest.ts
index fdcc0123aa53..4483e14d2bb1 100644
--- a/tests/unit/ReportSelectorTest.ts
+++ b/tests/unit/ReportSelectorTest.ts
@@ -80,4 +80,20 @@ describe('policyChatRoomsSelector', () => {
         const result = policyChatRoomsSelector(policyID, archivedSet)(reports);
         expect(result).toEqual([policyAdmins]);
     });
+
+    it('excludes rooms the user has left (closed reports)', () => {
+        const leftRoom = {
+            reportID: '1',
+            policyID,
+            chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
+            statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+            stateNum: CONST.REPORT.STATE_NUM.APPROVED,
+        } as Report;
+        const reports = {
+            [`${REPORT_KEY_PREFIX}1`]: leftRoom,
+            [`${REPORT_KEY_PREFIX}2`]: policyAdmins,
+        };
+        const result = policyChatRoomsSelector(policyID, emptyArchivedSet)(reports);
+        expect(result).toEqual([policyAdmins]);
+    });
 });
diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts
index 85c94e02fe0f..3e4a4ba15684 100644
--- a/tests/unit/ReportUtilsTest.ts
+++ b/tests/unit/ReportUtilsTest.ts
@@ -21,7 +21,6 @@ import type {FormulaContext} from '@libs/Formula';
 import getBase62ReportID from '@libs/getBase62ReportID';
 import {translate} from '@libs/Localize';
 import Log from '@libs/Log';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import getReportURLForCurrentContext from '@libs/Navigation/helpers/getReportURLForCurrentContext';
 import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
 import Navigation from '@libs/Navigation/Navigation';
@@ -109,7 +108,6 @@ import {
     getPolicyName,
     getReasonAndReportActionThatRequiresAttention,
     getReportActionWithSmartscanError,
-    getReportFieldMaps,
     getReportFieldsByPolicyID,
     getReportIDFromLink,
     getReportOrDraftReport,
@@ -166,6 +164,7 @@ import {
     shouldReportBeInOptionList,
     shouldReportShowSubscript,
     shouldShowFlagComment,
+    shouldShowMarkAsDone,
     sortIconsByName,
     sortOutstandingReportsBySelected,
     temporary_getMoneyRequestOptions,
@@ -175,7 +174,7 @@ import {buildOptimisticTransaction} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import IntlStore from '@src/languages/IntlStore';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type {
     BankAccountList,
     Beta,
@@ -10423,26 +10422,17 @@ describe('ReportUtils', () => {
             const policyID = '123456';
             await Onyx.set(ONYXKEYS.SESSION, {email: currentUserEmail, accountID: currentUserAccountID});
 
-            const policyWithoutCurrentUser: Policy = {
-                ...createRandomPolicy(1),
-                id: policyID,
-                employeeList: {
-                    'employee@test.com': {
-                        role: CONST.POLICY.ROLE.USER,
-                        errors: {},
-                    },
-                },
-            };
+            // policy.role holds the current user's own role and is synced for every workspace they belong to,
+            // even when employeeList has not loaded (the roster is only fully synced for the active workspace).
+            // A non-member therefore has no role, so membership is determined from policy.role.
+            const policyWithoutCurrentUser: Policy = {...createRandomPolicy(1), id: policyID, employeeList: {}};
+            delete (policyWithoutCurrentUser as Partial<Policy>).role;
 
             const policyWithCurrentUser: Policy = {
                 ...createRandomPolicy(2),
                 id: policyID,
-                employeeList: {
-                    [currentUserEmail]: {
-                        role: CONST.POLICY.ROLE.USER,
-                        errors: {},
-                    },
-                },
+                role: CONST.POLICY.ROLE.USER,
+                employeeList: {},
             };
 
             const restrictedReport: Report = {
@@ -14632,106 +14622,6 @@ describe('ReportUtils', () => {
         });
     });
 
-    describe('getReportFieldMaps', () => {
-        it('should read invoice field values from report name value pairs keyed by raw field ID', async () => {
-            const reportID = 'getReportFieldMapsRawKey';
-            const report: Report = {
-                reportID,
-                policyID: '1',
-                type: CONST.REPORT.TYPE.INVOICE,
-                fieldList: {},
-            };
-            const policyFieldList: Record<string, PolicyReportField> = {
-                expensify_field_id_LIST: {
-                    type: 'dropdown',
-                    values: ['policy default'],
-                    disabledOptions: [false],
-                    fieldID: 'field_id_LIST',
-                    name: 'Client',
-                    defaultValue: 'policy default',
-                    orderWeight: 0,
-                    deletable: true,
-                    keys: [],
-                    externalIDs: [],
-                    isTax: false,
-                    target: CONST.REPORT_FIELD_TARGETS.INVOICE,
-                },
-            };
-            const reportNameValuePairField: PolicyReportField = {
-                type: 'dropdown',
-                values: ['policy default'],
-                disabledOptions: [false],
-                fieldID: 'field_id_LIST',
-                name: 'Client',
-                defaultValue: 'policy default',
-                orderWeight: 0,
-                deletable: true,
-                keys: [],
-                externalIDs: [],
-                isTax: false,
-                value: 'persisted value',
-                target: CONST.REPORT_FIELD_TARGETS.INVOICE,
-            };
-
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report);
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`, Object.fromEntries([['field_id_LIST', reportNameValuePairField]]));
-
-            const {fieldValues, fieldsByName} = getReportFieldMaps(report, policyFieldList);
-
-            expect(fieldValues.client).toBe('persisted value');
-            expect(fieldsByName.client.value).toBe('persisted value');
-        });
-
-        it('should not read expense field values from report name value pairs', async () => {
-            const reportID = 'getReportFieldMapsExpenseField';
-            const report: Report = {
-                reportID,
-                policyID: '1',
-                type: CONST.REPORT.TYPE.EXPENSE,
-                fieldList: {},
-            };
-            const policyFieldList: Record<string, PolicyReportField> = {
-                expensify_field_id_LIST: {
-                    type: 'dropdown',
-                    values: ['policy default'],
-                    disabledOptions: [false],
-                    fieldID: 'field_id_LIST',
-                    name: 'Client',
-                    defaultValue: 'policy default',
-                    orderWeight: 0,
-                    deletable: true,
-                    keys: [],
-                    externalIDs: [],
-                    isTax: false,
-                    target: CONST.REPORT_FIELD_TARGETS.EXPENSE,
-                },
-            };
-            const reportNameValuePairField: PolicyReportField = {
-                type: 'dropdown',
-                values: ['policy default'],
-                disabledOptions: [false],
-                fieldID: 'field_id_LIST',
-                name: 'Client',
-                defaultValue: 'policy default',
-                orderWeight: 0,
-                deletable: true,
-                keys: [],
-                externalIDs: [],
-                isTax: false,
-                value: 'persisted value',
-                target: CONST.REPORT_FIELD_TARGETS.EXPENSE,
-            };
-
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report);
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`, Object.fromEntries([['field_id_LIST', reportNameValuePairField]]));
-
-            const {fieldValues, fieldsByName} = getReportFieldMaps(report, policyFieldList);
-
-            expect(fieldValues.client).toBe('policy default');
-            expect(fieldsByName.client.value).toBeUndefined();
-        });
-    });
-
     describe('canEditReportTitle', () => {
         const getTitleField = (deletable: boolean): PolicyReportField => ({
             fieldID: CONST.REPORT_FIELD_TITLE_FIELD_ID,
@@ -15821,17 +15711,7 @@ describe('ReportUtils', () => {
 
                 // Then it should navigate to the category step
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
-                        ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(
-                            CONST.IOU.ACTION.CATEGORIZE,
-                            CONST.IOU.TYPE.SUBMIT,
-                            transaction.transactionID,
-                            policyExpenseReport.reportID,
-                            undefined,
-                            true,
-                        ),
-                    ),
+                    ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
                 );
             });
 
@@ -15874,17 +15754,7 @@ describe('ReportUtils', () => {
 
                 // Then it should automatically pick the available policy and navigate to the category step
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
-                        ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(
-                            CONST.IOU.ACTION.CATEGORIZE,
-                            CONST.IOU.TYPE.SUBMIT,
-                            transaction.transactionID,
-                            policyExpenseReport.reportID,
-                            undefined,
-                            true,
-                        ),
-                    ),
+                    ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
                 );
             });
 
@@ -15914,16 +15784,15 @@ describe('ReportUtils', () => {
 
                 // Then it should navigate to the upgrade page because no policies were found to categorize with
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                            action: CONST.IOU.ACTION.CATEGORIZE,
-                            iouType: CONST.IOU.TYPE.SUBMIT,
-                            transactionID: transaction.transactionID,
-                            reportID: '1',
-                            upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                            shouldSubmitExpense: true,
-                        }),
-                    ),
+                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                        action: CONST.IOU.ACTION.CATEGORIZE,
+                        iouType: CONST.IOU.TYPE.SUBMIT,
+                        transactionID: transaction.transactionID,
+                        reportID: '1',
+                        backTo: '',
+                        upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                        shouldSubmitExpense: true,
+                    }),
                 );
             });
 
@@ -15966,16 +15835,15 @@ describe('ReportUtils', () => {
 
                 // Then it should navigate to the upgrade page because it's ambiguous which policy to use
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                            action: CONST.IOU.ACTION.CATEGORIZE,
-                            iouType: CONST.IOU.TYPE.SUBMIT,
-                            transactionID: transaction.transactionID,
-                            reportID: '1',
-                            upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                            shouldSubmitExpense: true,
-                        }),
-                    ),
+                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                        action: CONST.IOU.ACTION.CATEGORIZE,
+                        iouType: CONST.IOU.TYPE.SUBMIT,
+                        transactionID: transaction.transactionID,
+                        reportID: '1',
+                        backTo: '',
+                        upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                        shouldSubmitExpense: true,
+                    }),
                 );
             });
 
@@ -16062,17 +15930,7 @@ describe('ReportUtils', () => {
                 // Then it should NOT navigate to restricted action page, but to category step
                 expect(Navigation.navigate).not.toHaveBeenCalledWith(ROUTES.RESTRICTED_ACTION.getRoute(activePolicy.id));
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
-                        ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(
-                            CONST.IOU.ACTION.CATEGORIZE,
-                            CONST.IOU.TYPE.SUBMIT,
-                            transaction.transactionID,
-                            policyExpenseReport.reportID,
-                            undefined,
-                            true,
-                        ),
-                    ),
+                    ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
                 );
             });
 
@@ -18604,3 +18462,136 @@ describe('ReportUtils', () => {
         });
     });
 });
+describe('shouldShowMarkAsDone', () => {
+    const policyID = '1';
+    const otherAccountID = 42;
+
+    it('should return false when user is not a track-intent user', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: false, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when policy is not submit-and-close', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.BASIC,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when user does not own the report', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: otherAccountID,
+            managerID: otherAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when next approver is different from owner', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: otherAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when isTrackIntentUser is undefined', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: undefined, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when report is undefined', () => {
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report: undefined, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when policy is undefined', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: undefined})).toBe(false);
+    });
+
+    it('should return true when user is track-intent, policy is submit-and-close, user owns report, and submits to self', async () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+            owner: currentUserEmail,
+        } as Policy;
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, testPolicy);
+        await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {
+            [currentUserAccountID]: {accountID: currentUserAccountID, login: currentUserEmail},
+        });
+        await waitForBatchedUpdates();
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: testPolicy})).toBe(true);
+    });
+});
diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts
index dd0028022f2a..a9de9bc5ff47 100644
--- a/tests/unit/Search/SearchUIUtilsTest.ts
+++ b/tests/unit/Search/SearchUIUtilsTest.ts
@@ -3093,6 +3093,108 @@ describe('SearchUIUtils', () => {
             ).toStrictEqual(transactionCardGroupListItems);
         });
 
+        it('should label personal card groups as "Personal card" while keeping company-feed names for company cards and "Deleted feed" for removed feeds', () => {
+            const personalCardID = 40404040;
+            const csvPersonalCardID = 50505050;
+            const deletedFeedCardID = 60606060;
+            const workspaceFeedCardID = 70707070;
+
+            const data: OnyxTypes.SearchResults['data'] = {
+                personalDetailsList: {},
+                [`${CONST.SEARCH.GROUP_PREFIX}${personalCardID}` as const]: {
+                    accountID: adminAccountID,
+                    bank: CONST.PERSONAL_CARDS.BANK_NAME.CHASE,
+                    cardID: personalCardID,
+                    cardName: 'Personal Chase',
+                    count: 1,
+                    currency: 'USD',
+                    lastFourPAN: '1111',
+                    total: 10,
+                },
+                [`${CONST.SEARCH.GROUP_PREFIX}${csvPersonalCardID}` as const]: {
+                    accountID: adminAccountID,
+                    bank: CONST.PERSONAL_CARDS.BANK_NAME.CSV,
+                    cardID: csvPersonalCardID,
+                    cardName: 'CSV import',
+                    count: 1,
+                    currency: 'USD',
+                    lastFourPAN: '2222',
+                    total: 20,
+                },
+                [`${CONST.SEARCH.GROUP_PREFIX}${deletedFeedCardID}` as const]: {
+                    accountID: adminAccountID,
+                    bank: CONST.BANK_NAMES.CITIBANK,
+                    cardID: deletedFeedCardID,
+                    cardName: 'Removed company card',
+                    count: 1,
+                    currency: 'USD',
+                    lastFourPAN: '3333',
+                    total: 30,
+                },
+                [`${CONST.SEARCH.GROUP_PREFIX}${workspaceFeedCardID}` as const]: {
+                    accountID: adminAccountID,
+                    bank: CONST.COMPANY_CARD.FEED_BANK_NAME.VISA,
+                    cardID: workspaceFeedCardID,
+                    cardName: 'Workspace Visa',
+                    count: 1,
+                    currency: 'USD',
+                    lastFourPAN: '4444',
+                    total: 40,
+                },
+            };
+
+            // Personal cards have no fundID; the deleted company feed card keeps its fundID so it is not personal.
+            // The workspace-feed company card also has no fundID (company-feed cards never carry one), so it must be
+            // distinguished from a personal card via the non-personal card list rather than `isPersonalCard` alone.
+            const cardList = {
+                [personalCardID]: {cardID: personalCardID, bank: CONST.PERSONAL_CARDS.BANK_NAME.CHASE},
+                [csvPersonalCardID]: {cardID: csvPersonalCardID, bank: CONST.PERSONAL_CARDS.BANK_NAME.CSV, fundID: '123'},
+                [deletedFeedCardID]: {cardID: deletedFeedCardID, bank: CONST.BANK_NAMES.CITIBANK, fundID: '456'},
+                [workspaceFeedCardID]: {cardID: workspaceFeedCardID, bank: CONST.COMPANY_CARD.FEED_BANK_NAME.VISA},
+            } as unknown as OnyxTypes.CardList;
+
+            // The non-personal list keeps every company/workspace-feed card while filtering personal cards out.
+            const nonPersonalAndWorkspaceCardList = {
+                [workspaceFeedCardID]: {cardID: workspaceFeedCardID, bank: CONST.COMPANY_CARD.FEED_BANK_NAME.VISA},
+            } as unknown as OnyxTypes.CardList;
+
+            // The VISA feed exists in the workspace, so it should resolve to a real feed name (not "Deleted feed").
+            const cardFeeds = {
+                policy1: {
+                    settings: {
+                        companyCards: {
+                            [CONST.COMPANY_CARD.FEED_BANK_NAME.VISA]: {} as CustomCardFeedData,
+                        },
+                    },
+                } as OnyxTypes.CardFeeds,
+            };
+
+            const [sections] = SearchUIUtils.getSections({
+                type: CONST.SEARCH.DATA_TYPES.EXPENSE,
+                data,
+                currentAccountID: adminAccountID,
+                currentUserEmail: '',
+                translate: translateLocal,
+                formatPhoneNumber,
+                bankAccountList: {},
+                groupBy: CONST.SEARCH.GROUP_BY.CARD,
+                cardFeeds,
+                cardList,
+                nonPersonalAndWorkspaceCardList,
+                conciergeReportID: undefined,
+                convertToDisplayString,
+            }) as [TransactionCardGroupListItemType[], number, boolean];
+
+            const feedNameByCardID = new Map(sections.map((section) => [section.cardID, section.formattedFeedName]));
+
+            expect(feedNameByCardID.get(personalCardID)).toBe('Personal card');
+            expect(feedNameByCardID.get(csvPersonalCardID)).toBe('Personal card');
+            expect(feedNameByCardID.get(deletedFeedCardID)).toBe('Deleted feed');
+            // A workspace-feed company card without a fundID must NOT be mislabeled as a personal card.
+            expect(feedNameByCardID.get(workspaceFeedCardID)).not.toBe('Personal card');
+            expect(feedNameByCardID.get(workspaceFeedCardID)).not.toBe('Deleted feed');
+        });
+
         it('should return getWithdrawalIDSections result when type is EXPENSE and groupBy is withdrawal-id', () => {
             expect(
                 SearchUIUtils.getSections({
diff --git a/tests/unit/SearchAutocompleteListTest.tsx b/tests/unit/SearchAutocompleteListTest.tsx
index 16b77aa90ce3..5f4cfc2e4973 100644
--- a/tests/unit/SearchAutocompleteListTest.tsx
+++ b/tests/unit/SearchAutocompleteListTest.tsx
@@ -9,9 +9,11 @@ import SearchRouter from '@components/Search/SearchRouter/SearchRouter';
 import type {PrivateIsArchivedMap} from '@hooks/usePrivateIsArchivedMap';
 import type * as OptionsListUtilsModule from '@libs/OptionsListUtils';
 import {createOptionList} from '@libs/OptionsListUtils';
+import Navigation from '@navigation/Navigation';
 import ComposeProviders from '@src/components/ComposeProviders';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import type {PersonalDetails, Report} from '@src/types/onyx';
 import createCollection from '../utils/collections/createCollection';
 import createPersonalDetails from '../utils/collections/personalDetails';
@@ -419,5 +421,46 @@ describe('SearchAutocompleteList', () => {
             // NewServer should appear after the local results (in the server section)
             expect(relevantOrder.indexOf('Charlie Report')).toBeLessThan(relevantOrder.indexOf('NewServer Report'));
         });
+
+        // Regression test for https://github.com/Expensify/App/issues/93009: after the two-section switcher was
+        // introduced, the first matched chat was no longer highlighted because the highlight focused a fixed flat
+        // index that now lands on the "Recent chats" section header row instead of the first result. As a result
+        // pressing Enter ran a text search instead of opening the chat. The fix focuses the header-aware index of
+        // the first result.
+        it('should focus the first matched chat so submitting opens it instead of running a search', async () => {
+            const recentSearches: Record<string, {query: string; timestamp: string}> = {};
+            recentSearches['2024-01-01T00:00:00'] = {query: 'type:expense', timestamp: '2024-01-01T00:00:00'};
+
+            await waitForBatchedUpdates();
+            await Onyx.multiSet({
+                ...mockedReports,
+                [ONYXKEYS.PERSONAL_DETAILS_LIST]: mockedPersonalDetails,
+                [ONYXKEYS.BETAS]: mockedBetas,
+                [ONYXKEYS.RECENT_SEARCHES]: recentSearches,
+            });
+
+            render(<SearchRouterWrapper />);
+            await flushAllUpdates();
+
+            // Wait for the first recent chat row (not just the header) to render so the highlight has a target.
+            await waitFor(() => {
+                expect(screen.getByText('Recent chats')).toBeTruthy();
+                expect(screen.getByText('Alice Report')).toBeTruthy();
+            });
+
+            // Type a query that matches the first recent chat ("Alice Report") as a whole word.
+            // The header-aware highlight effect should move focus onto that result row, not a section header.
+            const textInput = screen.getByTestId('search-autocomplete-text-input');
+            fireEvent.changeText(textInput, 'Alice');
+            await flushAllUpdates();
+
+            // Submitting (Enter) should open the focused chat rather than run a text search. The highlight effect
+            // runs asynchronously, so poll the submit until focus settles on the result. With the bug present the
+            // first row is never highlighted, so submit always runs a text search and this never becomes true.
+            await waitFor(() => {
+                fireEvent(textInput, 'submitEditing');
+                expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute('101'));
+            });
+        });
     });
 });
diff --git a/tests/unit/SequentialQueueTest.ts b/tests/unit/SequentialQueueTest.ts
index be9dc358b85b..67adffd451ad 100644
--- a/tests/unit/SequentialQueueTest.ts
+++ b/tests/unit/SequentialQueueTest.ts
@@ -1,5 +1,6 @@
 import Onyx from 'react-native-onyx';
 import type {OnyxKey, OnyxUpdate} from 'react-native-onyx';
+import * as NetworkState from '@libs/NetworkState';
 import {clear as clearPersistedRequests, getAll, getLength, getOngoingRequest, updateOngoingRequest} from '@userActions/PersistedRequests';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -7,6 +8,7 @@ import * as SequentialQueue from '../../src/libs/Network/SequentialQueue';
 import * as RequestModule from '../../src/libs/Request';
 import type Request from '../../src/types/onyx/Request';
 import type {AnyRequest, ConflictActionData} from '../../src/types/onyx/Request';
+import type {MockFetch} from '../utils/TestHelper';
 import * as TestHelper from '../utils/TestHelper';
 import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
 
@@ -15,13 +17,15 @@ const request: Request<'userMetadata'> = {
     successData: [{key: 'userMetadata', onyxMethod: 'set', value: {accountID: 1234}}],
     failureData: [{key: 'userMetadata', onyxMethod: 'set', value: {}}],
 };
+let mockFetch: MockFetch;
 beforeAll(() => {
     Onyx.init({
         keys: ONYXKEYS,
     });
 });
 beforeEach(() => {
-    global.fetch = TestHelper.getGlobalFetchMock();
+    mockFetch = TestHelper.createGlobalFetchMock();
+    global.fetch = mockFetch;
     return Onyx.clear()
         .then(() => SequentialQueue.clearQueueFlushedData())
         .then(waitForBatchedUpdates);
@@ -38,29 +42,103 @@ describe('SequentialQueue', () => {
         expect(getLength()).toBe(2);
     });
 
-    it('should push two requests with conflict resolution and replace', () => {
-        SequentialQueue.push(request);
-        const requestWithConflictResolution: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: (persistedRequests) => {
-                // should be one instance of ReconnectApp, get the index to replace it later
-                const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
-                if (index === -1) {
-                    return {conflictAction: {type: 'push'}};
-                }
+    it('should resolve waitForIdle without flushing when the network goes offline during persist', async () => {
+        // push()'s sync prelude marks isReadyPromise pending while online, then awaits the disk
+        // write. If the network flips offline during that await, flush() would early-return on its
+        // offline guard without resolving isReadyPromise — leaving waitForIdle() (READs) hung until
+        // an unrelated reconnect. push() must instead resolve isReadyPromise and skip flushing.
+        const offlineSpy = jest.spyOn(NetworkState, 'getIsOffline').mockReturnValue(false);
+        let timeoutId: ReturnType<typeof setTimeout> | undefined;
+        try {
+            // Kick off the push while "online": the synchronous prelude runs up to `await persistencePromise`.
+            const pushPromise = SequentialQueue.push(request);
 
-                return {
-                    conflictAction: {type: 'replace', index},
+            // Flip offline while the awaited disk write is still pending.
+            offlineSpy.mockReturnValue(true);
+
+            await pushPromise;
+
+            // The request is still persisted — not flushed, not dropped.
+            expect(getLength()).toBe(1);
+
+            // waitForIdle() must resolve rather than hang.
+            const idleOrTimeout = await Promise.race([
+                SequentialQueue.waitForIdle().then(() => 'resolved' as const),
+                new Promise<'timeout'>((resolve) => {
+                    timeoutId = setTimeout(() => resolve('timeout'), 1000);
+                }),
+            ]);
+            expect(idleOrTimeout).toBe('resolved');
+        } finally {
+            if (timeoutId) {
+                clearTimeout(timeoutId);
+            }
+            offlineSpy.mockRestore();
+        }
+    });
+
+    it('should not block the queue when a disk write fails during persist', async () => {
+        // If a conflict-resolution disk write rejects (storage full / corruption), push() must not throw
+        // or strand isReadyPromise — the request should still flush and waitForIdle() should resolve.
+        const originalSet = Onyx.set.bind(Onyx);
+
+        mockFetch.pause();
+        try {
+            await SequentialQueue.push({command: 'OpenReport'}); // occupies ongoingRequest
+            await waitForBatchedUpdates();
+            await SequentialQueue.push(request); // ReconnectApp stacks in the queue
+
+            // Fail the conflict-resolution persist (a raw Onyx.set on the persisted-requests key).
+            const setMock = jest
+                .spyOn(Onyx, 'set')
+                .mockImplementation((key, value) => (key === ONYXKEYS.PERSISTED_REQUESTS ? Promise.reject(new Error('simulated disk-write failure')) : originalSet(key, value)));
+            try {
+                const replacing: Request<never> = {
+                    command: 'ReconnectApp',
+                    data: {accountID: 56789},
+                    checkAndFixConflictingRequest: (persistedRequests) => {
+                        const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
+                        return {conflictAction: index === -1 ? {type: 'push'} : {type: 'replace', index}};
+                    },
                 };
-            },
-        };
-        SequentialQueue.push(requestWithConflictResolution);
-        expect(getLength()).toBe(1);
-        // We know there is only one request and it's ongoing.
-        // We can get it and verify that the ongoing request is the second one.
-        const ongoingRequest = getOngoingRequest();
-        expect(ongoingRequest?.data?.accountID).toBe(56789);
+                // The failed disk write must not reject the caller.
+                await expect(SequentialQueue.push(replacing)).resolves.toBeUndefined();
+            } finally {
+                setMock.mockRestore();
+            }
+        } finally {
+            await mockFetch.resume();
+        }
+
+        // The queue still drains and READs unblock — a hang here would fail the test by timing out.
+        await SequentialQueue.waitForIdle();
+        expect(getLength()).toBe(0);
+    });
+
+    it('should push two requests with conflict resolution and replace', async () => {
+        // Pause the queue so `process()` does not consume the first request before
+        // the conflict resolver runs. Under persist-before-fire `push()` is async,
+        // so we await both pushes and then assert on the on-disk queue directly.
+        SequentialQueue.pause();
+        try {
+            await SequentialQueue.push(request);
+            const requestWithConflictResolution: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: (persistedRequests) => {
+                    const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
+                    if (index === -1) {
+                        return {conflictAction: {type: 'push'}};
+                    }
+                    return {conflictAction: {type: 'replace', index}};
+                },
+            };
+            await SequentialQueue.push(requestWithConflictResolution);
+            expect(getLength()).toBe(1);
+            expect(getAll().at(0)?.data?.accountID).toBe(56789);
+        } finally {
+            SequentialQueue.unpause();
+        }
     });
 
     it('should push two requests with conflict resolution and push', () => {
@@ -90,108 +168,112 @@ describe('SequentialQueue', () => {
     });
 
     it('should add a new request even if a similar one is ongoing', async () => {
-        // .push at the end flush the queue
-        SequentialQueue.push(request);
-
-        // wait for Onyx.connect execute the callback and start processing the queue
-        await Promise.resolve();
-
-        const requestWithConflictResolution: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: (persistedRequests) => {
-                // should be one instance of ReconnectApp, get the index to replace it later
-                const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
-                if (index === -1) {
-                    return {conflictAction: {type: 'push'}};
-                }
-
-                return {
-                    conflictAction: {type: 'replace', index},
-                };
-            },
-        };
-
-        SequentialQueue.push(requestWithConflictResolution);
-
-        const ongoingRequest = getOngoingRequest();
-        expect(ongoingRequest?.data?.accountID).toBe(56789);
-    });
-
-    it('should replace request request in queue while a similar one is ongoing', async () => {
-        // .push at the end flush the queue
-        SequentialQueue.push(request);
-
-        // wait for Onyx.connect execute the callback and start processing the queue
-        await Promise.resolve();
-
-        const conflictResolver = <TKey extends OnyxKey>(persistedRequests: Array<Request<TKey>>): ConflictActionData => {
-            // should be one instance of ReconnectApp, get the index to replace it later
-            const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
-            if (index === -1) {
-                return {conflictAction: {type: 'push'}};
-            }
-
-            return {
-                conflictAction: {type: 'replace', index},
+        // Pause fetch so the first request lands as `ongoingRequest` but never completes.
+        // The conflict checker on push 2 inspects the persisted queue (which excludes the
+        // ongoing request), so it cannot find a 'ReconnectApp' to replace and falls back
+        // to 'push'. The new request is therefore added to the queue.
+        mockFetch.pause();
+        try {
+            await SequentialQueue.push(request);
+            await waitForBatchedUpdates();
+            expect(getOngoingRequest()?.command).toBe('ReconnectApp');
+
+            const requestWithConflictResolution: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: (persistedRequests) => {
+                    const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
+                    if (index === -1) {
+                        return {conflictAction: {type: 'push'}};
+                    }
+                    return {conflictAction: {type: 'replace', index}};
+                },
             };
-        };
 
-        const requestWithConflictResolution: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: conflictResolver,
-        };
+            await SequentialQueue.push(requestWithConflictResolution);
 
-        const requestWithConflictResolution2: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: conflictResolver,
-        };
-
-        SequentialQueue.push(requestWithConflictResolution);
-        SequentialQueue.push(requestWithConflictResolution2);
-
-        expect(getLength()).toBe(2);
+            // The new request is in the persisted queue with the expected accountID.
+            expect(getAll().some((r) => r.data?.accountID === 56789)).toBe(true);
+        } finally {
+            await mockFetch.resume();
+        }
     });
 
-    it('should replace request request in queue while a similar one is ongoing and keep the same index', () => {
-        SequentialQueue.push({command: 'OpenReport'});
-        SequentialQueue.push(request);
+    it('should replace request in queue while a similar one is ongoing', async () => {
+        mockFetch.pause();
+        try {
+            await SequentialQueue.push(request);
+            await waitForBatchedUpdates();
+            expect(getOngoingRequest()?.command).toBe('ReconnectApp');
 
-        const requestWithConflictResolution: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: (persistedRequests) => {
-                // should be one instance of ReconnectApp, get the index to replace it later
+            const conflictResolver = <TKey extends OnyxKey>(persistedRequests: Array<Request<TKey>>): ConflictActionData => {
                 const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
                 if (index === -1) {
                     return {conflictAction: {type: 'push'}};
                 }
+                return {conflictAction: {type: 'replace', index}};
+            };
 
-                return {
-                    conflictAction: {type: 'replace', index},
-                };
-            },
-        };
+            const requestWithConflictResolution: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: conflictResolver,
+            };
 
-        SequentialQueue.push(requestWithConflictResolution);
-        SequentialQueue.push({command: 'AddComment'});
-        SequentialQueue.push({command: 'OpenReport'});
+            const requestWithConflictResolution2: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: conflictResolver,
+            };
 
-        expect(getLength()).toBe(4);
-        const persistedRequests = getAll();
-        const ongoingRequest = getOngoingRequest();
+            // First conflict push: queue is empty (ongoing not in queue) → push action → queue=[r2].
+            // Second conflict push: queue=[r2] → replace at 0 → queue=[r3].
+            // Total in-flight items: ongoing + queue = 2.
+            await SequentialQueue.push(requestWithConflictResolution);
+            await SequentialQueue.push(requestWithConflictResolution2);
 
-        // The first OpenReport call is ongoing
-        expect(ongoingRequest?.command).toBe('OpenReport');
+            expect(getLength()).toBe(2);
+        } finally {
+            await mockFetch.resume();
+        }
+    });
 
-        // We know ReconnectApp is at index 0 in the queue now, so we can get it to verify
-        // that was replaced by the new request.
-        expect(persistedRequests.at(0)?.data?.accountID).toBe(56789);
+    it('should replace request in queue while a similar one is ongoing and keep the same index', async () => {
+        mockFetch.pause();
+        try {
+            // First push moves into `ongoingRequest`; subsequent pushes stack in the queue.
+            await SequentialQueue.push({command: 'OpenReport'});
+            await waitForBatchedUpdates();
+            expect(getOngoingRequest()?.command).toBe('OpenReport');
+
+            await SequentialQueue.push(request);
+
+            const requestWithConflictResolution: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: (persistedRequests) => {
+                    const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
+                    if (index === -1) {
+                        return {conflictAction: {type: 'push'}};
+                    }
+                    return {conflictAction: {type: 'replace', index}};
+                },
+            };
+
+            await SequentialQueue.push(requestWithConflictResolution);
+            await SequentialQueue.push({command: 'AddComment'});
+            await SequentialQueue.push({command: 'OpenReport'});
+
+            expect(getLength()).toBe(4);
+            const persistedRequests = getAll();
+            expect(getOngoingRequest()?.command).toBe('OpenReport');
+            expect(persistedRequests.at(0)?.data?.accountID).toBe(56789);
+        } finally {
+            await mockFetch.resume();
+        }
     });
 
-    // need to test a rance condition between processing the next request and then pushing a new request with conflict resolver
+    // need to test a race condition between processing the next request and then pushing a new request with conflict resolver
     it('should resolve the conflict and replace the correct request in the queue while a new request is picked up after unpausing', async () => {
         SequentialQueue.pause();
         for (let i = 0; i < 5; i++) {
diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts
index 4e2737861ae0..b734fb10f3f9 100644
--- a/tests/unit/SidebarUtilsTest.ts
+++ b/tests/unit/SidebarUtilsTest.ts
@@ -1630,6 +1630,164 @@ describe('SidebarUtils', () => {
             expect(result.messageText).toBeTruthy();
             expect(result.messageText).not.toContain('Concierge');
         });
+
+        it('returns track-intent welcome message for policy expense chat when user is track-intent and owns the report', async () => {
+            const currentUserAccountID = 1;
+            const MOCK_REPORT: Report = {
+                ...LHNTestUtils.getFakeReport(),
+                chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: currentUserAccountID,
+                policyID: 'testPolicy',
+            };
+            const MOCK_POLICY: Policy = {
+                id: 'testPolicy',
+                name: 'Test Workspace',
+                type: CONST.POLICY.TYPE.TEAM,
+            } as Policy;
+
+            await waitForBatchedUpdates();
+            await act(async () => {
+                await Onyx.multiSet({
+                    [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+                    [ONYXKEYS.SESSION]: {accountID: currentUserAccountID},
+                });
+            });
+
+            const result = SidebarUtils.getWelcomeMessage({
+                report: MOCK_REPORT,
+                policy: MOCK_POLICY,
+                invoiceReceiverPolicy: undefined,
+                participantPersonalDetailList: [],
+                translate: translateLocal,
+                localeCompare,
+                conciergeReportID: MOCK_CONCIERGE_REPORT_ID,
+                isTrackIntentUser: true,
+                currentUserAccountID,
+            });
+            expect(result.messageText).toBe("This is where you'll track expenses.");
+        });
+
+        it('returns standard welcome message for policy expense chat when user is track-intent but does NOT own the report', async () => {
+            const currentUserAccountID = 1;
+            const otherUserAccountID = 2;
+            const MOCK_REPORT: Report = {
+                ...LHNTestUtils.getFakeReport(),
+                chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: otherUserAccountID,
+                policyID: 'testPolicy',
+            };
+            const MOCK_POLICY: Policy = {
+                id: 'testPolicy',
+                name: 'Test Workspace',
+                type: CONST.POLICY.TYPE.TEAM,
+            } as Policy;
+
+            await waitForBatchedUpdates();
+            await act(async () => {
+                await Onyx.multiSet({
+                    [ONYXKEYS.PERSONAL_DETAILS_LIST]: {
+                        ...LHNTestUtils.fakePersonalDetails,
+                        [otherUserAccountID]: {
+                            accountID: otherUserAccountID,
+                            displayName: 'Other User',
+                            login: 'other@test.com',
+                            avatar: '',
+                        },
+                    },
+                    [ONYXKEYS.SESSION]: {accountID: currentUserAccountID},
+                });
+            });
+
+            const result = SidebarUtils.getWelcomeMessage({
+                report: MOCK_REPORT,
+                policy: MOCK_POLICY,
+                invoiceReceiverPolicy: undefined,
+                participantPersonalDetailList: [],
+                translate: translateLocal,
+                localeCompare,
+                conciergeReportID: MOCK_CONCIERGE_REPORT_ID,
+                isTrackIntentUser: true,
+                currentUserAccountID,
+            });
+            expect(result.messageHtml).toContain('will submit expenses to');
+        });
+
+        it('returns standard welcome message for policy expense chat when user is NOT track-intent', async () => {
+            const currentUserAccountID = 1;
+            const MOCK_REPORT: Report = {
+                ...LHNTestUtils.getFakeReport(),
+                chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: currentUserAccountID,
+                policyID: 'testPolicy',
+            };
+            const MOCK_POLICY: Policy = {
+                id: 'testPolicy',
+                name: 'Test Workspace',
+                type: CONST.POLICY.TYPE.TEAM,
+            } as Policy;
+
+            await waitForBatchedUpdates();
+            await act(async () => {
+                await Onyx.multiSet({
+                    [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+                    [ONYXKEYS.SESSION]: {accountID: currentUserAccountID},
+                });
+            });
+
+            const result = SidebarUtils.getWelcomeMessage({
+                report: MOCK_REPORT,
+                policy: MOCK_POLICY,
+                invoiceReceiverPolicy: undefined,
+                participantPersonalDetailList: [],
+                translate: translateLocal,
+                localeCompare,
+                conciergeReportID: MOCK_CONCIERGE_REPORT_ID,
+                isTrackIntentUser: false,
+                currentUserAccountID,
+            });
+            expect(result.messageHtml).toContain('will submit expenses to');
+        });
+
+        it('returns standard welcome message when policy has a custom description even for track-intent users', async () => {
+            const currentUserAccountID = 1;
+            const MOCK_REPORT: Report = {
+                ...LHNTestUtils.getFakeReport(),
+                chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: currentUserAccountID,
+                policyID: 'testPolicy',
+            };
+            const MOCK_POLICY: Policy = {
+                id: 'testPolicy',
+                name: 'Test Workspace',
+                description: 'Custom workspace description',
+                type: CONST.POLICY.TYPE.TEAM,
+            } as Policy;
+
+            await waitForBatchedUpdates();
+            await act(async () => {
+                await Onyx.multiSet({
+                    [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+                    [ONYXKEYS.SESSION]: {accountID: currentUserAccountID},
+                });
+            });
+
+            const result = SidebarUtils.getWelcomeMessage({
+                report: MOCK_REPORT,
+                policy: MOCK_POLICY,
+                invoiceReceiverPolicy: undefined,
+                participantPersonalDetailList: [],
+                translate: translateLocal,
+                localeCompare,
+                conciergeReportID: MOCK_CONCIERGE_REPORT_ID,
+                isTrackIntentUser: true,
+                currentUserAccountID,
+            });
+            expect(result.messageHtml).toBe('Custom workspace description');
+        });
     });
 
     describe('getOptionData', () => {
@@ -1885,6 +2043,52 @@ describe('SidebarUtils', () => {
             expect(result?.alternateText).toBe('changed the foreign currency default tax rate to "Foreign Tax (10%)" (previously "Foreign Tax (15%)")');
         });
 
+        it('returns the correct alternate text for UPDATE_CATEGORY_TAX_RATE action', async () => {
+            const report: Report = {
+                ...createRandomReport(4, 'policyAdmins'),
+                participants: {'18921695': {notificationPreference: 'always'}},
+            };
+            const lastAction: ReportAction = {
+                ...createRandomReportAction(2),
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                originalMessage: {
+                    categoryName: 'Office Supplies',
+                    oldTaxName: 'Tax Exempt',
+                    oldTaxPercentage: '0%',
+                    newTaxName: 'Tax Rate 1',
+                    newTaxPercentage: '5%',
+                },
+            };
+            const reportActions: ReportActions = {[lastAction.reportActionID]: lastAction};
+            await act(async () => {
+                await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, report);
+                await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, reportActions);
+            });
+
+            const result = SidebarUtils.getOptionData({
+                report,
+                reportAttributes: undefined,
+                reportNameValuePairs: {},
+                personalDetails: {},
+                policy: undefined,
+                invoiceReceiverPolicy: undefined,
+                parentReportAction: undefined,
+                conciergeReportID: '',
+                oneTransactionThreadReport: undefined,
+                card: undefined,
+                translate: translateLocal,
+                localeCompare,
+                lastAction,
+                lastActionReport: undefined,
+                isReportArchived: undefined,
+                currentUserAccountID: 0,
+                currentUserLogin: CURRENT_USER_LOGIN,
+                reportAttributesDerived: undefined,
+            });
+
+            expect(result?.alternateText).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Tax Exempt (0%)")');
+        });
+
         it('returns the correct alternate text for UPDATE_REQUIRE_COMPANY_CARDS_ENABLED action', async () => {
             const report: Report = {
                 ...createRandomReport(4, 'policyAdmins'),
diff --git a/tests/unit/WorkspaceReportFieldUtilsTest.ts b/tests/unit/WorkspaceReportFieldUtilsTest.ts
index 5c9f7e8cecca..6a02ca2f75aa 100644
--- a/tests/unit/WorkspaceReportFieldUtilsTest.ts
+++ b/tests/unit/WorkspaceReportFieldUtilsTest.ts
@@ -1,5 +1,4 @@
-import {generateFieldID, getUnsupportedReportFieldFormulaParts, hasFormulaPartsInInitialValue, isReportFieldNameExisting, isReportFieldTargetValid} from '@libs/WorkspaceReportFieldUtils';
-import CONST from '@src/CONST';
+import {getUnsupportedReportFieldFormulaParts, hasFormulaPartsInInitialValue, isReportFieldNameExisting} from '@libs/WorkspaceReportFieldUtils';
 import type {PolicyReportField} from '@src/types/onyx/Policy';
 
 describe('WorkspaceReportFieldUtils.hasFormulaPartsInInitialValue', () => {
@@ -84,28 +83,13 @@ describe('WorkspaceReportFieldUtils.getUnsupportedReportFieldFormulaParts', () =
 });
 
 describe('WorkspaceReportFieldUtils.isReportFieldNameExisting', () => {
-    const baseNameField: PolicyReportField = {
-        fieldID: '',
-        name: '',
-        type: 'text',
-        values: [],
-        disabledOptions: [],
-        defaultValue: '',
-        orderWeight: 0,
-        deletable: false,
-        keys: [],
-        externalIDs: [],
-        isTax: false,
-    };
     const fieldList: Record<string, PolicyReportField> = {
-        field1: {...baseNameField, name: 'Field1', type: 'text'},
-        field2: {...baseNameField, name: 'Field2', type: 'date'},
-        field3: {...baseNameField, name: 'Field3', type: 'text', target: CONST.REPORT_FIELD_TARGETS.EXPENSE},
-        field4: {...baseNameField, name: 'Field3', type: 'text', target: CONST.REPORT_FIELD_TARGETS.INVOICE},
+        field1: {name: 'Field1', type: 'text'} as PolicyReportField,
+        field2: {name: 'Field2', type: 'date'} as PolicyReportField,
     };
 
     it('should return false when field name does not exist', () => {
-        expect(isReportFieldNameExisting(fieldList, 'Field5')).toBe(false);
+        expect(isReportFieldNameExisting(fieldList, 'Field3')).toBe(false);
     });
 
     it('should return true when field name exists with exact case match', () => {
@@ -116,54 +100,4 @@ describe('WorkspaceReportFieldUtils.isReportFieldNameExisting', () => {
         expect(isReportFieldNameExisting(fieldList, 'FIELD1')).toBe(true);
         expect(isReportFieldNameExisting(fieldList, 'field1')).toBe(true);
     });
-
-    it('checks existing names only within the expected target', () => {
-        expect(isReportFieldNameExisting(fieldList, 'Field1', CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe(false);
-        expect(isReportFieldNameExisting(fieldList, 'Field1', CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe(true);
-        expect(isReportFieldNameExisting(fieldList, 'Field3', CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe(true);
-        expect(isReportFieldNameExisting(fieldList, 'Field3', CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe(true);
-    });
-});
-
-describe('WorkspaceReportFieldUtils.generateFieldID', () => {
-    it('keeps the existing field ID format when no target is provided', () => {
-        expect(generateFieldID('Field A')).toBe('field_id_FIELD_A');
-    });
-
-    it('can include target in the field ID to avoid cross-target collisions', () => {
-        expect(generateFieldID('Field A', CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe('field_id_INVOICE_FIELD_A');
-        expect(generateFieldID('Field A', CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe('field_id_EXPENSE_FIELD_A');
-    });
-});
-
-describe('WorkspaceReportFieldUtils.isReportFieldTargetValid', () => {
-    const baseField: PolicyReportField = {
-        fieldID: 'field_id_1',
-        name: 'Field A',
-        type: CONST.REPORT_FIELD_TYPES.TEXT,
-        values: [],
-        disabledOptions: [],
-        defaultValue: '',
-        orderWeight: 1,
-        deletable: true,
-        keys: [],
-        externalIDs: [],
-        isTax: false,
-    };
-
-    it('allows expense fields without target', () => {
-        expect(isReportFieldTargetValid(baseField, CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe(true);
-    });
-
-    it('blocks expense settings for invoice-targeted fields', () => {
-        expect(isReportFieldTargetValid({...baseField, target: CONST.REPORT_FIELD_TARGETS.INVOICE}, CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe(false);
-    });
-
-    it('allows invoice settings for invoice-targeted fields', () => {
-        expect(isReportFieldTargetValid({...baseField, target: CONST.REPORT_FIELD_TARGETS.INVOICE}, CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe(true);
-    });
-
-    it('blocks invoice settings for fields without target', () => {
-        expect(isReportFieldTargetValid(baseField, CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe(false);
-    });
 });
diff --git a/tests/unit/hooks/useExpenseSubmission.test.ts b/tests/unit/hooks/useExpenseSubmission.test.ts
index 08ea679d68da..7a89126b3d97 100644
--- a/tests/unit/hooks/useExpenseSubmission.test.ts
+++ b/tests/unit/hooks/useExpenseSubmission.test.ts
@@ -9,6 +9,8 @@ import waitForBatchedUpdatesWithAct from '../../utils/waitForBatchedUpdatesWithA
 
 const mockRequestMoneyAction = jest.fn();
 const mockTrackExpenseAction = jest.fn();
+const mockSubmitPerDiemExpenseAction = jest.fn();
+const mockSubmitPerDiemExpenseForSelfDMAction = jest.fn();
 const mockCleanupAfterExpenseCreate = jest.fn();
 const mockCleanupAndNavigateAfterExpenseCreate = jest.fn();
 const mockResolveChatTargetForSubmitCleanup = jest.fn();
@@ -18,6 +20,11 @@ jest.mock('@userActions/IOU/TrackExpense', () => ({
     trackExpense: (...args: unknown[]) => mockTrackExpenseAction(...args),
 }));
 
+jest.mock('@userActions/IOU/PerDiem', () => ({
+    submitPerDiemExpense: (...args: unknown[]) => mockSubmitPerDiemExpenseAction(...args),
+    submitPerDiemExpenseForSelfDM: (...args: unknown[]) => mockSubmitPerDiemExpenseForSelfDMAction(...args),
+}));
+
 jest.mock('@libs/Navigation/helpers/cleanupAfterExpenseCreate', () => ({
     __esModule: true,
     default: (...args: unknown[]) => mockCleanupAfterExpenseCreate(...args),
@@ -106,6 +113,38 @@ function buildTransaction(overrides: Partial<Transaction> = {}): Transaction {
     } as Transaction;
 }
 
+function buildReportAction(overrides: Partial<ReportAction> = {}): ReportAction {
+    return {
+        reportActionID: 'report-action-1',
+        actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+        created: '2026-04-24',
+        ...overrides,
+    };
+}
+
+function buildPerDiemTransaction(overrides: Partial<Transaction> = {}): Transaction {
+    return buildTransaction({
+        amount: 200,
+        merchant: 'Per diem',
+        comment: {
+            comment: 'Trip per diem',
+            customUnit: {
+                customUnitID: 'per-diem-custom-unit',
+                customUnitRateID: 'per-diem-rate',
+                name: CONST.CUSTOM_UNITS.NAME_PER_DIEM_INTERNATIONAL,
+                subRates: [{id: 'sub-rate-1', name: 'Meals', quantity: 1, rate: 200}],
+                attributes: {
+                    dates: {
+                        start: '2026-04-24',
+                        end: '2026-04-24',
+                    },
+                },
+            },
+        },
+        ...overrides,
+    });
+}
+
 function buildParams(overrides: Partial<Parameters<typeof useExpenseSubmission>[0]> = {}): Parameters<typeof useExpenseSubmission>[0] {
     const transaction = buildTransaction();
     return {
@@ -190,16 +229,14 @@ describe('useExpenseSubmission orchestrator-suppressed cleanup', () => {
             // Move-from-track SUBMIT: the action writes the transaction under the EXISTING tracked transaction id,
             // so cleanup must reference that same id — not a fresh rand64() optimistic one.
             const EXISTING_TRACKED_TRANSACTION_ID = 'tracked-transaction-99';
-            const linkedTrackedExpenseReportAction = {
+            const linkedTrackedExpenseReportAction = buildReportAction({
                 reportActionID: 'linked-action-1',
-                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
-                created: '2026-04-24',
                 originalMessage: {
                     IOUTransactionID: EXISTING_TRACKED_TRANSACTION_ID,
                     IOUReportID: 'tracked-report-1',
                     type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
                 },
-            } as unknown as ReportAction;
+            });
             const movedTransaction = buildTransaction({
                 linkedTrackedExpenseReportAction,
                 linkedTrackedExpenseReportID: 'tracked-report-1',
@@ -244,6 +281,55 @@ describe('useExpenseSubmission orchestrator-suppressed cleanup', () => {
             expect(mockResolveChatTargetForSubmitCleanup).not.toHaveBeenCalled();
             expect(mockCleanupAndNavigateAfterExpenseCreate).toHaveBeenCalledWith(expect.objectContaining({optimisticChatReportID: 'iou-chat-77'}));
         });
+
+        it('routes tracked per diem SUBMIT through requestMoney so the original tracked expense is moved', async () => {
+            const existingTrackedTransactionID = 'tracked-per-diem-transaction-1';
+            const linkedTrackedExpenseReportAction = buildReportAction({
+                reportActionID: 'tracked-per-diem-action-1',
+                childReportID: 'tracked-per-diem-thread-1',
+                originalMessage: {
+                    IOUTransactionID: existingTrackedTransactionID,
+                    IOUReportID: 'tracked-per-diem-report-1',
+                    type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
+                },
+            });
+            const perDiemTransaction = buildPerDiemTransaction({
+                linkedTrackedExpenseReportAction,
+                linkedTrackedExpenseReportID: 'tracked-per-diem-report-1',
+            });
+
+            const {result} = renderHook(() =>
+                useExpenseSubmission(
+                    buildParams({
+                        action: CONST.IOU.ACTION.SUBMIT,
+                        requestType: CONST.IOU.REQUEST_TYPE.PER_DIEM,
+                        isPerDiemRequest: true,
+                        transaction: perDiemTransaction,
+                        transactions: [perDiemTransaction],
+                    }),
+                ),
+            );
+            await waitForBatchedUpdatesWithAct();
+
+            await act(async () => {
+                result.current.createTransaction(false, true);
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            expect(mockRequestMoneyAction).toHaveBeenCalledTimes(1);
+            expect(mockRequestMoneyAction).toHaveBeenCalledWith(
+                expect.objectContaining({
+                    action: CONST.IOU.ACTION.SUBMIT,
+                    existingTransaction: perDiemTransaction,
+                    transactionParams: expect.objectContaining({
+                        linkedTrackedExpenseReportAction,
+                        linkedTrackedExpenseReportID: 'tracked-per-diem-report-1',
+                    }),
+                }),
+            );
+            expect(mockSubmitPerDiemExpenseAction).not.toHaveBeenCalled();
+            expect(mockSubmitPerDiemExpenseForSelfDMAction).not.toHaveBeenCalled();
+        });
     });
 
     describe('trackExpense path', () => {
@@ -293,6 +379,33 @@ describe('useExpenseSubmission orchestrator-suppressed cleanup', () => {
             expect(mockTrackExpenseAction).toHaveBeenCalledWith(expect.objectContaining({existingTransaction: params.transactions.at(0)}));
         });
     });
+
+    describe('per diem path', () => {
+        it('keeps initial self-DM per diem tracking on submitPerDiemExpenseForSelfDM', async () => {
+            const perDiemTransaction = buildPerDiemTransaction();
+
+            const {result} = renderHook(() =>
+                useExpenseSubmission(
+                    buildParams({
+                        iouType: CONST.IOU.TYPE.TRACK,
+                        requestType: CONST.IOU.REQUEST_TYPE.PER_DIEM,
+                        isPerDiemRequest: true,
+                        transaction: perDiemTransaction,
+                        transactions: [perDiemTransaction],
+                    }),
+                ),
+            );
+            await waitForBatchedUpdatesWithAct();
+
+            await act(async () => {
+                result.current.createTransaction(false, true);
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            expect(mockSubmitPerDiemExpenseForSelfDMAction).toHaveBeenCalledTimes(1);
+            expect(mockRequestMoneyAction).not.toHaveBeenCalled();
+        });
+    });
 });
 
 describe('useExpenseSubmission action-bailout safety', () => {
@@ -323,7 +436,7 @@ describe('useExpenseSubmission action-bailout safety', () => {
 
     it('skips cleanup/nav when a multi-transaction SUBMIT batch has any iteration that bails (defense-in-depth — preserves the failed item draft)', async () => {
         // Cast keeps the fixture minimal — pre-validation only needs truthy presence.
-        const linkedTracked = {linkedTrackedExpenseReportAction: {reportActionID: 'a-1'} as unknown as ReportAction, linkedTrackedExpenseReportID: 'r-1'};
+        const linkedTracked = {linkedTrackedExpenseReportAction: buildReportAction({reportActionID: 'a-1'}), linkedTrackedExpenseReportID: 'r-1'};
         const transaction1 = buildTransaction({transactionID: 't-1', ...linkedTracked});
         const transaction2 = buildTransaction({transactionID: 't-2', ...linkedTracked});
         mockRequestMoneyAction.mockReturnValueOnce({iouReport: {reportID: 'iou-1'}}).mockReturnValueOnce({});
diff --git a/tests/unit/hooks/useInboxTabSpanLifecycle.test.ts b/tests/unit/hooks/useInboxTabSpanLifecycle.test.ts
new file mode 100644
index 000000000000..6252fb049de0
--- /dev/null
+++ b/tests/unit/hooks/useInboxTabSpanLifecycle.test.ts
@@ -0,0 +1,138 @@
+import {act, renderHook} from '@testing-library/react-native';
+import useInboxTabSpanLifecycle from '@hooks/useInboxTabSpanLifecycle';
+import CONST from '@src/CONST';
+
+type FocusCallback = () => (() => void) | void;
+type FakeSpan = {id: string};
+
+const SPAN = CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB;
+
+const mockUseFocusEffect = jest.fn<void, [FocusCallback]>();
+const mockGetSpan = jest.fn<FakeSpan | undefined, [string]>();
+const mockEndSpan = jest.fn<void, [string]>();
+const mockCancelSpan = jest.fn<void, [string]>();
+
+// The hook only consumes useFocusEffect from this module. We capture the focus callback
+// (via mockUseFocusEffect.mock.calls) so each test can drive focus/blur explicitly instead
+// of standing up a navigation container.
+jest.mock('@react-navigation/native', () => ({
+    useFocusEffect: (callback: FocusCallback) => {
+        mockUseFocusEffect(callback);
+    },
+}));
+
+jest.mock('@libs/telemetry/activeSpans', () => ({
+    getSpan: (spanId: string) => mockGetSpan(spanId),
+    endSpan: (spanId: string) => mockEndSpan(spanId),
+    cancelSpan: (spanId: string) => mockCancelSpan(spanId),
+}));
+
+const spanAtMount: FakeSpan = {id: 'span-at-mount'};
+const newerSpan: FakeSpan = {id: 'newer-span'};
+
+/** The currently active span returned by getSpan. Defaults to the one present when the hook mounts. */
+let currentActiveSpan: FakeSpan | undefined;
+
+/** Returns the latest focus callback the hook registered with useFocusEffect. */
+function getFocusCallback(): FocusCallback {
+    const callback = mockUseFocusEffect.mock.calls.at(-1)?.[0];
+    if (!callback) {
+        throw new Error('useFocusEffect was never called by the hook');
+    }
+    return callback;
+}
+
+describe('useInboxTabSpanLifecycle', () => {
+    beforeEach(() => {
+        jest.clearAllMocks();
+        currentActiveSpan = spanAtMount;
+        mockGetSpan.mockImplementation(() => currentActiveSpan);
+    });
+
+    it('ends the span when the sidebar lays out for the first time (normal path)', () => {
+        const {result} = renderHook(() => useInboxTabSpanLifecycle());
+
+        act(() => {
+            result.current();
+        });
+
+        expect(mockEndSpan).toHaveBeenCalledTimes(1);
+        expect(mockEndSpan).toHaveBeenCalledWith(SPAN);
+        expect(mockCancelSpan).not.toHaveBeenCalled();
+    });
+
+    it('does not end the span on focus before the first layout (cold path)', () => {
+        renderHook(() => useInboxTabSpanLifecycle());
+
+        act(() => {
+            getFocusCallback()();
+        });
+
+        expect(mockEndSpan).not.toHaveBeenCalled();
+    });
+
+    it('ends the span on re-focus after layout (warm react-freeze path)', () => {
+        const {result} = renderHook(() => useInboxTabSpanLifecycle());
+
+        // First layout completes, then the user leaves and returns: react-freeze keeps the
+        // layout cached so onLayout will not fire again, and focus must end the span instead.
+        act(() => {
+            result.current();
+        });
+        mockEndSpan.mockClear();
+
+        act(() => {
+            getFocusCallback()();
+        });
+
+        expect(mockEndSpan).toHaveBeenCalledTimes(1);
+        expect(mockEndSpan).toHaveBeenCalledWith(SPAN);
+    });
+
+    it('cancels the span on blur when layout never completed (orphan cleanup)', () => {
+        renderHook(() => useInboxTabSpanLifecycle());
+
+        const blurCleanup = getFocusCallback()();
+
+        expect(typeof blurCleanup).toBe('function');
+        act(() => {
+            blurCleanup?.();
+        });
+
+        expect(mockCancelSpan).toHaveBeenCalledTimes(1);
+        expect(mockCancelSpan).toHaveBeenCalledWith(SPAN);
+    });
+
+    it('cancels the span on unmount when layout never completed and the active span is unchanged', () => {
+        const {unmount} = renderHook(() => useInboxTabSpanLifecycle());
+
+        unmount();
+
+        expect(mockCancelSpan).toHaveBeenCalledTimes(1);
+        expect(mockCancelSpan).toHaveBeenCalledWith(SPAN);
+    });
+
+    it('does not cancel on unmount when a newer span has started (subsequent tab click)', () => {
+        const {unmount} = renderHook(() => useInboxTabSpanLifecycle());
+
+        // A later tab click started a fresh span before this instance unmounted. The unmount
+        // cleanup must not cancel that newer span.
+        currentActiveSpan = newerSpan;
+        unmount();
+
+        expect(mockCancelSpan).not.toHaveBeenCalled();
+    });
+
+    it('does not cancel on unmount after layout has completed', () => {
+        const {result, unmount} = renderHook(() => useInboxTabSpanLifecycle());
+
+        act(() => {
+            result.current();
+        });
+        mockCancelSpan.mockClear();
+
+        unmount();
+
+        expect(mockCancelSpan).not.toHaveBeenCalled();
+    });
+});
diff --git a/tests/unit/hooks/useRestoreWorkspacesTabOnNavigate.test.ts b/tests/unit/hooks/useRestoreWorkspacesTabOnNavigate.test.ts
index 464d507ae18a..ea75a8c57023 100644
--- a/tests/unit/hooks/useRestoreWorkspacesTabOnNavigate.test.ts
+++ b/tests/unit/hooks/useRestoreWorkspacesTabOnNavigate.test.ts
@@ -2,7 +2,6 @@ import {StackActions, TabActions} from '@react-navigation/native';
 import {renderHook} from '@testing-library/react-native';
 import Navigation from '@libs/Navigation/Navigation';
 import navigationRef from '@libs/Navigation/navigationRef';
-// eslint-disable-next-line no-restricted-imports -- TransitionTracker is mocked here to assert the tab-jump sequencing after popToTop in navigateToWorkspacesPage.
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/tests/unit/navigateToWorkspacesPageTest.ts b/tests/unit/navigateToWorkspacesPageTest.ts
index 05cff0353dda..ac3ab3b618b7 100644
--- a/tests/unit/navigateToWorkspacesPageTest.ts
+++ b/tests/unit/navigateToWorkspacesPageTest.ts
@@ -4,7 +4,6 @@ import interceptAnonymousUser from '@libs/interceptAnonymousUser';
 import navigateToWorkspacesPage from '@libs/Navigation/helpers/navigateToWorkspacesPage';
 import Navigation from '@libs/Navigation/Navigation';
 import navigationRef from '@libs/Navigation/navigationRef';
-// eslint-disable-next-line no-restricted-imports -- TransitionTracker is mocked here to assert the tab-jump sequencing after popToTop in navigateToWorkspacesPage.
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import * as PolicyUtils from '@libs/PolicyUtils';
 import NAVIGATORS from '@src/NAVIGATORS';
diff --git a/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx b/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
index d5e74dd493e6..1a5a64a65eae 100644
--- a/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
+++ b/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
@@ -25,28 +25,38 @@ jest.mock('@libs/actions/Report', () => ({
     getReportChannelName: (reportID: string) => `private-report-${reportID}`,
 }));
 
+let mockIsVisible = true;
+const mockVisibilityCallbacks = new Set<() => void>();
+
+jest.mock('@libs/Visibility', () => ({
+    __esModule: true,
+    default: {
+        hasFocus: jest.fn(() => true),
+        isVisible: jest.fn(() => mockIsVisible),
+        onVisibilityChange: jest.fn((callback: () => void) => {
+            mockVisibilityCallbacks.add(callback);
+            return () => {
+                mockVisibilityCallbacks.delete(callback);
+            };
+        }),
+    },
+}));
+
 const REPORT_ID = '123';
 const REPORT_ACTION_ID = '456';
 const CREATED = '2026-04-03 10:00:00.000';
 const STREAM_SESSION_ID = 'stream-session-1';
 const TARGET_BODY_MARKDOWN = 'Hello';
 const COMPLETED_BODY_MARKDOWN = 'Hello world';
+const NEXT_BODY_MARKDOWN = 'HelloWorld';
 const FINAL_RENDERED_HTML = '<comment>Server final response</comment>';
+const PUSHER_DRAFT_PACE_INTERVAL_MS = 10;
 const SHORT_FINAL_RENDERED_HTML = '<comment>OK</comment>';
 const LONG_FINAL_RENDERED_TEXT = Array.from({length: 12}, (_, index) => `Streaming response ${index}`).join(' ');
 const LONG_FINAL_RENDERED_HTML = `<comment>${LONG_FINAL_RENDERED_TEXT}</comment>`;
 
-type MockPusherSubscribe = jest.MockedFunction<
-    (
-        channelName: string,
-        eventName?: string,
-        eventCallback?: (event: ConciergeDraftEvent | ConciergeDraftEventsEvent) => void,
-        onResubscribe?: () => void,
-    ) => ReturnType<typeof Pusher.subscribe>
->;
-
-function getMockPusherSubscribe(): MockPusherSubscribe {
-    return Pusher.subscribe as MockPusherSubscribe;
+function getMockPusherSubscribe() {
+    return jest.mocked(Pusher.subscribe);
 }
 
 function getFirstMessageText(reportAction: ReportAction | null): string | undefined {
@@ -83,6 +93,13 @@ function emitPusherEvent(eventType: string, event: ConciergeDraftEvent | Concier
     callback(event);
 }
 
+function triggerVisibilityChange(isVisible: boolean) {
+    mockIsVisible = isVisible;
+    for (const callback of mockVisibilityCallbacks) {
+        callback();
+    }
+}
+
 describe('ConciergeDraftContext', () => {
     beforeAll(() => {
         Onyx.init({keys: ONYXKEYS});
@@ -90,6 +107,8 @@ describe('ConciergeDraftContext', () => {
 
     beforeEach(async () => {
         getMockPusherSubscribe().mockClear();
+        mockIsVisible = true;
+        mockVisibilityCallbacks.clear();
         setCachedDraft(REPORT_ID, null);
         await Onyx.clear();
         await Onyx.set(ONYXKEYS.CONCIERGE_REPORT_ID, REPORT_ID);
@@ -98,6 +117,7 @@ describe('ConciergeDraftContext', () => {
 
     afterEach(async () => {
         setCachedDraft(REPORT_ID, null);
+        jest.restoreAllMocks();
         await Onyx.clear();
     });
 
@@ -168,6 +188,119 @@ describe('ConciergeDraftContext', () => {
         unmount();
     });
 
+    it('catches up paced Pusher drafts from elapsed time when visibility returns', async () => {
+        let now = 1000;
+        jest.spyOn(Date, 'now').mockImplementation(() => now);
+        const wrapper = ({children}: PropsWithChildren) => <ConciergeDraftProvider reportID={REPORT_ID}>{children}</ConciergeDraftProvider>;
+        const {result, unmount} = renderHook(() => useConciergeDraft(), {wrapper});
+
+        await waitFor(() => {
+            expect(Pusher.subscribe).toHaveBeenCalledTimes(6);
+        });
+
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(TARGET_BODY_MARKDOWN));
+        });
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('H');
+
+        act(() => {
+            triggerVisibilityChange(false);
+        });
+
+        now += 4 * PUSHER_DRAFT_PACE_INTERVAL_MS;
+        act(() => {
+            triggerVisibilityChange(true);
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('Hello');
+
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(NEXT_BODY_MARKDOWN, {sequence: 2}));
+        });
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('HelloW');
+
+        now += PUSHER_DRAFT_PACE_INTERVAL_MS;
+        act(() => {
+            triggerVisibilityChange(true);
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('HelloWo');
+
+        unmount();
+    });
+
+    it('preserves elapsed catch-up across queued Pusher targets when visibility returns', async () => {
+        let now = 1000;
+        jest.spyOn(Date, 'now').mockImplementation(() => now);
+        const wrapper = ({children}: PropsWithChildren) => <ConciergeDraftProvider reportID={REPORT_ID}>{children}</ConciergeDraftProvider>;
+        const {result, unmount} = renderHook(() => useConciergeDraft(), {wrapper});
+
+        await waitFor(() => {
+            expect(Pusher.subscribe).toHaveBeenCalledTimes(6);
+        });
+
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(TARGET_BODY_MARKDOWN));
+        });
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('H');
+
+        act(() => {
+            triggerVisibilityChange(false);
+        });
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(NEXT_BODY_MARKDOWN, {sequence: 2}));
+        });
+
+        now += 9 * PUSHER_DRAFT_PACE_INTERVAL_MS;
+        act(() => {
+            triggerVisibilityChange(true);
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe(NEXT_BODY_MARKDOWN);
+
+        unmount();
+    });
+
+    it('applies buffered completed Pusher drafts when visibility returns', async () => {
+        const wrapper = ({children}: PropsWithChildren) => <ConciergeDraftProvider reportID={REPORT_ID}>{children}</ConciergeDraftProvider>;
+        const {result, unmount} = renderHook(() => useConciergeDraft(), {wrapper});
+
+        await waitFor(() => {
+            expect(Pusher.subscribe).toHaveBeenCalledTimes(6);
+        });
+
+        act(() => {
+            triggerVisibilityChange(false);
+        });
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(COMPLETED_BODY_MARKDOWN));
+        });
+        act(() => {
+            emitPusherEvent(
+                Pusher.TYPE.CONCIERGE_DRAFT_COMPLETED,
+                createDraftEvent('', {
+                    sequence: 2,
+                    status: 'completed',
+                    bodyMarkdown: undefined,
+                    finalRenderedHTML: FINAL_RENDERED_HTML,
+                }),
+            );
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).not.toBe('Server final response');
+        expect(result.current.isDraftPendingCompletion).toBe(true);
+
+        act(() => {
+            triggerVisibilityChange(true);
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('Server final response');
+        expect(result.current.isDraftPendingCompletion).toBe(false);
+        expect(getCachedDraft(REPORT_ID)?.pusherPendingCompletionEvent).toBeUndefined();
+
+        unmount();
+    });
+
     it('trickles finalRenderedHTML-only Pusher events before completing the draft', async () => {
         const wrapper = ({children}: PropsWithChildren) => <ConciergeDraftProvider reportID={REPORT_ID}>{children}</ConciergeDraftProvider>;
         const {result, unmount} = renderHook(() => useConciergeDraft(), {wrapper});
diff --git a/tests/unit/pages/settings/AddAgentPageTest.tsx b/tests/unit/pages/settings/AddAgentPageTest.tsx
index 976a43f88352..287e135d72e6 100644
--- a/tests/unit/pages/settings/AddAgentPageTest.tsx
+++ b/tests/unit/pages/settings/AddAgentPageTest.tsx
@@ -244,15 +244,10 @@ describe('AddAgentPage', () => {
             expect(mockNavigate).not.toHaveBeenCalled();
         });
 
-        it('navigates to Edit Approval Workflow with the optimistic accountID seed when policyID + workflowApproverEmail are set', () => {
-            // The Edit page seeds approver[0] from the optimistic personal detail keyed by the
-            // optimistic accountID, so we can hop directly to the editor without waiting for
-            // CREATE_AGENT to resolve. The server-echoed `optimisticAgentAccountIDMapping`
-            // (and a prompt-match fallback) reconciles the seed to the real email once the
-            // response lands.
+        it('goes back when policyID is present without navigating to a workflow editor', () => {
             render(
                 <AddAgentPage
-                    route={makeRoute({policyID: 'POL_42', workflowApproverEmail: 'manager@example.com'})}
+                    route={makeRoute({policyID: 'POL_42'})}
                     navigation={undefined as never}
                 />,
             );
@@ -260,8 +255,7 @@ describe('AddAgentPage', () => {
             mockFormOnSubmit?.({firstName: 'Bot', prompt: 'Reject gambling.'});
 
             expect(mockGoBack).toHaveBeenCalledTimes(1);
-            expect(mockNavigate).toHaveBeenCalledWith(expect.stringContaining('workspaces/POL_42/workflows/approvals/manager%40example.com/edit'));
-            expect(mockNavigate).toHaveBeenCalledWith(expect.stringContaining('seedApproverAccountID=-123456'));
+            expect(mockNavigate).not.toHaveBeenCalled();
         });
     });
 });
diff --git a/tests/unit/pages/settings/CopilotPageTest.tsx b/tests/unit/pages/settings/CopilotPageTest.tsx
index cc97e2520429..1c06a930e470 100644
--- a/tests/unit/pages/settings/CopilotPageTest.tsx
+++ b/tests/unit/pages/settings/CopilotPageTest.tsx
@@ -73,6 +73,7 @@ jest.mock('@libs/actions/Delegate', () => ({
     connect: jest.fn(),
     openSecuritySettingsPage: jest.fn(),
     removeDelegate: jest.fn(),
+    removeDelegator: jest.fn(),
 }));
 
 jest.mock('@libs/Navigation/Navigation', () => ({
@@ -158,7 +159,7 @@ describe('CopilotPage', () => {
         expect(output).toContain('delegate.addCopilot');
     });
 
-    it('renders a delegator row with a Switch button when the user has delegators', () => {
+    it('renders a delegator row with a three-dot menu when the user has delegators', () => {
         setOnyxAccount({
             validated: true,
             delegatedAccess: {
@@ -171,7 +172,7 @@ describe('CopilotPage', () => {
         const output = JSON.stringify(toJSON());
 
         expect(output).toContain('boss@example.com');
-        expect(output).toContain('delegate.switch');
+        expect(output).toContain('icon-three-dots');
         expect(output).toContain('delegate.youCanAccessTheseAccounts');
         expect(output).not.toContain('delegate.membersCanAccessYourAccount');
     });
diff --git a/tests/unit/selectors/TodosTest.ts b/tests/unit/selectors/TodosTest.ts
index 25e57801cd2a..9d90b76cb698 100644
--- a/tests/unit/selectors/TodosTest.ts
+++ b/tests/unit/selectors/TodosTest.ts
@@ -1,6 +1,6 @@
-import todosReportCountsSelector, {todosSingleReportIDsSelector} from '@selectors/Todos';
+import todosReportCountsSelector, {flaggedExpensesReviewSelector, todosSingleReportIDsSelector} from '@selectors/Todos';
 import CONST from '@src/CONST';
-import type {TodosDerivedValue} from '@src/types/onyx';
+import type {FlaggedExpensesDerivedValue, TodosDerivedValue} from '@src/types/onyx';
 
 describe('todosReportCountsSelector', () => {
     it('returns undefined when todos is undefined', () => {
@@ -212,3 +212,69 @@ describe('todosSingleReportIDsSelector', () => {
         expect(second[CONST.SEARCH.SEARCH_KEYS.SUBMIT]).toBe('21');
     });
 });
+
+describe('flaggedExpensesReviewSelector', () => {
+    it('returns count 0 and undefined identifiers when input is undefined', () => {
+        const result = flaggedExpensesReviewSelector(undefined);
+
+        expect(result.count).toBe(0);
+        expect(result.firstTransactionID).toBeUndefined();
+        expect(result.firstReportID).toBeUndefined();
+    });
+
+    it('returns count 0 and undefined identifiers when there are no flagged expenses', () => {
+        const value: FlaggedExpensesDerivedValue = {flaggedExpenses: []};
+
+        const result = flaggedExpensesReviewSelector(value);
+
+        expect(result.count).toBe(0);
+        expect(result.firstTransactionID).toBeUndefined();
+        expect(result.firstReportID).toBeUndefined();
+    });
+
+    it('returns aggregated count and stable first identifiers for multiple flagged expenses', () => {
+        const value: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [
+                {transactionID: 't1', reportID: 'r1'},
+                {transactionID: 't2', reportID: 'r2'},
+                {transactionID: 't3', reportID: 'r3'},
+            ],
+        };
+
+        const result = flaggedExpensesReviewSelector(value);
+
+        expect(result.count).toBe(3);
+        expect(result.firstTransactionID).toBe('t1');
+        expect(result.firstReportID).toBe('r1');
+    });
+
+    it('returns the same object reference when called twice with shallowly equal values', () => {
+        const value: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [{transactionID: 'tA', reportID: 'rA'}],
+        };
+        const first = flaggedExpensesReviewSelector(value);
+
+        const clone: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [{transactionID: 'tA', reportID: 'rA'}],
+        };
+        const second = flaggedExpensesReviewSelector(clone);
+
+        expect(second).toBe(first);
+    });
+
+    it('returns a new object reference when the first flagged expense changes', () => {
+        const value: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [{transactionID: 'tA', reportID: 'rA'}],
+        };
+        const first = flaggedExpensesReviewSelector(value);
+
+        const changed: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [{transactionID: 'tB', reportID: 'rB'}],
+        };
+        const second = flaggedExpensesReviewSelector(changed);
+
+        expect(second).not.toBe(first);
+        expect(second.firstTransactionID).toBe('tB');
+        expect(second.firstReportID).toBe('rB');
+    });
+});
diff --git a/tests/unit/useCreateReportTest.tsx b/tests/unit/useCreateReportTest.tsx
index 8c76cf0a9169..d4dcbe58d183 100644
--- a/tests/unit/useCreateReportTest.tsx
+++ b/tests/unit/useCreateReportTest.tsx
@@ -39,6 +39,7 @@ jest.mock('@libs/PolicyUtils', () => ({
         return undefined;
     }),
     isPaidGroupPolicy: jest.fn((policy: OnyxEntry<Policy>) => policy?.type === 'team' || policy?.type === 'corporate'),
+    isGroupPolicy: jest.fn((policy: OnyxEntry<Policy>) => policy?.type === 'team' || policy?.type === 'corporate' || policy?.type === 'submit2026'),
 }));
 
 jest.mock('@libs/interceptAnonymousUser', () => jest.fn((cb: () => void) => cb()));
diff --git a/tests/unit/useSidebarOrderedReportsTest.tsx b/tests/unit/useSidebarOrderedReportsTest.tsx
index 442bd868d9d9..aa8d3bf916da 100644
--- a/tests/unit/useSidebarOrderedReportsTest.tsx
+++ b/tests/unit/useSidebarOrderedReportsTest.tsx
@@ -16,6 +16,8 @@ jest.mock('@libs/SidebarUtils', () => ({
     sortReportsToDisplayInLHN: jest.fn(),
     getReportsToDisplayInLHN: jest.fn(),
     updateReportsToDisplayInLHN: jest.fn(),
+    filterReportsForInboxTab: jest.fn((reportIDs: string[]) => reportIDs),
+    getInboxTabCounts: jest.fn(() => ({})),
 }));
 jest.mock('@libs/Navigation/Navigation', () => ({
     getActiveRouteWithoutParams: jest.fn(() => ''),
diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts
index b710ea226cde..edea0633e606 100644
--- a/tests/utils/TestHelper.ts
+++ b/tests/utils/TestHelper.ts
@@ -217,7 +217,7 @@ function signOutTestUser() {
  * - fail() - start returning a failure response
  * - success() - go back to returning a success response
  */
-function getGlobalFetchMock(mockResponse?: Partial<Response>): typeof fetch {
+function createGlobalFetchMock(mockResponse?: Partial<Response>): MockFetch {
     let queue: QueueItem[] = [];
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
     let responses = new Map<string, (params: any) => OnyxResponse<any>>();
@@ -280,7 +280,11 @@ function getGlobalFetchMock(mockResponse?: Partial<Response>): typeof fetch {
     mockFetch.mockAPICommand = <TCommand extends ApiCommand>(command: TCommand, responseHandler: (params: ApiRequestCommandParameters[TCommand]) => OnyxResponse<any>): void => {
         responses.set(command, responseHandler);
     };
-    return mockFetch as typeof fetch;
+    return mockFetch;
+}
+
+function getGlobalFetchMock(mockResponse?: Partial<Response>): typeof fetch {
+    return createGlobalFetchMock(mockResponse);
 }
 
 function setupGlobalFetchMock(): MockFetch {
@@ -394,6 +398,7 @@ export {
     buildTestReportComment,
     getFetchMockCalls,
     getGlobalFetchMock,
+    createGlobalFetchMock,
     setPersonalDetails,
     signInWithTestUser,
     signOutTestUser,
