From 19880e4f5791c40a5ba96bf64425453006a8c32f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Tue, 12 May 2026 08:43:08 +0200
Subject: [PATCH 01/11] Reapply "feat: 79048 restore reverted usd flow"

This reverts commit 2a6276e99740955c761f50b9ab8163b0b2314568.

# Conflicts:
#	src/ROUTES.ts
#	src/components/Navigation/DebugTabView.tsx
#	src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
---
 src/CONST/index.ts                            |  58 +++++
 src/ROUTES.ts                                 |  37 ++-
 src/SCREENS.ts                                |   1 +
 src/components/Navigation/DebugTabView.tsx    |   5 +-
 .../useReimbursementAccountSubmitCallback.ts  |  28 +++
 .../ModalStackNavigators/index.tsx            |  14 ++
 src/libs/Navigation/linkingConfig/config.ts   |   4 +
 src/libs/Navigation/types.ts                  |   8 +
 src/libs/ReimbursementAccountUtils.ts         |  25 +-
 .../ConnectedVerifiedBankAccount.tsx          |   4 +-
 .../NonUSDVerifiedBankAccountFlowPage.tsx     |   2 +-
 .../ReimbursementAccountPage.tsx              |  40 ++-
 .../ReimbursementAccountVerifyAccountPage.tsx |   3 +-
 .../USD/BankInfo/BankInfo.tsx                 |  37 +--
 .../USD/BankInfo/subSteps/Manual.tsx          |   6 +-
 .../USD/BankInfo/subSteps/Plaid.tsx           |  12 +-
 .../USD/BankInfo/types.ts                     |   6 +
 .../BeneficialOwnerDetailsFormPages.tsx       | 123 ++++++++++
 .../BeneficialOwnersStep.tsx                  | 232 +++++++++---------
 .../AddressUBO.tsx                            |   4 +-
 .../ConfirmationUBO.tsx                       |   4 +-
 .../DateOfBirthUBO.tsx                        |   4 +-
 .../LegalNameUBO.tsx                          |   4 +-
 .../SocialSecurityNumberUBO.tsx               |   5 +-
 .../USD/BusinessInfo/BusinessInfo.tsx         |  80 +++---
 .../BusinessInfo/subSteps/AddressBusiness.tsx |   4 +-
 .../subSteps/ConfirmationBusiness.tsx         |  12 +-
 .../subSteps/IncorporationCode.tsx            |   4 +-
 .../subSteps/IncorporationDateBusiness.tsx    |   4 +-
 .../subSteps/IncorporationStateBusiness.tsx   |   4 +-
 .../IndustryCode/IndustryCodeSelector.tsx     |  23 +-
 .../BusinessInfo/subSteps/NameBusiness.tsx    |   5 +-
 .../subSteps/PhoneNumberBusiness.tsx          |   5 +-
 .../BusinessInfo/subSteps/TaxIdBusiness.tsx   |   5 +-
 .../subSteps/TypeBusiness/TypeBusiness.tsx    |   4 +-
 .../BusinessInfo/subSteps/WebsiteBusiness.tsx |   5 +-
 .../CompleteVerification.tsx                  |  37 +--
 .../subSteps/ConfirmAgreements.tsx            |   8 +-
 .../ConnectBankAccount/ConnectBankAccount.tsx |  30 ++-
 .../components/FinishChatCard.tsx             |   4 +-
 .../USD/Country/index.tsx                     |  14 +-
 .../Requestor/PersonalInfo/PersonalInfo.tsx   |  73 ++++--
 .../PersonalInfo/subSteps/Address.tsx         |   4 +-
 .../PersonalInfo/subSteps/Confirmation.tsx    |   4 +-
 .../PersonalInfo/subSteps/DateOfBirth.tsx     |   4 +-
 .../PersonalInfo/subSteps/FullName.tsx        |   4 +-
 .../subSteps/SocialSecurityNumber.tsx         |   5 +-
 .../USD/Requestor/RequestorStep.tsx           |  16 +-
 .../VerifyIdentity/VerifyIdentity.tsx         |  27 +-
 .../USD/USDVerifiedBankAccountFlow.tsx        |  97 --------
 .../USD/USDVerifiedBankAccountFlowPage.tsx    | 135 ++++++++++
 src/pages/ReimbursementAccount/USD/types.ts   |  28 +++
 .../VerifiedBankAccountFlowEntryPoint.tsx     |   4 +-
 .../WorkspaceExpensifyCardBankAccounts.tsx    |   2 -
 .../WorkspaceExpensifyCardPageEmptyState.tsx  |   3 +-
 .../WorkspaceTravelInvoicingSection.tsx       |   3 +-
 ...ceTravelInvoicingSettlementAccountPage.tsx |   2 -
 tests/unit/ReimbursementAccountUtilsTest.ts   |   9 +-
 58 files changed, 837 insertions(+), 497 deletions(-)
 create mode 100644 src/hooks/useReimbursementAccountSubmitCallback.ts
 create mode 100644 src/pages/ReimbursementAccount/USD/BankInfo/types.ts
 create mode 100644 src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnerDetailsFormPages.tsx
 delete mode 100644 src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlow.tsx
 create mode 100644 src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlowPage.tsx
 create mode 100644 src/pages/ReimbursementAccount/USD/types.ts

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index d458d94012e7..8c8b2e3fdbc1 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -666,7 +666,65 @@ const CONST = {
             VALIDATION: 'ValidationStep',
             ENABLE: 'EnableStep',
         },
+        PAGE_NAMES: {
+            COUNTRY: 'currency-and-country',
+            BANK_ACCOUNT: 'bank-info',
+            REQUESTOR: 'personal-info',
+            VERIFY_IDENTITY: 'verify-identity',
+            COMPANY: 'company',
+            BENEFICIAL_OWNERS: 'business-owner',
+            ACH_CONTRACT: 'ach-contract',
+            VALIDATION: 'validation',
+            ENABLE: 'enable',
+        },
         STEP_NAMES: ['1', '2', '3', '4', '5', '6'],
+        BANK_INFO_STEP: {
+            SUB_PAGE_NAMES: {
+                MANUAL: 'manual',
+                PLAID: 'plaid',
+            },
+        },
+        PERSONAL_INFO_STEP: {
+            SUB_PAGE_NAMES: {
+                FULL_NAME: 'full-name',
+                DATE_OF_BIRTH: 'date-of-birth',
+                SSN: 'ssn',
+                ADDRESS: 'address',
+                CONFIRMATION: 'confirmation',
+            },
+        },
+        BUSINESS_INFO_STEP: {
+            SUB_PAGE_NAMES: {
+                NAME: 'name',
+                TAX_ID: 'tax-id',
+                WEBSITE: 'website',
+                PHONE: 'phone',
+                ADDRESS: 'address',
+                TYPE: 'type',
+                INCORPORATION_DATE: 'start-date',
+                INCORPORATION_STATE: 'state',
+                INCORPORATION_CODE: 'code',
+                CONFIRMATION: 'confirmation',
+            },
+        },
+        BENEFICIAL_OWNERS_STEP: {
+            SUB_PAGE_NAMES: {
+                IS_USER_UBO: 'is-user-ubo',
+                IS_ANYONE_ELSE_UBO: 'is-anyone-else-ubo',
+                ARE_THERE_MORE_UBOS: 'are-there-more-ubos',
+                UBOS_LIST: 'ubos-list',
+                LEGAL_NAME: 'legal-name',
+                DATE_OF_BIRTH: 'date-of-birth',
+                SSN: 'ssn',
+                ADDRESS: 'address',
+                CONFIRMATION: 'confirmation',
+            },
+        },
+        COMPLETE_VERIFICATION_STEP: {
+            SUB_PAGE_NAMES: {
+                CONFIRM_AGREEMENTS: 'confirm-agreements',
+            },
+        },
         SUBSTEP: {
             MANUAL: 'manual',
             PLAID: 'plaid',
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 92c5f63aa775..290b780e3b0f 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -13,7 +13,6 @@ import type {IOUAction, IOURequestType, IOUType, OdometerImageType} from './CONS
 import type {ReplacementReason} from './libs/actions/Card';
 import Log from './libs/Log';
 import type {RootNavigatorParamList} from './libs/Navigation/types';
-import type {ReimbursementAccountStepToOpen} from './libs/ReimbursementAccountUtils';
 import StringUtils from './libs/StringUtils';
 import {getUrlWithParams} from './libs/Url';
 import SCREENS from './SCREENS';
@@ -864,34 +863,22 @@ const ROUTES = {
 
         getRoute: (policyID?: string, backTo?: string) => getUrlWithBackToParam(`bank-account/${VERIFY_ACCOUNT}?policyID=${policyID}`, backTo),
     },
-    BANK_ACCOUNT_NEW: 'bank-account/new',
     BANK_ACCOUNT_PERSONAL: 'bank-account/personal',
+    // TODO: rename the route as no longer accepts step
     BANK_ACCOUNT_WITH_STEP_TO_OPEN: {
-        route: 'bank-account/:stepToOpen?',
-        getRoute: ({
-            policyID,
-            stepToOpen = '',
-            bankAccountID,
-            backTo,
-            subStepToOpen,
-        }: {
-            policyID: string | undefined;
-            stepToOpen?: ReimbursementAccountStepToOpen;
-            bankAccountID?: number;
-            backTo?: string;
-            subStepToOpen?: typeof CONST.BANK_ACCOUNT.STEP.COUNTRY;
-        }) => {
+        route: 'bank-account/new',
+        getRoute: ({policyID, bankAccountID, backTo}: {policyID: string | undefined; bankAccountID?: number; backTo?: string}) => {
             if (!policyID && !bankAccountID) {
-                return getUrlWithBackToParam(`bank-account/${stepToOpen}`, backTo);
+                return getUrlWithBackToParam(`bank-account/new`, backTo);
             }
 
             if (bankAccountID) {
-                return getUrlWithBackToParam(`bank-account/${stepToOpen}?bankAccountID=${bankAccountID}`, backTo);
+                return getUrlWithBackToParam(`bank-account/new?bankAccountID=${bankAccountID}`, backTo);
             }
             // TODO this backTo comes from drilling it through bank account form screens
             // should be removed once https://github.com/Expensify/App/pull/72219 is resolved
 
-            return getUrlWithBackToParam(`bank-account/${stepToOpen}?policyID=${policyID}${subStepToOpen ? `&subStep=${subStepToOpen}` : ''}`, backTo);
+            return getUrlWithBackToParam(`bank-account/new?policyID=${policyID}`, backTo);
         },
     },
     BANK_ACCOUNT_ENTER_SIGNER_INFO: {
@@ -921,6 +908,18 @@ const ROUTES = {
             return getUrlWithBackToParam(`${base}${pagePart}${subPagePart}${actionPart}${queryString}`, backTo);
         },
     },
+    BANK_ACCOUNT_USD_SETUP: {
+        route: 'bank-account/new/us/:page?/:subPage?/:action?',
+        getRoute: ({policyID, page, subPage, action, backTo}: {policyID?: string; page?: string; subPage?: string; action?: 'edit'; backTo?: string}) => {
+            const base = 'bank-account/new/us';
+            const pagePart = page ? `/${page}` : '';
+            const subPagePart = subPage ? `/${subPage}` : '';
+            const actionPart = action ? `/${action}` : '';
+            const queryString = policyID ? `?policyID=${policyID}` : '';
+            // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
+            return getUrlWithBackToParam(`${base}${pagePart}${subPagePart}${actionPart}${queryString}`, backTo);
+        },
+    },
     SETTINGS: 'settings',
     SETTINGS_PROFILE: {
         route: 'settings/profile',
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 3ec194ad5a61..8b16aaf10c0e 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -1001,6 +1001,7 @@ const SCREENS = {
     DYNAMIC_PRIVATE_NOTES_LIST: 'Dynamic_PrivateNotes_List',
     DYNAMIC_PRIVATE_NOTES_EDIT: 'Dynamic_PrivateNotes_Edit',
     REIMBURSEMENT_ACCOUNT: 'ReimbursementAccount',
+    REIMBURSEMENT_ACCOUNT_USD: 'Reimbursement_Account_USD',
     REIMBURSEMENT_ACCOUNT_NON_USD: 'Reimbursement_Account_Non_USD',
     REIMBURSEMENT_ACCOUNT_ENTER_SIGNER_INFO: 'Reimbursement_Account_Signer_Info',
     REFERRAL_DETAILS: 'Referral_Details',
diff --git a/src/components/Navigation/DebugTabView.tsx b/src/components/Navigation/DebugTabView.tsx
index 454123719a64..9280c430554b 100644
--- a/src/components/Navigation/DebugTabView.tsx
+++ b/src/components/Navigation/DebugTabView.tsx
@@ -97,10 +97,7 @@ function getSettingsRoute(status: IndicatorStatus | undefined, reimbursementAcco
         case CONST.INDICATOR_STATUS.HAS_POLICY_ERRORS:
             return ROUTES.WORKSPACE_INITIAL.getRoute(policyIDWithErrors);
         case CONST.INDICATOR_STATUS.HAS_REIMBURSEMENT_ACCOUNT_ERRORS:
-            return ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
-                policyID: reimbursementAccount?.achData?.policyID,
-                stepToOpen: getReimbursementAccountRouteForCurrentStep(reimbursementAccount?.achData?.currentStep ?? CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT),
-            });
+            return ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID: reimbursementAccount?.achData?.policyID});
         case CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_ERRORS:
             return ROUTES.SETTINGS_SUBSCRIPTION.route;
         case CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_INFO:
diff --git a/src/hooks/useReimbursementAccountSubmitCallback.ts b/src/hooks/useReimbursementAccountSubmitCallback.ts
new file mode 100644
index 000000000000..90fdc0026166
--- /dev/null
+++ b/src/hooks/useReimbursementAccountSubmitCallback.ts
@@ -0,0 +1,28 @@
+import {useCallback, useEffect, useRef} from 'react';
+import ONYXKEYS from '@src/ONYXKEYS';
+import useOnyx from './useOnyx';
+
+/**
+ * Defers navigation (onSubmit) until the reimbursement account API call completes.
+ * Instead of navigating to the next step immediately after firing the API call,
+ * this hook waits for `isLoading` to go back to `false` and checks for errors.
+ *
+ * @param onSubmit - callback that navigates to the next step
+ * @returns markSubmitting - call this right after firing the API action
+ */
+export default function useReimbursementAccountSubmitCallback(onSubmit?: () => void) {
+    const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
+    const isSubmittingRef = useRef(false);
+
+    useEffect(() => {
+        if (!isSubmittingRef.current || reimbursementAccount?.isLoading || reimbursementAccount?.errors) {
+            return;
+        }
+        isSubmittingRef.current = false;
+        onSubmit?.();
+    }, [reimbursementAccount?.isLoading, reimbursementAccount?.errors, onSubmit]);
+
+    return useCallback(() => {
+        isSubmittingRef.current = true;
+    }, []);
+}
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index c68128702d8c..a401d3580ca7 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -4,6 +4,7 @@ import {View} from 'react-native';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
 import withAgentAccessDenied from '@libs/Navigation/AppNavigator/withAgentAccessDenied';
+import {isMobileChrome} from '@libs/Browser';
 import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator';
 import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation';
 import type {PlatformStackNavigationOptions} from '@libs/Navigation/PlatformStackNavigation/types';
@@ -64,6 +65,17 @@ const loadAttachmentModalScreen = () => require<ReactComponentModule>('../../../
 
 type Screens = Partial<Record<Screen, () => React.ComponentType>>;
 
+// Reimbursement Account flow animations glitch on low-end Android devices in Chrome mWeb https://github.com/Expensify/App/issues/87658 so we intentionally disable them
+const IS_MOBILE_CHROME = isMobileChrome();
+
+const REIMBURSEMENT_ACCOUNT_FLOW_SCREENS: Screen[] = [
+    SCREENS.REIMBURSEMENT_ACCOUNT,
+    SCREENS.REIMBURSEMENT_ACCOUNT_USD,
+    SCREENS.REIMBURSEMENT_ACCOUNT_NON_USD,
+    SCREENS.REIMBURSEMENT_ACCOUNT_VERIFY_ACCOUNT,
+    SCREENS.REIMBURSEMENT_ACCOUNT_ENTER_SIGNER_INFO,
+];
+
 const OPTIONS_PER_SCREEN: Partial<Record<Screen, PlatformStackNavigationOptions>> = {
     [SCREENS.SETTINGS.MERGE_ACCOUNTS.MERGE_RESULT]: {
         animationTypeForReplace: 'push',
@@ -131,6 +143,7 @@ const OPTIONS_PER_SCREEN: Partial<Record<Screen, PlatformStackNavigationOptions>
     [SCREENS.TWO_FACTOR_AUTH.SUCCESS]: {
         animationTypeForReplace: 'push',
     },
+    ...(IS_MOBILE_CHROME ? Object.fromEntries(REIMBURSEMENT_ACCOUNT_FLOW_SCREENS.map((screen) => [screen, {animation: Animations.NONE}])) : {}),
 };
 
 /**
@@ -740,6 +753,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_ITEMS]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage').default,
     [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: () => require<ReactComponentModule>('@pages/workspace/ConnectExistingBusinessBankAccountPage').default,
     [SCREENS.REIMBURSEMENT_ACCOUNT]: withAgentAccessDenied(() => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/ReimbursementAccountPage').default),
+    [SCREENS.REIMBURSEMENT_ACCOUNT_USD]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlowPage').default,
     [SCREENS.REIMBURSEMENT_ACCOUNT_NON_USD]: withAgentAccessDenied(
         () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlowPage').default,
     ),
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 6d88c576a397..33e27496a2e2 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -1183,6 +1183,10 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                             path: ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.route,
                             exact: true,
                         },
+                        [SCREENS.REIMBURSEMENT_ACCOUNT_USD]: {
+                            path: ROUTES.BANK_ACCOUNT_USD_SETUP.route,
+                            exact: true,
+                        },
                         [SCREENS.REIMBURSEMENT_ACCOUNT_NON_USD]: {
                             path: ROUTES.BANK_ACCOUNT_NON_USD_SETUP.route,
                             exact: true,
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 3a3d2525d0e6..8f855f69817c 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -2321,6 +2321,14 @@ type ReimbursementAccountNavigatorParamList = {
         bankAccountID?: string;
         subStep?: typeof CONST.BANK_ACCOUNT.STEP.COUNTRY;
     };
+    [SCREENS.REIMBURSEMENT_ACCOUNT_USD]: {
+        page?: string;
+        subPage?: string;
+        action?: 'edit';
+        policyID?: string;
+        // eslint-disable-next-line no-restricted-syntax -- backTo is a temporary param will be removed after https://github.com/Expensify/App/issues/73825 is done
+        backTo?: Routes;
+    };
     [SCREENS.REIMBURSEMENT_ACCOUNT_NON_USD]: {
         page?: string;
         subPage?: string;
diff --git a/src/libs/ReimbursementAccountUtils.ts b/src/libs/ReimbursementAccountUtils.ts
index e0f1dd03be60..4bce69e731c0 100644
--- a/src/libs/ReimbursementAccountUtils.ts
+++ b/src/libs/ReimbursementAccountUtils.ts
@@ -1,6 +1,6 @@
 import type {ValueOf} from 'type-fest';
 import CONST from '@src/CONST';
-import type {ACHDataReimbursementAccount, ReimbursementAccountStep} from '@src/types/onyx/ReimbursementAccount';
+import type {ACHDataReimbursementAccount} from '@src/types/onyx/ReimbursementAccount';
 
 type ReimbursementAccountStepToOpen = ValueOf<typeof REIMBURSEMENT_ACCOUNT_ROUTE_NAMES> | '';
 
@@ -14,27 +14,6 @@ const REIMBURSEMENT_ACCOUNT_ROUTE_NAMES = {
     NEW: 'new',
 } as const;
 
-function getRouteForCurrentStep(currentStep: ReimbursementAccountStep): ReimbursementAccountStepToOpen {
-    switch (currentStep) {
-        case CONST.BANK_ACCOUNT.STEP.COMPANY:
-            return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.COMPANY;
-        case CONST.BANK_ACCOUNT.STEP.REQUESTOR:
-            return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.PERSONAL_INFORMATION;
-        case CONST.BANK_ACCOUNT.STEP.BENEFICIAL_OWNERS:
-            return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.BENEFICIAL_OWNERS;
-        case CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT:
-            return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.CONTRACT;
-        case CONST.BANK_ACCOUNT.STEP.VALIDATION:
-            return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.VALIDATE;
-        case CONST.BANK_ACCOUNT.STEP.ENABLE:
-            return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.ENABLE;
-        case CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT:
-        case CONST.BANK_ACCOUNT.STEP.COUNTRY:
-        default:
-            return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW;
-    }
-}
-
 /**
  * Returns true if a VBBA exists in any state other than OPEN or LOCKED
  */
@@ -67,5 +46,5 @@ const hasInProgressVBBA = (achData?: ACHDataReimbursementAccount, isNonUSDWorksp
     return hasInProgressUSDVBBA(achData);
 };
 
-export {getBankAccountIDAsNumber, getRouteForCurrentStep, hasInProgressUSDVBBA, hasInProgressVBBA, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES};
+export {getBankAccountIDAsNumber, hasInProgressUSDVBBA, hasInProgressVBBA, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES};
 export type {ReimbursementAccountStepToOpen};
diff --git a/src/pages/ReimbursementAccount/ConnectedVerifiedBankAccount.tsx b/src/pages/ReimbursementAccount/ConnectedVerifiedBankAccount.tsx
index a426ad5ffa4f..50f622603918 100644
--- a/src/pages/ReimbursementAccount/ConnectedVerifiedBankAccount.tsx
+++ b/src/pages/ReimbursementAccount/ConnectedVerifiedBankAccount.tsx
@@ -27,10 +27,10 @@ type ConnectedVerifiedBankAccountProps = {
     onBackButtonPress: () => void;
 
     /** Method to set the state of shouldShowConnectedVerifiedBankAccount */
-    setShouldShowConnectedVerifiedBankAccount: (shouldShowConnectedVerifiedBankAccount: boolean) => void;
+    setShouldShowConnectedVerifiedBankAccount?: (shouldShowConnectedVerifiedBankAccount: boolean) => void;
 
     /** Method to set the state of USD bank account step */
-    setUSDBankAccountStep: (step: string | null) => void;
+    setUSDBankAccountStep?: (step: string | null) => void;
 
     /** Whether the workspace currency is set to non USD currency */
     isNonUSDWorkspace: boolean;
diff --git a/src/pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlowPage.tsx b/src/pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlowPage.tsx
index 8d675eac39e9..f8b065860289 100644
--- a/src/pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlowPage.tsx
+++ b/src/pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlowPage.tsx
@@ -121,7 +121,7 @@ function NonUSDVerifiedBankAccountFlowPage({route}: NonUSDVerifiedBankAccountFlo
     }, [backTo, currentPageIndex, pages, policyID]);
 
     return (
-        <View style={styles.flex1}>
+        <View style={[styles.flex1, styles.appBG]}>
             <CurrentPage
                 onSubmit={onSubmit}
                 onBackButtonPress={onBackButtonPress}
diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx b/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx
index d5fa72a4d1fc..e70826be0f45 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 {getRouteForCurrentStep, hasInProgressUSDVBBA, hasInProgressVBBA} from '@libs/ReimbursementAccountUtils';
+import {hasInProgressUSDVBBA, hasInProgressVBBA} from '@libs/ReimbursementAccountUtils';
 import shouldReopenOnfido from '@libs/shouldReopenOnfido';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {isFullScreenName} from '@navigation/helpers/isNavigatorName';
@@ -60,7 +60,6 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 import ConnectedVerifiedBankAccount from './ConnectedVerifiedBankAccount';
 import getStartPageForContinueSetup from './NonUSD/utils/getStartPageForContinueSetup';
-import USDVerifiedBankAccountFlow from './USD/USDVerifiedBankAccountFlow';
 import getFieldsForStep from './USD/utils/getFieldsForStep';
 import getStepToOpenFromRouteParams from './USD/utils/getStepToOpenFromRouteParams';
 import VerifiedBankAccountFlowEntryPoint from './VerifiedBankAccountFlowEntryPoint';
@@ -77,7 +76,7 @@ const OFFLINE_ACCESSIBLE_STEPS = [
     CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT,
 ] as const;
 
-function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}: ReimbursementAccountPageProps) {
+function ReimbursementAccountPage({route, policy, isLoadingPolicy}: ReimbursementAccountPageProps) {
     const {environmentURL} = useEnvironment();
     const session = useSession();
     const [reimbursementAccount, reimbursementAccountMetadata] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
@@ -332,12 +331,6 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
                 // so we don't clear it. We only want to clear the errors if we are moving between steps.
                 hideBankAccountErrors();
             }
-
-            // Use the current page navigation object to set the param to the correct route in the stack
-            const stepToOpen = getRouteForCurrentStep(currentStep);
-            if (stepToOpen && !isNonUSDSetup) {
-                navigation.setParams({stepToOpen});
-            }
         },
         // eslint-disable-next-line react-hooks/exhaustive-deps
         [
@@ -356,10 +349,19 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
         // If user comes back to the flow we never want to allow him to go through plaid again
         // so we're always showing manual setup with locked numbers he can not change
         setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL).then(() => {
-            setShouldShowContinueSetupButton(false);
-            setUSDBankAccountStep(currentStep);
+            const stepToPageName: Record<string, string> = {
+                [CONST.BANK_ACCOUNT.STEP.COUNTRY]: CONST.BANK_ACCOUNT.PAGE_NAMES.COUNTRY,
+                [CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT]: CONST.BANK_ACCOUNT.PAGE_NAMES.BANK_ACCOUNT,
+                [CONST.BANK_ACCOUNT.STEP.REQUESTOR]: CONST.BANK_ACCOUNT.PAGE_NAMES.REQUESTOR,
+                [CONST.BANK_ACCOUNT.STEP.COMPANY]: CONST.BANK_ACCOUNT.PAGE_NAMES.COMPANY,
+                [CONST.BANK_ACCOUNT.STEP.BENEFICIAL_OWNERS]: CONST.BANK_ACCOUNT.PAGE_NAMES.BENEFICIAL_OWNERS,
+                [CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT]: CONST.BANK_ACCOUNT.PAGE_NAMES.ACH_CONTRACT,
+                [CONST.BANK_ACCOUNT.STEP.VALIDATION]: CONST.BANK_ACCOUNT.PAGE_NAMES.VALIDATION,
+            };
+            const page = stepToPageName[currentStep] ?? CONST.BANK_ACCOUNT.PAGE_NAMES.COUNTRY;
+            Navigation.navigate(ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID: policyIDParam, page, backTo}));
         });
-    }, [currentStep]);
+    }, [currentStep, policyIDParam, backTo]);
 
     const continueNonUSDVBBASetup = () => {
         const {page: startPage, subPage: startSubPage} = getStartPageForContinueSetup(achData, nonUSDCountryDraftValue, policyCurrency, reimbursementAccountDraft);
@@ -529,20 +531,6 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
         );
     }
 
-    if (!isNonUSDSetup && USDBankAccountStep !== null) {
-        return (
-            <USDVerifiedBankAccountFlow
-                USDBankAccountStep={USDBankAccountStep}
-                policyID={policyIDParam}
-                onBackButtonPress={goBack}
-                requestorStepRef={requestorStepRef}
-                onfidoToken={onfidoToken}
-                setUSDBankAccountStep={setUSDBankAccountStep}
-                setShouldShowConnectedVerifiedBankAccount={setShouldShowConnectedVerifiedBankAccount}
-            />
-        );
-    }
-
     return (
         <VerifiedBankAccountFlowEntryPoint
             setShouldShowContinueSetupButton={setShouldShowContinueSetupButton}
diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountVerifyAccountPage.tsx b/src/pages/ReimbursementAccount/ReimbursementAccountVerifyAccountPage.tsx
index 819f5c75c041..f7f5e8be32b7 100644
--- a/src/pages/ReimbursementAccount/ReimbursementAccountVerifyAccountPage.tsx
+++ b/src/pages/ReimbursementAccount/ReimbursementAccountVerifyAccountPage.tsx
@@ -3,7 +3,6 @@ import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import VerifyAccountPageBase from '@pages/settings/VerifyAccountPageBase';
-import CONST from '@src/CONST';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 
@@ -15,7 +14,7 @@ function ReimbursementAccountVerifyAccountPage({route}: ReimbursementAccountVeri
         <VerifyAccountPageBase
             navigateBackTo={ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID, backTo})}
             handleClose={() => {
-                Navigation.goBack(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID, backTo, subStepToOpen: CONST.BANK_ACCOUNT.STEP.COUNTRY}), {compareParams: false});
+                Navigation.goBack(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID, backTo}), {compareParams: false});
             }}
         />
     );
diff --git a/src/pages/ReimbursementAccount/USD/BankInfo/BankInfo.tsx b/src/pages/ReimbursementAccount/USD/BankInfo/BankInfo.tsx
index 8ff529ef084d..a5b3dc71988f 100644
--- a/src/pages/ReimbursementAccount/USD/BankInfo/BankInfo.tsx
+++ b/src/pages/ReimbursementAccount/USD/BankInfo/BankInfo.tsx
@@ -2,8 +2,7 @@ import React, {useEffect, useRef} from 'react';
 import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import useSubStep from '@hooks/useSubStep';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import useReimbursementAccountSubmitCallback from '@hooks/useReimbursementAccountSubmitCallback';
 import getPlaidOAuthReceivedRedirectURI from '@libs/getPlaidOAuthReceivedRedirectURI';
 import {getBankAccountIDAsNumber} from '@libs/ReimbursementAccountUtils';
 import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues';
@@ -20,27 +19,22 @@ type BankInfoProps = {
     /** Goes to the previous step */
     onBackButtonPress: () => void;
 
+    /** Handles submit button press (URL-based navigation) */
+    onSubmit?: () => void;
+
     /** Current Policy ID */
     policyID: string;
-
-    /** Set the step of the USD verified bank account flow */
-    setUSDBankAccountStep: (step: string | null) => void;
-};
-
-type BankInfoSubStepProps = SubStepProps & {
-    setUSDBankAccountStep: (step: string | null) => void;
 };
 
 const BANK_INFO_STEP_KEYS = INPUT_IDS.BANK_INFO_STEP;
-const manualSubSteps: Array<React.ComponentType<BankInfoSubStepProps>> = [Manual];
-const plaidSubSteps: Array<React.ComponentType<BankInfoSubStepProps>> = [Plaid];
 const receivedRedirectURI = getPlaidOAuthReceivedRedirectURI();
 
-function BankInfo({onBackButtonPress, policyID, setUSDBankAccountStep}: BankInfoProps) {
+function BankInfo({onBackButtonPress, onSubmit, policyID}: BankInfoProps) {
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
     const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT);
     const [plaidLinkToken] = useOnyx(ONYXKEYS.RAM_ONLY_PLAID_LINK_TOKEN);
     const {translate} = useLocalize();
+    const markSubmitting = useReimbursementAccountSubmitCallback(onSubmit);
 
     const redirectedFromPlaidToManualRef = useRef(false);
     const values = getSubStepValues(BANK_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount ?? {});
@@ -90,10 +84,10 @@ function BankInfo({onBackButtonPress, policyID, setUSDBankAccountStep}: BankInfo
                 policyID,
             );
         }
+        markSubmitting();
     };
 
-    const bodyContent = setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID ? plaidSubSteps : manualSubSteps;
-    const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep<BankInfoSubStepProps>({bodyContent, startFrom: 0, onFinished: submit});
+    const BankInfoPage = setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID ? Plaid : Manual;
 
     // Some services user connects to via Plaid return dummy account numbers and routing numbers e.g. Chase
     // In this case we need to redirect user to manual flow to enter real account number and routing number
@@ -108,12 +102,8 @@ function BankInfo({onBackButtonPress, policyID, setUSDBankAccountStep}: BankInfo
     }, [setupType, values.bankName]);
 
     const handleBackButtonPress = () => {
-        if (screenIndex === 0) {
-            onBackButtonPress();
-            hideBankAccountErrors();
-        } else {
-            prevScreen();
-        }
+        onBackButtonPress();
+        hideBankAccountErrors();
     };
 
     return (
@@ -125,12 +115,7 @@ function BankInfo({onBackButtonPress, policyID, setUSDBankAccountStep}: BankInfo
             startStepIndex={1}
             stepNames={CONST.BANK_ACCOUNT.STEP_NAMES}
         >
-            <SubStep
-                isEditing={isEditing}
-                onNext={nextScreen}
-                onMove={moveTo}
-                setUSDBankAccountStep={setUSDBankAccountStep}
-            />
+            <BankInfoPage onNext={submit} />
         </InteractiveStepWrapper>
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Manual.tsx b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Manual.tsx
index 6e89550cb6d8..53a090418c49 100644
--- a/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Manual.tsx
+++ b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Manual.tsx
@@ -8,21 +8,19 @@ import useAutoFocusInput from '@hooks/useAutoFocusInput';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getFieldRequiredErrors, isValidRoutingNumber} from '@libs/ValidationUtils';
 import ExampleCheckImage from '@pages/ReimbursementAccount/USD/BankInfo/ExampleCheck';
+import type BankInfoSubStepProps from '@pages/ReimbursementAccount/USD/BankInfo/types';
 import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
 
-type ManualProps = SubStepProps;
-
 const BANK_INFO_STEP_KEYS = INPUT_IDS.BANK_INFO_STEP;
 const STEP_FIELDS = [BANK_INFO_STEP_KEYS.ROUTING_NUMBER, BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER];
 
-function Manual({onNext}: ManualProps) {
+function Manual({onNext}: BankInfoSubStepProps) {
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
     const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT);
 
diff --git a/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx
index d1719b8047fa..b64b07e70a45 100644
--- a/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx
+++ b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx
@@ -6,21 +6,17 @@ import InputWrapper from '@components/Form/InputWrapper';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import usePrevious from '@hooks/usePrevious';
-import type {SubStepProps} from '@hooks/useSubStep/types';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getBankAccountIDAsNumber} from '@libs/ReimbursementAccountUtils';
+import type BankInfoSubStepProps from '@pages/ReimbursementAccount/USD/BankInfo/types';
 import {setBankAccountSubStep, validatePlaidSelection} from '@userActions/BankAccounts';
 import {updateReimbursementAccountDraft} from '@userActions/ReimbursementAccount';
 import ONYXKEYS from '@src/ONYXKEYS';
 import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
 
-type PlaidProps = SubStepProps & {
-    setUSDBankAccountStep: (step: string | null) => void;
-};
-
 const BANK_INFO_STEP_KEYS = INPUT_IDS.BANK_INFO_STEP;
 
-function Plaid({onNext, setUSDBankAccountStep}: PlaidProps) {
+function Plaid({onNext}: BankInfoSubStepProps) {
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
     const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT);
     const [plaidData] = useOnyx(ONYXKEYS.PLAID_DATA);
@@ -61,12 +57,10 @@ function Plaid({onNext, setUSDBankAccountStep}: PlaidProps) {
             return;
         }
         setBankAccountSubStep(null);
-        setUSDBankAccountStep(null);
-    }, [isFocused, prevIsFocused, plaidData?.bankAccounts, setUSDBankAccountStep]);
+    }, [isFocused, prevIsFocused, plaidData?.bankAccounts]);
 
     const handlePlaidExit = () => {
         setBankAccountSubStep(null);
-        setUSDBankAccountStep(null);
     };
 
     return (
diff --git a/src/pages/ReimbursementAccount/USD/BankInfo/types.ts b/src/pages/ReimbursementAccount/USD/BankInfo/types.ts
new file mode 100644
index 000000000000..e79203da7611
--- /dev/null
+++ b/src/pages/ReimbursementAccount/USD/BankInfo/types.ts
@@ -0,0 +1,6 @@
+type BankInfoSubStepProps = {
+    /** Continues to the next step */
+    onNext: (data?: unknown) => void;
+};
+
+export default BankInfoSubStepProps;
diff --git a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnerDetailsFormPages.tsx b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnerDetailsFormPages.tsx
new file mode 100644
index 000000000000..5ea2a967a3ae
--- /dev/null
+++ b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnerDetailsFormPages.tsx
@@ -0,0 +1,123 @@
+import React, {useCallback} from 'react';
+import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
+import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import useSubPage from '@hooks/useSubPage';
+import type {SubPageProps} from '@hooks/useSubPage/types';
+import Navigation from '@libs/Navigation/Navigation';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import AddressUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/AddressUBO';
+import ConfirmationUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/ConfirmationUBO';
+import DateOfBirthUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/DateOfBirthUBO';
+import LegalNameUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/LegalNameUBO';
+import SocialSecurityNumberUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/SocialSecurityNumberUBO';
+
+const PAGE_NAMES = CONST.BANK_ACCOUNT.PAGE_NAMES;
+const SUB_PAGE_NAMES = CONST.BANK_ACCOUNT.BENEFICIAL_OWNERS_STEP.SUB_PAGE_NAMES;
+
+type BeneficialOwnerSubPageProps = SubPageProps & {
+    beneficialOwnerBeingModifiedID: string;
+    setBeneficialOwnerBeingModifiedID?: (id: string) => void;
+};
+
+const pages = [
+    {pageName: SUB_PAGE_NAMES.LEGAL_NAME, component: LegalNameUBO},
+    {pageName: SUB_PAGE_NAMES.DATE_OF_BIRTH, component: DateOfBirthUBO},
+    {pageName: SUB_PAGE_NAMES.SSN, component: SocialSecurityNumberUBO},
+    {pageName: SUB_PAGE_NAMES.ADDRESS, component: AddressUBO},
+    {pageName: SUB_PAGE_NAMES.CONFIRMATION, component: ConfirmationUBO},
+];
+
+type BeneficialOwnerDetailsFormPagesProps = {
+    /** ID of current policy */
+    policyID?: string;
+
+    /** ID of the beneficial owner being modified */
+    beneficialOwnerBeingModifiedID: string;
+
+    /** Setter for the beneficial owner being modified */
+    setBeneficialOwnerBeingModifiedID: (id: string) => void;
+
+    /** Whether user is editing an already-created beneficial owner */
+    isEditingCreatedBeneficialOwner: boolean;
+
+    /** Callback triggered after the last form page is completed */
+    onFinished: () => void;
+
+    /** Back to URL for preserving navigation context */
+    backTo?: string;
+};
+
+function BeneficialOwnerDetailsFormPages({
+    policyID,
+    beneficialOwnerBeingModifiedID,
+    setBeneficialOwnerBeingModifiedID,
+    isEditingCreatedBeneficialOwner,
+    onFinished,
+    backTo,
+}: BeneficialOwnerDetailsFormPagesProps) {
+    const {translate} = useLocalize();
+    const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT);
+    const hasExistingBeneficialOwners = (reimbursementAccountDraft?.beneficialOwnerKeys ?? []).length > 0;
+
+    const buildRoute = useCallback(
+        (pageName: string, action?: 'edit') => ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID, page: PAGE_NAMES.BENEFICIAL_OWNERS, subPage: pageName, action, backTo}),
+        [policyID, backTo],
+    );
+
+    const {CurrentPage, isEditing, currentPageName, pageIndex, prevPage, nextPage, moveTo, isRedirecting} = useSubPage<BeneficialOwnerSubPageProps>({
+        pages,
+        startFrom: 0,
+        onFinished,
+        buildRoute,
+    });
+
+    const handleBackButtonPress = useCallback(() => {
+        if (isEditing) {
+            Navigation.goBack(buildRoute(SUB_PAGE_NAMES.CONFIRMATION));
+            return;
+        }
+
+        if (pageIndex === 0) {
+            if (isEditingCreatedBeneficialOwner) {
+                Navigation.goBack(buildRoute(SUB_PAGE_NAMES.UBOS_LIST));
+            } else if (hasExistingBeneficialOwners) {
+                Navigation.goBack(buildRoute(SUB_PAGE_NAMES.ARE_THERE_MORE_UBOS));
+            } else {
+                Navigation.goBack(buildRoute(SUB_PAGE_NAMES.IS_ANYONE_ELSE_UBO));
+            }
+        } else {
+            prevPage();
+        }
+    }, [buildRoute, isEditing, isEditingCreatedBeneficialOwner, pageIndex, prevPage, hasExistingBeneficialOwners]);
+
+    if (isRedirecting) {
+        return <FullScreenLoadingIndicator reasonAttributes={{context: 'BeneficialOwnerDetailsFormPages', isRedirecting}} />;
+    }
+
+    return (
+        <InteractiveStepWrapper
+            wrapperID="BeneficialOwnersStep"
+            shouldEnablePickerAvoiding={false}
+            shouldEnableMaxHeight
+            headerTitle={translate('beneficialOwnerInfoStep.companyOwner')}
+            handleBackButtonPress={handleBackButtonPress}
+            startStepIndex={5}
+            stepNames={CONST.BANK_ACCOUNT.STEP_NAMES}
+        >
+            <CurrentPage
+                isEditing={isEditing}
+                onNext={nextPage}
+                onMove={moveTo}
+                currentPageName={currentPageName}
+                beneficialOwnerBeingModifiedID={beneficialOwnerBeingModifiedID}
+                setBeneficialOwnerBeingModifiedID={setBeneficialOwnerBeingModifiedID}
+            />
+        </InteractiveStepWrapper>
+    );
+}
+
+export default BeneficialOwnerDetailsFormPages;
diff --git a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnersStep.tsx b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnersStep.tsx
index 83e6e31c1616..ee0f5404c74b 100644
--- a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnersStep.tsx
+++ b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnersStep.tsx
@@ -1,37 +1,46 @@
 import {Str} from 'expensify-common';
-import React, {useState} from 'react';
+import React, {useCallback, useEffect} from 'react';
 import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import YesNoStep from '@components/SubStepForms/YesNoStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import useSubStep from '@hooks/useSubStep';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import useReimbursementAccountSubmitCallback from '@hooks/useReimbursementAccountSubmitCallback';
 import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
 import {getBankAccountIDAsNumber} from '@libs/ReimbursementAccountUtils';
 import {updateBeneficialOwnersForBankAccount} from '@userActions/BankAccounts';
 import {setDraftValues} from '@userActions/FormActions';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import SafeString from '@src/utils/SafeString';
-import AddressUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/AddressUBO';
-import ConfirmationUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/ConfirmationUBO';
-import DateOfBirthUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/DateOfBirthUBO';
-import LegalNameUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/LegalNameUBO';
-import SocialSecurityNumberUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/SocialSecurityNumberUBO';
+import BeneficialOwnerDetailsFormPages from './BeneficialOwnerDetailsFormPages';
 import CompanyOwnersListUBO from './subSteps/CompanyOwnersListUBO';
 
 type BeneficialOwnersStepProps = {
     /** Goes to the previous step */
     onBackButtonPress: () => void;
-};
 
-type BeneficialOwnerSubStepProps = SubStepProps & {beneficialOwnerBeingModifiedID: string; setBeneficialOwnerBeingModifiedID?: (id: string) => void};
+    /** Handles submit button press (URL-based navigation) */
+    onSubmit?: () => void;
+
+    /** Name of the current sub page */
+    currentSubPage?: string;
+
+    /** ID of current policy */
+    policyID?: string;
+
+    /** Back to URL for preserving navigation context */
+    backTo?: string;
+};
 
-const SUBSTEP = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.SUBSTEP;
+const PAGE_NAMES = CONST.BANK_ACCOUNT.PAGE_NAMES;
+const SUB_PAGE_NAMES = CONST.BANK_ACCOUNT.BENEFICIAL_OWNERS_STEP.SUB_PAGE_NAMES;
 const MAX_NUMBER_OF_UBOS = 4;
-const bodyContent: Array<React.ComponentType<BeneficialOwnerSubStepProps>> = [LegalNameUBO, DateOfBirthUBO, SocialSecurityNumberUBO, AddressUBO, ConfirmationUBO];
 
-function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) {
+const OUTER_SUB_PAGES = new Set<string>([SUB_PAGE_NAMES.IS_USER_UBO, SUB_PAGE_NAMES.IS_ANYONE_ELSE_UBO, SUB_PAGE_NAMES.ARE_THERE_MORE_UBOS, SUB_PAGE_NAMES.UBOS_LIST]);
+
+function BeneficialOwnersStep({onBackButtonPress, onSubmit, currentSubPage, policyID, backTo}: BeneficialOwnersStepProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
 
@@ -39,27 +48,53 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) {
     const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT);
 
     const companyName = reimbursementAccount?.achData?.companyName ?? '';
-    const policyID = reimbursementAccount?.achData?.policyID;
-    const defaultValues = {
-        ownsMoreThan25Percent: reimbursementAccount?.achData?.ownsMoreThan25Percent ?? reimbursementAccountDraft?.ownsMoreThan25Percent ?? false,
-        hasOtherBeneficialOwners: reimbursementAccount?.achData?.hasOtherBeneficialOwners ?? reimbursementAccountDraft?.hasOtherBeneficialOwners ?? false,
-        beneficialOwnerKeys: reimbursementAccount?.achData?.beneficialOwnerKeys ?? reimbursementAccountDraft?.beneficialOwnerKeys ?? [],
-    };
-
-    // We're only reading beneficialOwnerKeys from draft values because there is not option to remove UBO
-    // if we were to set them based on values saved in BE then there would be no option to enter different UBOs
-    // user would always see the same UBOs that was saved in BE when returning to this step and trying to change something
-    const [beneficialOwnerKeys, setBeneficialOwnerKeys] = useState<string[]>(defaultValues.beneficialOwnerKeys);
-    const [beneficialOwnerBeingModifiedID, setBeneficialOwnerBeingModifiedID] = useState('');
-    const [isEditingCreatedBeneficialOwner, setIsEditingCreatedBeneficialOwner] = useState(false);
-    const [isUserUBO, setIsUserUBO] = useState(defaultValues.ownsMoreThan25Percent);
-    const [isAnyoneElseUBO, setIsAnyoneElseUBO] = useState(defaultValues.hasOtherBeneficialOwners);
-    const [currentUBOSubStep, setCurrentUBOSubStep] = useState(1);
+    const markSubmitting = useReimbursementAccountSubmitCallback(onSubmit);
+
+    // Read state from Onyx draft so it survives URL-based navigation (component remounts)
+    const isUserUBO = reimbursementAccountDraft?.ownsMoreThan25Percent ?? reimbursementAccount?.achData?.ownsMoreThan25Percent ?? false;
+    const beneficialOwners = reimbursementAccount?.achData?.beneficialOwners;
+    const isAnyoneElseUBO = beneficialOwners?.length ? true : (reimbursementAccountDraft?.hasOtherBeneficialOwners ?? false);
+    const beneficialOwnerKeys: string[] = reimbursementAccountDraft?.beneficialOwnerKeys ?? reimbursementAccount?.achData?.beneficialOwnerKeys ?? [];
+    // eslint-disable-next-line rulesdir/no-default-id-values
+    const beneficialOwnerBeingModifiedID = reimbursementAccountDraft?.ownerBeingModifiedID ?? '';
+    const isEditingCreatedBeneficialOwner = reimbursementAccountDraft?.isEditingCreatedOwner ?? false;
     const canAddMoreUBOS = beneficialOwnerKeys.length < (isUserUBO ? MAX_NUMBER_OF_UBOS - 1 : MAX_NUMBER_OF_UBOS);
 
+    const hasCompletedBeneficialOwnersStep = reimbursementAccount?.achData?.ownsMoreThan25Percent !== undefined;
+
+    // Redirect to the correct sub-page if no subPage is in the URL
+    useEffect(() => {
+        if (currentSubPage) {
+            return;
+        }
+
+        let subPage: string = SUB_PAGE_NAMES.IS_USER_UBO;
+        if (isUserUBO || (isAnyoneElseUBO && beneficialOwnerKeys.length > 0)) {
+            subPage = SUB_PAGE_NAMES.UBOS_LIST;
+        } else if (hasCompletedBeneficialOwnersStep) {
+            subPage = SUB_PAGE_NAMES.IS_ANYONE_ELSE_UBO;
+        }
+
+        Navigation.setParams({subPage} as Record<string, unknown>);
+    }, [currentSubPage, policyID, backTo, isAnyoneElseUBO, beneficialOwnerKeys.length, isUserUBO, hasCompletedBeneficialOwnersStep]);
+
+    const navigateToSubPage = useCallback(
+        (subPage: string) => {
+            Navigation.navigate(ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID, page: PAGE_NAMES.BENEFICIAL_OWNERS, subPage, backTo}));
+        },
+        [policyID, backTo],
+    );
+
+    const navigateBackToSubPage = useCallback(
+        (subPage: string) => {
+            Navigation.goBack(ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID, page: PAGE_NAMES.BENEFICIAL_OWNERS, subPage, backTo}));
+        },
+        [policyID, backTo],
+    );
+
     const submit = () => {
         const beneficialOwnerFields = ['firstName', 'lastName', 'dob', 'ssnLast4', 'street', 'city', 'state', 'zipCode'];
-        const beneficialOwners = beneficialOwnerKeys.map((ownerKey) =>
+        const beneficialOwnersData = beneficialOwnerKeys.map((ownerKey) =>
             beneficialOwnerFields.reduce(
                 (acc, fieldName) => {
                     acc[fieldName] = reimbursementAccountDraft ? SafeString(reimbursementAccountDraft[`beneficialOwner_${ownerKey}_${fieldName}`]) : undefined;
@@ -73,75 +108,56 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) {
             getBankAccountIDAsNumber(reimbursementAccount?.achData),
             {
                 ownsMoreThan25Percent: isUserUBO,
-                beneficialOwners: JSON.stringify(beneficialOwners),
+                beneficialOwners: JSON.stringify(beneficialOwnersData),
                 beneficialOwnerKeys,
             },
             policyID,
         );
+        markSubmitting();
     };
 
     const addBeneficialOwner = (beneficialOwnerID: string) => {
-        // Each beneficial owner is assigned a unique key that will connect it to values in saved ONYX.
-        // That way we can dynamically render each Identity Form based on which keys are present in the beneficial owners array.
         const newBeneficialOwners = [...beneficialOwnerKeys, beneficialOwnerID];
-
-        setBeneficialOwnerKeys(newBeneficialOwners);
-        setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {beneficialOwners: JSON.stringify(newBeneficialOwners)});
+        setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {beneficialOwnerKeys: newBeneficialOwners, beneficialOwners: JSON.stringify(newBeneficialOwners)});
     };
+
     const handleBeneficialOwnerDetailsFormSubmit = () => {
         const shouldAddBeneficialOwner = !beneficialOwnerKeys.find((beneficialOwnerID) => beneficialOwnerID === beneficialOwnerBeingModifiedID) && canAddMoreUBOS;
 
-        if (shouldAddBeneficialOwner) {
+        if (shouldAddBeneficialOwner && beneficialOwnerBeingModifiedID) {
             addBeneficialOwner(beneficialOwnerBeingModifiedID);
         }
 
-        // Because beneficialOwnerKeys array is not yet updated at this point we need to check against lower MAX_NUMBER_OF_UBOS (account for the one that is being added)
         const isLastUBOThatCanBeAdded = beneficialOwnerKeys.length === (isUserUBO ? MAX_NUMBER_OF_UBOS - 2 : MAX_NUMBER_OF_UBOS - 1);
-        setCurrentUBOSubStep(isEditingCreatedBeneficialOwner || isLastUBOThatCanBeAdded ? SUBSTEP.UBOS_LIST : SUBSTEP.ARE_THERE_MORE_UBOS);
-        setIsEditingCreatedBeneficialOwner(false);
+        const nextSubPage = isEditingCreatedBeneficialOwner || isLastUBOThatCanBeAdded ? SUB_PAGE_NAMES.UBOS_LIST : SUB_PAGE_NAMES.ARE_THERE_MORE_UBOS;
+        setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {isEditingCreatedOwner: false});
+        navigateToSubPage(nextSubPage);
     };
 
-    const {
-        componentToRender: BeneficialOwnerDetailsForm,
-        isEditing,
-        screenIndex,
-        nextScreen,
-        prevScreen,
-        moveTo,
-        resetScreenIndex,
-        goToTheLastStep,
-    } = useSubStep<BeneficialOwnerSubStepProps>({
-        bodyContent,
-        startFrom: 0,
-        onFinished: handleBeneficialOwnerDetailsFormSubmit,
-    });
-
     const prepareBeneficialOwnerDetailsForm = () => {
         const beneficialOwnerID = Str.guid();
-        setBeneficialOwnerBeingModifiedID(beneficialOwnerID);
-        // Reset Beneficial Owner Details Form to first subStep
-        resetScreenIndex();
-        setCurrentUBOSubStep(SUBSTEP.UBO_DETAILS_FORM);
+        setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {ownerBeingModifiedID: beneficialOwnerID});
+        navigateToSubPage(SUB_PAGE_NAMES.LEGAL_NAME);
     };
 
     const handleNextUBOSubstep = (value: boolean) => {
-        if (currentUBOSubStep === SUBSTEP.IS_USER_UBO) {
-            setIsUserUBO(value);
+        if (currentSubPage === SUB_PAGE_NAMES.IS_USER_UBO) {
+            setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {ownsMoreThan25Percent: value});
 
             // User is an owner but there are 4 other owners already added, so we remove last one
             if (value && beneficialOwnerKeys.length === 4) {
-                setBeneficialOwnerKeys((previousBeneficialOwners) => previousBeneficialOwners.slice(0, 3));
+                setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {beneficialOwnerKeys: beneficialOwnerKeys.slice(0, 3)});
             }
 
-            setCurrentUBOSubStep(SUBSTEP.IS_ANYONE_ELSE_UBO);
+            navigateToSubPage(SUB_PAGE_NAMES.IS_ANYONE_ELSE_UBO);
             return;
         }
 
-        if (currentUBOSubStep === SUBSTEP.IS_ANYONE_ELSE_UBO) {
-            setIsAnyoneElseUBO(value);
+        if (currentSubPage === SUB_PAGE_NAMES.IS_ANYONE_ELSE_UBO) {
+            setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {hasOtherBeneficialOwners: value});
 
             if (!canAddMoreUBOS && value) {
-                setCurrentUBOSubStep(SUBSTEP.UBOS_LIST);
+                navigateToSubPage(SUB_PAGE_NAMES.UBOS_LIST);
                 return;
             }
 
@@ -150,66 +166,62 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) {
                 return;
             }
 
-            // User is not an owner and no one else is an owner
             if (!isUserUBO && !value) {
                 submit();
                 return;
             }
 
-            // User is an owner and no one else is an owner
             if (isUserUBO && !value) {
-                setCurrentUBOSubStep(SUBSTEP.UBOS_LIST);
+                navigateToSubPage(SUB_PAGE_NAMES.UBOS_LIST);
                 return;
             }
         }
 
-        // Are there more UBOs
-        if (currentUBOSubStep === SUBSTEP.ARE_THERE_MORE_UBOS) {
+        if (currentSubPage === SUB_PAGE_NAMES.ARE_THERE_MORE_UBOS) {
             if (value) {
                 prepareBeneficialOwnerDetailsForm();
                 return;
             }
-            setCurrentUBOSubStep(SUBSTEP.UBOS_LIST);
-            return;
-        }
-
-        // User reached the limit of UBOs
-        if (currentUBOSubStep === SUBSTEP.UBO_DETAILS_FORM && !canAddMoreUBOS) {
-            setCurrentUBOSubStep(SUBSTEP.UBOS_LIST);
+            navigateToSubPage(SUB_PAGE_NAMES.UBOS_LIST);
         }
     };
 
     const handleBackButtonPress = () => {
-        if (isEditing) {
-            goToTheLastStep();
-            return;
-        }
-
-        // User goes back to previous step
-        if (currentUBOSubStep === SUBSTEP.IS_USER_UBO) {
+        if (currentSubPage === SUB_PAGE_NAMES.IS_USER_UBO) {
             onBackButtonPress();
-            // User reached limit of UBOs and goes back to initial question about additional UBOs
-        } else if (currentUBOSubStep === SUBSTEP.UBOS_LIST && !canAddMoreUBOS) {
-            setCurrentUBOSubStep(SUBSTEP.IS_ANYONE_ELSE_UBO);
-            // User goes back to last radio button
-        } else if (currentUBOSubStep === SUBSTEP.UBOS_LIST && isAnyoneElseUBO) {
-            setCurrentUBOSubStep(SUBSTEP.ARE_THERE_MORE_UBOS);
-        } else if (currentUBOSubStep === SUBSTEP.UBOS_LIST && isUserUBO && !isAnyoneElseUBO) {
-            setCurrentUBOSubStep(SUBSTEP.IS_ANYONE_ELSE_UBO);
-            // User moves between subSteps of beneficial owner details form
-        } else if (currentUBOSubStep === SUBSTEP.UBO_DETAILS_FORM && screenIndex > 0) {
-            prevScreen();
+        } else if (currentSubPage === SUB_PAGE_NAMES.IS_ANYONE_ELSE_UBO) {
+            navigateBackToSubPage(SUB_PAGE_NAMES.IS_USER_UBO);
+        } else if (currentSubPage === SUB_PAGE_NAMES.UBOS_LIST && !canAddMoreUBOS) {
+            navigateBackToSubPage(SUB_PAGE_NAMES.IS_ANYONE_ELSE_UBO);
+        } else if (currentSubPage === SUB_PAGE_NAMES.UBOS_LIST && isAnyoneElseUBO) {
+            navigateBackToSubPage(SUB_PAGE_NAMES.ARE_THERE_MORE_UBOS);
+        } else if (currentSubPage === SUB_PAGE_NAMES.UBOS_LIST && isUserUBO && !isAnyoneElseUBO) {
+            navigateBackToSubPage(SUB_PAGE_NAMES.IS_ANYONE_ELSE_UBO);
         } else {
-            setCurrentUBOSubStep((currentSubstep) => currentSubstep - 1);
+            Navigation.goBack();
         }
     };
 
     const handleUBOEdit = (beneficialOwnerID: string) => {
-        setBeneficialOwnerBeingModifiedID(beneficialOwnerID);
-        setIsEditingCreatedBeneficialOwner(true);
-        setCurrentUBOSubStep(SUBSTEP.UBO_DETAILS_FORM);
+        setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {ownerBeingModifiedID: beneficialOwnerID, isEditingCreatedOwner: true});
+        navigateToSubPage(SUB_PAGE_NAMES.LEGAL_NAME);
     };
 
+    // If the current sub page is not an outer page, render the details form
+    if (currentSubPage && !OUTER_SUB_PAGES.has(currentSubPage)) {
+        return (
+            <BeneficialOwnerDetailsFormPages
+                policyID={policyID}
+                beneficialOwnerBeingModifiedID={beneficialOwnerBeingModifiedID}
+                // eslint-disable-next-line @typescript-eslint/no-misused-promises
+                setBeneficialOwnerBeingModifiedID={(id: string) => setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {ownerBeingModifiedID: id})}
+                isEditingCreatedBeneficialOwner={isEditingCreatedBeneficialOwner}
+                onFinished={handleBeneficialOwnerDetailsFormSubmit}
+                backTo={backTo}
+            />
+        );
+    }
+
     return (
         <InteractiveStepWrapper
             wrapperID="BeneficialOwnersStep"
@@ -217,11 +229,11 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) {
             shouldEnableMaxHeight
             headerTitle={translate('beneficialOwnerInfoStep.companyOwner')}
             handleBackButtonPress={handleBackButtonPress}
-            shouldShowOfflineIndicatorInWideScreen={currentUBOSubStep === SUBSTEP.UBOS_LIST}
+            shouldShowOfflineIndicatorInWideScreen={currentSubPage === SUB_PAGE_NAMES.UBOS_LIST}
             startStepIndex={5}
             stepNames={CONST.BANK_ACCOUNT.STEP_NAMES}
         >
-            {currentUBOSubStep === SUBSTEP.IS_USER_UBO && (
+            {currentSubPage === SUB_PAGE_NAMES.IS_USER_UBO && (
                 <YesNoStep
                     title={translate('beneficialOwnerInfoStep.doYouOwn25percent', companyName)}
                     description={translate('beneficialOwnerInfoStep.regulationRequiresUsToVerifyTheIdentity')}
@@ -231,7 +243,7 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) {
                 />
             )}
 
-            {currentUBOSubStep === SUBSTEP.IS_ANYONE_ELSE_UBO && (
+            {currentSubPage === SUB_PAGE_NAMES.IS_ANYONE_ELSE_UBO && (
                 <YesNoStep
                     title={translate('beneficialOwnerInfoStep.doAnyIndividualOwn25percent', companyName)}
                     description={translate('beneficialOwnerInfoStep.regulationRequiresUsToVerifyTheIdentity')}
@@ -241,17 +253,7 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) {
                 />
             )}
 
-            {currentUBOSubStep === SUBSTEP.UBO_DETAILS_FORM && (
-                <BeneficialOwnerDetailsForm
-                    isEditing={isEditing}
-                    beneficialOwnerBeingModifiedID={beneficialOwnerBeingModifiedID}
-                    setBeneficialOwnerBeingModifiedID={setBeneficialOwnerBeingModifiedID}
-                    onNext={nextScreen}
-                    onMove={moveTo}
-                />
-            )}
-
-            {currentUBOSubStep === SUBSTEP.ARE_THERE_MORE_UBOS && (
+            {currentSubPage === SUB_PAGE_NAMES.ARE_THERE_MORE_UBOS && (
                 <YesNoStep
                     title={translate('beneficialOwnerInfoStep.areThereMoreIndividualsWhoOwn25percent', companyName)}
                     description={translate('beneficialOwnerInfoStep.regulationRequiresUsToVerifyTheIdentity')}
@@ -261,7 +263,7 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) {
                 />
             )}
 
-            {currentUBOSubStep === SUBSTEP.UBOS_LIST && (
+            {currentSubPage === SUB_PAGE_NAMES.UBOS_LIST && (
                 <CompanyOwnersListUBO
                     beneficialOwnerKeys={beneficialOwnerKeys}
                     handleUBOsConfirmation={submit}
diff --git a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/AddressUBO.tsx b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/AddressUBO.tsx
index 1f3507f8357a..03e1ad8a2494 100644
--- a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/AddressUBO.tsx
+++ b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/AddressUBO.tsx
@@ -3,7 +3,7 @@ import AddressStep from '@components/SubStepForms/AddressStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import SafeString from '@src/utils/SafeString';
@@ -11,7 +11,7 @@ import SafeString from '@src/utils/SafeString';
 const BENEFICIAL_OWNER_INFO_KEY = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.BENEFICIAL_OWNER_DATA;
 const BENEFICIAL_OWNER_PREFIX = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.BENEFICIAL_OWNER_DATA.PREFIX;
 
-type AddressUBOProps = SubStepProps & {beneficialOwnerBeingModifiedID: string};
+type AddressUBOProps = SubPageProps & {beneficialOwnerBeingModifiedID: string};
 
 function AddressUBO({onNext, onMove, isEditing, beneficialOwnerBeingModifiedID}: AddressUBOProps) {
     const {translate} = useLocalize();
diff --git a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/ConfirmationUBO.tsx b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/ConfirmationUBO.tsx
index 5534c513c721..db3260ed398c 100644
--- a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/ConfirmationUBO.tsx
+++ b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/ConfirmationUBO.tsx
@@ -2,13 +2,13 @@ import React from 'react';
 import ConfirmationStep from '@components/SubStepForms/ConfirmationStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import {getLatestErrorMessage} from '@libs/ErrorUtils';
 import getValuesForBeneficialOwner from '@pages/ReimbursementAccount/USD/utils/getValuesForBeneficialOwner';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 
-type ConfirmationUBOProps = SubStepProps & {beneficialOwnerBeingModifiedID: string};
+type ConfirmationUBOProps = SubPageProps & {beneficialOwnerBeingModifiedID: string};
 
 const UBO_STEP_INDEXES = CONST.REIMBURSEMENT_ACCOUNT.SUBSTEP_INDEX.UBO;
 
diff --git a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/DateOfBirthUBO.tsx b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/DateOfBirthUBO.tsx
index 8f824cf54334..9eb85e749b36 100644
--- a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/DateOfBirthUBO.tsx
+++ b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/DateOfBirthUBO.tsx
@@ -3,7 +3,7 @@ import DateOfBirthStep from '@components/SubStepForms/DateOfBirthStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import SafeString from '@src/utils/SafeString';
@@ -11,7 +11,7 @@ import SafeString from '@src/utils/SafeString';
 const DOB = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.BENEFICIAL_OWNER_DATA.DOB;
 const BENEFICIAL_OWNER_PREFIX = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.BENEFICIAL_OWNER_DATA.PREFIX;
 
-type DateOfBirthUBOProps = SubStepProps & {beneficialOwnerBeingModifiedID: string};
+type DateOfBirthUBOProps = SubPageProps & {beneficialOwnerBeingModifiedID: string};
 
 function DateOfBirthUBO({onNext, onMove, isEditing, beneficialOwnerBeingModifiedID}: DateOfBirthUBOProps) {
     const {translate} = useLocalize();
diff --git a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/LegalNameUBO.tsx b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/LegalNameUBO.tsx
index ac34d4e4132f..dcd23543abbd 100644
--- a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/LegalNameUBO.tsx
+++ b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/LegalNameUBO.tsx
@@ -4,7 +4,7 @@ import FullNameStep from '@components/SubStepForms/FullNameStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import SafeString from '@src/utils/SafeString';
@@ -12,7 +12,7 @@ import SafeString from '@src/utils/SafeString';
 const {FIRST_NAME, LAST_NAME} = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.BENEFICIAL_OWNER_DATA;
 const BENEFICIAL_OWNER_PREFIX = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.BENEFICIAL_OWNER_DATA.PREFIX;
 
-type LegalNameUBOProps = SubStepProps & {beneficialOwnerBeingModifiedID: string};
+type LegalNameUBOProps = SubPageProps & {beneficialOwnerBeingModifiedID: string};
 
 function LegalNameUBO({onNext, onMove, isEditing, beneficialOwnerBeingModifiedID}: LegalNameUBOProps) {
     const {translate} = useLocalize();
diff --git a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/SocialSecurityNumberUBO.tsx b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/SocialSecurityNumberUBO.tsx
index 84c8723cf296..2df5a39d837d 100644
--- a/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/SocialSecurityNumberUBO.tsx
+++ b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/subSteps/BeneficialOwnerDetailsFormSubSteps/SocialSecurityNumberUBO.tsx
@@ -4,7 +4,7 @@ import SingleFieldStep from '@components/SubStepForms/SingleFieldStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import {getFieldRequiredErrors, isValidSSNLastFour} from '@libs/ValidationUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -13,7 +13,7 @@ import SafeString from '@src/utils/SafeString';
 const SSN_LAST_4 = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.BENEFICIAL_OWNER_DATA.SSN_LAST_4;
 const BENEFICIAL_OWNER_PREFIX = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.BENEFICIAL_OWNER_DATA.PREFIX;
 
-type SocialSecurityNumberUBOProps = SubStepProps & {beneficialOwnerBeingModifiedID: string};
+type SocialSecurityNumberUBOProps = SubPageProps & {beneficialOwnerBeingModifiedID: string};
 
 function SocialSecurityNumberUBO({onNext, onMove, isEditing, beneficialOwnerBeingModifiedID}: SocialSecurityNumberUBOProps) {
     const {translate} = useLocalize();
@@ -54,6 +54,7 @@ function SocialSecurityNumberUBO({onNext, onMove, isEditing, beneficialOwnerBein
             defaultValue={defaultSsnLast4}
             shouldShowHelpLinks={false}
             maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.SSN}
+            shouldDelayAutoFocus
         />
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/BusinessInfo.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/BusinessInfo.tsx
index be7ff00b0080..60e87e064fcf 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/BusinessInfo.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/BusinessInfo.tsx
@@ -1,11 +1,14 @@
 import {Str} from 'expensify-common';
 import lodashPick from 'lodash/pick';
 import React, {useCallback, useMemo} from 'react';
+import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import useSubStep from '@hooks/useSubStep';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import useReimbursementAccountSubmitCallback from '@hooks/useReimbursementAccountSubmitCallback';
+import useSubPage from '@hooks/useSubPage';
+import type {SubPageProps} from '@hooks/useSubPage/types';
+import Navigation from '@libs/Navigation/Navigation';
 import {parsePhoneNumber} from '@libs/PhoneNumber';
 import {getBankAccountIDAsNumber} from '@libs/ReimbursementAccountUtils';
 import {isValidWebsite} from '@libs/ValidationUtils';
@@ -14,6 +17,7 @@ import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues
 import {updateCompanyInformationForBankAccount} from '@userActions/BankAccounts';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
 import AddressBusiness from './subSteps/AddressBusiness';
 import ConfirmationBusiness from './subSteps/ConfirmationBusiness';
@@ -29,24 +33,32 @@ import WebsiteBusiness from './subSteps/WebsiteBusiness';
 type BusinessInfoProps = {
     /** Goes to the previous step */
     onBackButtonPress: () => void;
+
+    /** Handles submit button press (URL-based navigation) */
+    onSubmit?: () => void;
+
+    /** Back to URL for preserving navigation context */
+    backTo?: string;
 };
 
 const BUSINESS_INFO_STEP_KEYS = INPUT_IDS.BUSINESS_INFO_STEP;
+const PAGE_NAMES = CONST.BANK_ACCOUNT.PAGE_NAMES;
+const SUB_PAGE_NAMES = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.SUB_PAGE_NAMES;
 
-const bodyContent: Array<React.ComponentType<SubStepProps>> = [
-    NameBusiness,
-    TaxIdBusiness,
-    WebsiteBusiness,
-    PhoneNumberBusiness,
-    AddressBusiness,
-    TypeBusiness,
-    IncorporationDateBusiness,
-    IncorporationStateBusiness,
-    IncorporationCode,
-    ConfirmationBusiness,
+const pages = [
+    {pageName: SUB_PAGE_NAMES.NAME, component: NameBusiness},
+    {pageName: SUB_PAGE_NAMES.TAX_ID, component: TaxIdBusiness},
+    {pageName: SUB_PAGE_NAMES.WEBSITE, component: WebsiteBusiness},
+    {pageName: SUB_PAGE_NAMES.PHONE, component: PhoneNumberBusiness},
+    {pageName: SUB_PAGE_NAMES.ADDRESS, component: AddressBusiness},
+    {pageName: SUB_PAGE_NAMES.TYPE, component: TypeBusiness},
+    {pageName: SUB_PAGE_NAMES.INCORPORATION_DATE, component: IncorporationDateBusiness},
+    {pageName: SUB_PAGE_NAMES.INCORPORATION_STATE, component: IncorporationStateBusiness},
+    {pageName: SUB_PAGE_NAMES.INCORPORATION_CODE, component: IncorporationCode},
+    {pageName: SUB_PAGE_NAMES.CONFIRMATION, component: ConfirmationBusiness},
 ];
 
-function BusinessInfo({onBackButtonPress}: BusinessInfoProps) {
+function BusinessInfo({onBackButtonPress, onSubmit, backTo}: BusinessInfoProps) {
     const {translate} = useLocalize();
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
     const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT);
@@ -61,6 +73,7 @@ function BusinessInfo({onBackButtonPress}: BusinessInfoProps) {
 
     const policyID = reimbursementAccount?.achData?.policyID;
     const bankAccountID = getBankAccountIDAsNumber(reimbursementAccount?.achData);
+    const markSubmitting = useReimbursementAccountSubmitCallback(onSubmit);
     const values = useMemo(() => getSubStepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]);
 
     const submit = useCallback(
@@ -85,29 +98,39 @@ function BusinessInfo({onBackButtonPress}: BusinessInfoProps) {
     const isBankAccountVerifying = reimbursementAccount?.achData?.state === CONST.BANK_ACCOUNT.STATE.VERIFYING;
     const startFrom = useMemo(() => (isBankAccountVerifying ? 0 : getInitialSubStepForBusinessInfo(values)), [values, isBankAccountVerifying]);
 
-    const {
-        componentToRender: SubStep,
-        isEditing,
-        screenIndex,
-        nextScreen,
-        prevScreen,
-        moveTo,
-        goToTheLastStep,
-    } = useSubStep({bodyContent, startFrom, onFinished: () => submit(true), onNextSubStep: () => submit(false)});
+    const buildRoute = useCallback(
+        (pageName: string, action?: 'edit') => ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID, page: PAGE_NAMES.COMPANY, subPage: pageName, action, backTo}),
+        [policyID, backTo],
+    );
+
+    const {CurrentPage, isEditing, currentPageName, pageIndex, nextPage, prevPage, moveTo, isRedirecting} = useSubPage<SubPageProps>({
+        pages,
+        startFrom,
+        onFinished: () => {
+            submit(true);
+            markSubmitting();
+        },
+        onPageChange: () => submit(false),
+        buildRoute,
+    });
 
     const handleBackButtonPress = () => {
         if (isEditing) {
-            goToTheLastStep();
+            Navigation.goBack(buildRoute(SUB_PAGE_NAMES.CONFIRMATION));
             return;
         }
 
-        if (screenIndex === 0) {
+        if (pageIndex === 0) {
             onBackButtonPress();
         } else {
-            prevScreen();
+            prevPage();
         }
     };
 
+    if (isRedirecting) {
+        return <FullScreenLoadingIndicator reasonAttributes={{context: 'BusinessInfo', isRedirecting}} />;
+    }
+
     return (
         <InteractiveStepWrapper
             wrapperID="BusinessInfo"
@@ -118,10 +141,11 @@ function BusinessInfo({onBackButtonPress}: BusinessInfoProps) {
             startStepIndex={4}
             stepNames={CONST.BANK_ACCOUNT.STEP_NAMES}
         >
-            <SubStep
+            <CurrentPage
                 isEditing={isEditing}
-                onNext={nextScreen}
+                onNext={nextPage}
                 onMove={moveTo}
+                currentPageName={currentPageName}
             />
         </InteractiveStepWrapper>
     );
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/AddressBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/AddressBusiness.tsx
index 9d68d1da372f..69fc14e84caa 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/AddressBusiness.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/AddressBusiness.tsx
@@ -4,7 +4,7 @@ import AddressStep from '@components/SubStepForms/AddressStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import ONYXKEYS from '@src/ONYXKEYS';
 import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
@@ -21,7 +21,7 @@ const INPUT_KEYS = {
 
 const STEP_FIELDS = [COMPANY_BUSINESS_INFO_KEY.STREET, COMPANY_BUSINESS_INFO_KEY.CITY, COMPANY_BUSINESS_INFO_KEY.STATE, COMPANY_BUSINESS_INFO_KEY.ZIP_CODE];
 
-function AddressBusiness({onNext, onMove, isEditing}: SubStepProps) {
+function AddressBusiness({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount, reimbursementAccountResult] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/ConfirmationBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/ConfirmationBusiness.tsx
index 4bdeebd55e21..2ce528bc2118 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/ConfirmationBusiness.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/ConfirmationBusiness.tsx
@@ -10,7 +10,7 @@ import Text from '@components/Text';
 import TextLink from '@components/TextLink';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getFieldRequiredErrors} from '@libs/ValidationUtils';
 import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues';
@@ -35,7 +35,7 @@ function ConfirmCompanyLabel() {
     );
 }
 
-function ConfirmationBusiness({onNext, onMove}: SubStepProps) {
+function ConfirmationBusiness({onNext, onMove}: SubPageProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
 
@@ -106,7 +106,11 @@ function ConfirmationBusiness({onNext, onMove}: SubStepProps) {
             />
             <MenuItemWithTopDescription
                 description={translate('businessInfoStep.companyType')}
-                title={translate(`businessInfoStep.incorporationType.${values[BUSINESS_INFO_STEP_KEYS.INCORPORATION_TYPE]}` as TranslationPaths)}
+                title={
+                    values[BUSINESS_INFO_STEP_KEYS.INCORPORATION_TYPE]
+                        ? translate(`businessInfoStep.incorporationType.${values[BUSINESS_INFO_STEP_KEYS.INCORPORATION_TYPE]}` as TranslationPaths)
+                        : ''
+                }
                 shouldShowRightIcon
                 onPress={() => {
                     onMove(BUSINESS_INFO_STEP_INDEXES.COMPANY_TYPE);
@@ -122,7 +126,7 @@ function ConfirmationBusiness({onNext, onMove}: SubStepProps) {
             />
             <MenuItemWithTopDescription
                 description={translate('businessInfoStep.incorporationState')}
-                title={translate(`allStates.${values[BUSINESS_INFO_STEP_KEYS.INCORPORATION_STATE] as States}.stateName`)}
+                title={values[BUSINESS_INFO_STEP_KEYS.INCORPORATION_STATE] ? translate(`allStates.${values[BUSINESS_INFO_STEP_KEYS.INCORPORATION_STATE] as States}.stateName`) : ''}
                 shouldShowRightIcon
                 onPress={() => {
                     onMove(BUSINESS_INFO_STEP_INDEXES.INCORPORATION_STATE);
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationCode.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationCode.tsx
index 0fb2c08c063a..272bff25298d 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationCode.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationCode.tsx
@@ -6,7 +6,7 @@ import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {isValidIndustryCode} from '@libs/ValidationUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -16,7 +16,7 @@ import IndustryCodeSelector from './IndustryCode/IndustryCodeSelector';
 const COMPANY_INCORPORATION_CODE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.INCORPORATION_CODE;
 const STEP_FIELDS = [COMPANY_INCORPORATION_CODE_KEY];
 
-function IncorporationCode({onNext, isEditing}: SubStepProps) {
+function IncorporationCode({onNext, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationDateBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationDateBusiness.tsx
index 2febf55e42b5..7674f9b770d6 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationDateBusiness.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationDateBusiness.tsx
@@ -8,7 +8,7 @@ import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {getFieldRequiredErrors, isValidDate, isValidPastDate} from '@libs/ValidationUtils';
@@ -19,7 +19,7 @@ import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 const COMPANY_INCORPORATION_DATE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.INCORPORATION_DATE;
 const STEP_FIELDS = [COMPANY_INCORPORATION_DATE_KEY];
 
-function IncorporationDateBusiness({onNext, isEditing}: SubStepProps) {
+function IncorporationDateBusiness({onNext, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
 
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationStateBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationStateBusiness.tsx
index 5d10d77469b0..24d899552ea9 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationStateBusiness.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationStateBusiness.tsx
@@ -9,7 +9,7 @@ import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {getFieldRequiredErrors} from '@libs/ValidationUtils';
@@ -25,7 +25,7 @@ const validate = (
     translate: LocalizedTranslate,
 ): FormInputErrors<typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM> => getFieldRequiredErrors(values, STEP_FIELDS, translate);
 
-function IncorporationStateBusiness({onNext, isEditing}: SubStepProps) {
+function IncorporationStateBusiness({onNext, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
 
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IndustryCode/IndustryCodeSelector.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IndustryCode/IndustryCodeSelector.tsx
index 1584b9e5b93f..b5ced220b5bd 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IndustryCode/IndustryCodeSelector.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IndustryCode/IndustryCodeSelector.tsx
@@ -1,9 +1,12 @@
-import React, {useEffect, useMemo, useState} from 'react';
+import {useFocusEffect} from '@react-navigation/native';
+import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
 import {View} from 'react-native';
 import SelectionList from '@components/SelectionList';
 import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem';
+import type {ListItem, SelectionListHandle} from '@components/SelectionList/types';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
+import CONST from '@src/CONST';
 import {ALL_NAICS, NAICS, NAICS_MAPPING_WITH_ID} from '@src/NAICS';
 
 type IndustryCodeSelectorProps = {
@@ -14,11 +17,25 @@ type IndustryCodeSelectorProps = {
 
 function IndustryCodeSelector({onInputChange, value, errorText}: IndustryCodeSelectorProps) {
     const styles = useThemeStyles();
+    const selectionListRef = useRef<SelectionListHandle<ListItem>>(null);
     const [searchValue, setSearchValue] = useState<string | undefined>(value);
+    const [isReady, setIsReady] = useState(false);
 
     const [shouldDisplayChildItems, setShouldDisplayChildItems] = useState(false);
     const {translate} = useLocalize();
 
+    // Delay rendering the list and focusing the input until the screen transition animation completes.
+    useFocusEffect(
+        useCallback(() => {
+            const timeout = setTimeout(() => {
+                setIsReady(true);
+                selectionListRef.current?.focusTextInput();
+            }, CONST.ANIMATED_TRANSITION);
+
+            return () => clearTimeout(timeout);
+        }, []),
+    );
+
     const codeOptions = useMemo(() => {
         if (!searchValue) {
             return NAICS.map((item) => {
@@ -65,6 +82,7 @@ function IndustryCodeSelector({onInputChange, value, errorText}: IndustryCodeSel
                 onInputChange?.(val);
             },
             value: searchValue,
+            disableAutoFocus: true,
             errorText,
         }),
         [errorText, onInputChange, searchValue, translate],
@@ -73,7 +91,8 @@ function IndustryCodeSelector({onInputChange, value, errorText}: IndustryCodeSel
     return (
         <View style={styles.flexGrow1}>
             <SelectionList
-                data={codeOptions}
+                ref={selectionListRef}
+                data={isReady ? codeOptions : []}
                 ListItem={SingleSelectListItem}
                 onSelectRow={(item) => {
                     setSearchValue(item.value);
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/NameBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/NameBusiness.tsx
index 6e18b09b2923..fd819f39875d 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/NameBusiness.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/NameBusiness.tsx
@@ -4,7 +4,7 @@ import SingleFieldStep from '@components/SubStepForms/SingleFieldStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import {getFieldRequiredErrors, isValidCompanyName} from '@libs/ValidationUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -13,7 +13,7 @@ import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
 const COMPANY_NAME_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_NAME;
 const STEP_FIELDS = [COMPANY_NAME_KEY];
 
-function NameBusiness({onNext, onMove, isEditing}: SubStepProps) {
+function NameBusiness({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
@@ -63,6 +63,7 @@ function NameBusiness({onNext, onMove, isEditing}: SubStepProps) {
             shouldUseDefaultValue={shouldDisableCompanyName}
             disabled={shouldDisableCompanyName}
             shouldShowHelpLinks={false}
+            shouldDelayAutoFocus
         />
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/PhoneNumberBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/PhoneNumberBusiness.tsx
index 4437c83e6228..85dec7f7c1f0 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/PhoneNumberBusiness.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/PhoneNumberBusiness.tsx
@@ -5,7 +5,7 @@ import SingleFieldStep from '@components/SubStepForms/SingleFieldStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {getFieldRequiredErrors, isValidUSPhone} from '@libs/ValidationUtils';
 import CONST from '@src/CONST';
@@ -16,7 +16,7 @@ import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 const COMPANY_PHONE_NUMBER_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_PHONE;
 const STEP_FIELDS = [COMPANY_PHONE_NUMBER_KEY];
 
-function PhoneNumberBusiness({onNext, onMove, isEditing}: SubStepProps) {
+function PhoneNumberBusiness({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount, reimbursementAccountResult] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
@@ -67,6 +67,7 @@ function PhoneNumberBusiness({onNext, onMove, isEditing}: SubStepProps) {
             defaultValue={defaultCompanyPhoneNumber}
             shouldShowHelpLinks={false}
             placeholder={translate('common.phoneNumberPlaceholder')}
+            shouldDelayAutoFocus
         />
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TaxIdBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TaxIdBusiness.tsx
index 94a85398e8fb..5e3e9b13f73e 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TaxIdBusiness.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TaxIdBusiness.tsx
@@ -5,7 +5,7 @@ import SingleFieldStep from '@components/SubStepForms/SingleFieldStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {getFieldRequiredErrors, isValidTaxID} from '@libs/ValidationUtils';
 import CONST from '@src/CONST';
@@ -15,7 +15,7 @@ import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 
 const COMPANY_TAX_ID_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_TAX_ID;
 const STEP_FIELDS = [COMPANY_TAX_ID_KEY];
-function TaxIdBusiness({onNext, onMove, isEditing}: SubStepProps) {
+function TaxIdBusiness({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount, reimbursementAccountResult] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
@@ -77,6 +77,7 @@ function TaxIdBusiness({onNext, onMove, isEditing}: SubStepProps) {
             shouldShowHelpLinks={false}
             placeholder={translate('businessInfoStep.taxIDNumberPlaceholder')}
             inputMode={CONST.INPUT_MODE.NUMERIC}
+            shouldDelayAutoFocus
         />
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/TypeBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/TypeBusiness.tsx
index f8a296965496..0154ec35c188 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/TypeBusiness.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/TypeBusiness.tsx
@@ -7,7 +7,7 @@ import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {getFieldRequiredErrors} from '@libs/ValidationUtils';
@@ -19,7 +19,7 @@ import BusinessTypePicker from './BusinessTypePicker';
 const COMPANY_INCORPORATION_TYPE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.INCORPORATION_TYPE;
 const STEP_FIELDS = [COMPANY_INCORPORATION_TYPE_KEY];
 
-function TypeBusiness({onNext, isEditing}: SubStepProps) {
+function TypeBusiness({onNext, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
 
diff --git a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/WebsiteBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/WebsiteBusiness.tsx
index 8a15cbcf8908..7214ee4aa687 100644
--- a/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/WebsiteBusiness.tsx
+++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/WebsiteBusiness.tsx
@@ -6,7 +6,7 @@ import SingleFieldStep from '@components/SubStepForms/SingleFieldStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import {getDefaultCompanyWebsite} from '@libs/BankAccountUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {getFieldRequiredErrors, isValidWebsite} from '@libs/ValidationUtils';
@@ -19,7 +19,7 @@ import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 const COMPANY_WEBSITE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_WEBSITE;
 const STEP_FIELDS = [COMPANY_WEBSITE_KEY];
 
-function WebsiteBusiness({onNext, onMove, isEditing}: SubStepProps) {
+function WebsiteBusiness({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
     const [reimbursementAccount, reimbursementAccountResult] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
     const isLoadingReimbursementAccount = isLoadingOnyxValue(reimbursementAccountResult);
@@ -74,6 +74,7 @@ function WebsiteBusiness({onNext, onMove, isEditing}: SubStepProps) {
             defaultValue={defaultCompanyWebsite}
             inputMode={CONST.INPUT_MODE.URL}
             shouldShowHelpLinks={false}
+            shouldDelayAutoFocus
         />
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx b/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx
index 8b99de40b19c..4110007599d6 100644
--- a/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx
+++ b/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx
@@ -1,10 +1,8 @@
 import React, {useCallback, useMemo} from 'react';
-import type {ComponentType} from 'react';
 import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import useSubStep from '@hooks/useSubStep';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import useReimbursementAccountSubmitCallback from '@hooks/useReimbursementAccountSubmitCallback';
 import {getBankAccountIDAsNumber} from '@libs/ReimbursementAccountUtils';
 import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues';
 import {acceptACHContractForBankAccount} from '@userActions/BankAccounts';
@@ -16,12 +14,14 @@ import ConfirmAgreements from './subSteps/ConfirmAgreements';
 type CompleteVerificationProps = {
     /** Handles back button press */
     onBackButtonPress: () => void;
+
+    /** Handles submit button press (URL-based navigation) */
+    onSubmit?: () => void;
 };
 
 const COMPLETE_VERIFICATION_KEYS = INPUT_IDS.COMPLETE_VERIFICATION;
-const bodyContent: Array<ComponentType<SubStepProps>> = [ConfirmAgreements];
 
-function CompleteVerification({onBackButtonPress}: CompleteVerificationProps) {
+function CompleteVerification({onBackButtonPress, onSubmit}: CompleteVerificationProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
@@ -31,6 +31,7 @@ function CompleteVerification({onBackButtonPress}: CompleteVerificationProps) {
     const values = useMemo(() => getSubStepValues(COMPLETE_VERIFICATION_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]);
     const policyID = reimbursementAccount?.achData?.policyID;
     const bankAccountID = getBankAccountIDAsNumber(reimbursementAccount?.achData);
+    const markSubmitting = useReimbursementAccountSubmitCallback(onSubmit);
 
     const submit = useCallback(() => {
         acceptACHContractForBankAccount(
@@ -43,22 +44,8 @@ function CompleteVerification({onBackButtonPress}: CompleteVerificationProps) {
             policyID,
             policyID ? lastPaymentMethod?.[policyID] : undefined,
         );
-    }, [bankAccountID, values.isAuthorizedToUseBankAccount, values.certifyTrueInformation, values.acceptTermsAndConditions, policyID, lastPaymentMethod]);
-
-    const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo, goToTheLastStep} = useSubStep({bodyContent, startFrom: 0, onFinished: submit});
-
-    const handleBackButtonPress = () => {
-        if (isEditing) {
-            goToTheLastStep();
-            return;
-        }
-
-        if (screenIndex === 0) {
-            onBackButtonPress();
-        } else {
-            prevScreen();
-        }
-    };
+        markSubmitting();
+    }, [bankAccountID, values.isAuthorizedToUseBankAccount, values.certifyTrueInformation, values.acceptTermsAndConditions, policyID, lastPaymentMethod, markSubmitting]);
 
     return (
         <InteractiveStepWrapper
@@ -66,15 +53,11 @@ function CompleteVerification({onBackButtonPress}: CompleteVerificationProps) {
             shouldEnablePickerAvoiding={false}
             shouldEnableMaxHeight
             headerTitle={translate('completeVerificationStep.completeVerification')}
-            handleBackButtonPress={handleBackButtonPress}
+            handleBackButtonPress={onBackButtonPress}
             startStepIndex={6}
             stepNames={CONST.BANK_ACCOUNT.STEP_NAMES}
         >
-            <SubStep
-                isEditing={isEditing}
-                onNext={nextScreen}
-                onMove={moveTo}
-            />
+            <ConfirmAgreements onNext={submit} />
         </InteractiveStepWrapper>
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx b/src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx
index 0799cece1418..ad825930e2f1 100644
--- a/src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx
+++ b/src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx
@@ -7,15 +7,12 @@ import RenderHTML from '@components/RenderHTML';
 import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import type {SubStepProps} from '@hooks/useSubStep/types';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getFieldRequiredErrors, isRequiredFulfilled} from '@libs/ValidationUtils';
 import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues';
 import ONYXKEYS from '@src/ONYXKEYS';
 import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
 
-type ConfirmAgreementsProps = SubStepProps;
-
 const COMPLETE_VERIFICATION_KEYS = INPUT_IDS.COMPLETE_VERIFICATION;
 const STEP_FIELDS = [
     INPUT_IDS.COMPLETE_VERIFICATION.IS_AUTHORIZED_TO_USE_BANK_ACCOUNT,
@@ -38,6 +35,11 @@ function TermsAndConditionsLabel() {
     return <RenderHTML html={translate('common.acceptTermsAndConditions')} />;
 }
 
+type ConfirmAgreementsProps = {
+    /** Continues to the next step */
+    onNext: () => void;
+};
+
 function ConfirmAgreements({onNext}: ConfirmAgreementsProps) {
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
     const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT);
diff --git a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
index 5d44b1b79949..640215e572f3 100644
--- a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
+++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
@@ -1,6 +1,7 @@
 import {hasSeenTourSelector} from '@selectors/Onboarding';
 import React from 'react';
 import {View} from 'react-native';
+import ConfirmationPage from '@components/ConfirmationPage';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
 import Text from '@components/Text';
@@ -8,10 +9,14 @@ import TextLink from '@components/TextLink';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
+import useRootNavigationState from '@hooks/useRootNavigationState';
 import useThemeStyles from '@hooks/useThemeStyles';
+import {isFullScreenName} from '@navigation/helpers/isNavigatorName';
+import Navigation from '@navigation/Navigation';
 import ConnectedVerifiedBankAccount from '@pages/ReimbursementAccount/ConnectedVerifiedBankAccount';
 import {navigateToConciergeChat} from '@userActions/Report';
 import CONST from '@src/CONST';
+import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
 import BankAccountValidationForm from './components/BankAccountValidationForm';
 import FinishChatCard from './components/FinishChatCard';
@@ -21,15 +26,16 @@ type ConnectBankAccountProps = {
     onBackButtonPress: () => void;
 
     /** Method to set the state of shouldShowConnectedVerifiedBankAccount */
-    setShouldShowConnectedVerifiedBankAccount: (shouldShowConnectedVerifiedBankAccount: boolean) => void;
+    setShouldShowConnectedVerifiedBankAccount?: (shouldShowConnectedVerifiedBankAccount: boolean) => void;
 
     /** Method to set the state of shouldShowConnectedVerifiedBankAccount */
-    setUSDBankAccountStep: (step: string | null) => void;
+    setUSDBankAccountStep?: (step: string | null) => void;
 };
 
 function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBankAccount, setUSDBankAccountStep}: ConnectBankAccountProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
+    const topmostFullScreenRoute = useRootNavigationState((state) => state?.routes.findLast((lastRoute) => isFullScreenName(lastRoute.name)));
 
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${reimbursementAccount?.achData?.policyID}`);
@@ -45,10 +51,28 @@ function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBa
 
     // If a user tries to navigate directly to the validate page we'll show them the EnableStep
     if (bankAccountState === CONST.BANK_ACCOUNT.STATE.OPEN) {
+        if (topmostFullScreenRoute?.name === NAVIGATORS.SETTINGS_SPLIT_NAVIGATOR) {
+            return (
+                <ScreenWrapper testID="ReimbursementAccountPage">
+                    <HeaderWithBackButton
+                        title={translate('bankAccount.addBankAccount')}
+                        onBackButtonPress={() => Navigation.dismissModal()}
+                    />
+                    <ConfirmationPage
+                        heading={translate('bankAccount.bbaAdded')}
+                        description={translate('bankAccount.bbaAddedDescription')}
+                        shouldShowButton
+                        headingStyle={styles.mh5}
+                        buttonText={translate('common.confirm')}
+                        onButtonPress={() => Navigation.dismissModal()}
+                    />
+                </ScreenWrapper>
+            );
+        }
         return (
             <ConnectedVerifiedBankAccount
                 reimbursementAccount={reimbursementAccount}
-                onBackButtonPress={onBackButtonPress}
+                onBackButtonPress={() => Navigation.dismissModal()}
                 setShouldShowConnectedVerifiedBankAccount={setShouldShowConnectedVerifiedBankAccount}
                 setUSDBankAccountStep={setUSDBankAccountStep}
                 isNonUSDWorkspace={false}
diff --git a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx
index 62ae351d5384..b7e469bbe45e 100644
--- a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx
+++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx
@@ -26,7 +26,7 @@ type FinishChatCardProps = {
     requiresTwoFactorAuth: boolean;
 
     /** Method to set the state of USD bank account step */
-    setUSDBankAccountStep: (step: string | null) => void;
+    setUSDBankAccountStep?: (step: string | null) => void;
 };
 
 function FinishChatCard({requiresTwoFactorAuth, reimbursementAccount, setUSDBankAccountStep}: FinishChatCardProps) {
@@ -77,7 +77,7 @@ function FinishChatCard({requiresTwoFactorAuth, reimbursementAccount, setUSDBank
                     title={translate('workspace.bankAccount.updateDetails')}
                     onPress={() => {
                         setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL).then(() => {
-                            setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.REQUESTOR);
+                            setUSDBankAccountStep?.(CONST.BANK_ACCOUNT.STEP.REQUESTOR);
                             goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.REQUESTOR);
                         });
                     }}
diff --git a/src/pages/ReimbursementAccount/USD/Country/index.tsx b/src/pages/ReimbursementAccount/USD/Country/index.tsx
index b4a28c913745..ded09899c388 100644
--- a/src/pages/ReimbursementAccount/USD/Country/index.tsx
+++ b/src/pages/ReimbursementAccount/USD/Country/index.tsx
@@ -7,24 +7,20 @@ type CountryProps = {
     /** Handles back button press */
     onBackButtonPress: () => void;
 
+    /** Handles submit button press (URL-based navigation) */
+    onSubmit?: () => void;
+
     /** Array of step names */
     stepNames: readonly string[];
 
-    /** Method to set the state of setUSDBankAccountStep */
-    setUSDBankAccountStep?: (step: string | null) => void;
-
     /** ID of current policy */
     policyID: string | undefined;
 };
 
-function Country({onBackButtonPress, stepNames, setUSDBankAccountStep, policyID}: CountryProps) {
+function Country({onBackButtonPress, onSubmit, stepNames, policyID}: CountryProps) {
     const submit = () => {
-        if (!setUSDBankAccountStep) {
-            return;
-        }
-
-        setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT);
         goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT);
+        onSubmit?.();
     };
 
     return (
diff --git a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/PersonalInfo.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/PersonalInfo.tsx
index bd548f912ff0..a0c39597cf35 100644
--- a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/PersonalInfo.tsx
+++ b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/PersonalInfo.tsx
@@ -1,17 +1,21 @@
 import type {ForwardedRef} from 'react';
 import React, {useCallback, useMemo} from 'react';
 import type {View} from 'react-native';
+import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import useSubStep from '@hooks/useSubStep';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import useReimbursementAccountSubmitCallback from '@hooks/useReimbursementAccountSubmitCallback';
+import useSubPage from '@hooks/useSubPage';
+import type {SubPageProps} from '@hooks/useSubPage/types';
+import Navigation from '@libs/Navigation/Navigation';
 import {getBankAccountIDAsNumber} from '@libs/ReimbursementAccountUtils';
 import getInitialSubStepForPersonalInfo from '@pages/ReimbursementAccount/USD/utils/getInitialSubStepForPersonalInfo';
 import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues';
 import {updatePersonalInformationForBankAccount} from '@userActions/BankAccounts';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
 import Address from './subSteps/Address';
 import Confirmation from './subSteps/Confirmation';
@@ -23,14 +27,29 @@ type PersonalInfoProps = {
     /** Goes to the previous step */
     onBackButtonPress: () => void;
 
+    /** Handles submit button press (URL-based navigation) */
+    onSubmit?: () => void;
+
     /** Reference to the outer element */
     ref?: ForwardedRef<View>;
+
+    /** Back to URL for preserving navigation context */
+    backTo?: string;
 };
 
 const PERSONAL_INFO_STEP_KEYS = INPUT_IDS.PERSONAL_INFO_STEP;
-const bodyContent: Array<React.ComponentType<SubStepProps>> = [FullName, DateOfBirth, SocialSecurityNumber, Address, Confirmation];
+const PAGE_NAMES = CONST.BANK_ACCOUNT.PAGE_NAMES;
+const SUB_PAGE_NAMES = CONST.BANK_ACCOUNT.PERSONAL_INFO_STEP.SUB_PAGE_NAMES;
+
+const pages = [
+    {pageName: SUB_PAGE_NAMES.FULL_NAME, component: FullName},
+    {pageName: SUB_PAGE_NAMES.DATE_OF_BIRTH, component: DateOfBirth},
+    {pageName: SUB_PAGE_NAMES.SSN, component: SocialSecurityNumber},
+    {pageName: SUB_PAGE_NAMES.ADDRESS, component: Address},
+    {pageName: SUB_PAGE_NAMES.CONFIRMATION, component: Confirmation},
+];
 
-function PersonalInfo({onBackButtonPress, ref}: PersonalInfoProps) {
+function PersonalInfo({onBackButtonPress, onSubmit, ref, backTo}: PersonalInfoProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
@@ -39,6 +58,7 @@ function PersonalInfo({onBackButtonPress, ref}: PersonalInfoProps) {
     const policyID = reimbursementAccount?.achData?.policyID;
     const values = useMemo(() => getSubStepValues(PERSONAL_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]);
     const bankAccountID = getBankAccountIDAsNumber(reimbursementAccount?.achData);
+    const markSubmitting = useReimbursementAccountSubmitCallback(onSubmit);
     const submit = useCallback(
         (isConfirmPage: boolean) => {
             updatePersonalInformationForBankAccount(bankAccountID, {...values}, policyID, isConfirmPage);
@@ -48,26 +68,32 @@ function PersonalInfo({onBackButtonPress, ref}: PersonalInfoProps) {
     const isBankAccountVerifying = reimbursementAccount?.achData?.state === CONST.BANK_ACCOUNT.STATE.VERIFYING;
     const startFrom = useMemo(() => (isBankAccountVerifying ? 0 : getInitialSubStepForPersonalInfo(values)), [values, isBankAccountVerifying]);
 
-    const {
-        componentToRender: SubStep,
-        isEditing,
-        screenIndex,
-        nextScreen,
-        prevScreen,
-        moveTo,
-        goToTheLastStep,
-    } = useSubStep({bodyContent, startFrom, onFinished: () => submit(true), onNextSubStep: () => submit(false)});
+    const buildRoute = useCallback(
+        (pageName: string, action?: 'edit') => ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID, page: PAGE_NAMES.REQUESTOR, subPage: pageName, action, backTo}),
+        [policyID, backTo],
+    );
+
+    const {CurrentPage, isEditing, currentPageName, pageIndex, nextPage, prevPage, moveTo, isRedirecting} = useSubPage<SubPageProps>({
+        pages,
+        startFrom,
+        onFinished: () => {
+            submit(true);
+            markSubmitting();
+        },
+        onPageChange: () => submit(false),
+        buildRoute,
+    });
 
     const handleBackButtonPress = () => {
         if (isEditing) {
-            goToTheLastStep();
+            Navigation.goBack(buildRoute(SUB_PAGE_NAMES.CONFIRMATION));
             return;
         }
 
-        if (screenIndex === 0) {
+        if (pageIndex === 0) {
             onBackButtonPress();
         } else {
-            prevScreen();
+            prevPage();
         }
     };
 
@@ -82,11 +108,16 @@ function PersonalInfo({onBackButtonPress, ref}: PersonalInfoProps) {
             startStepIndex={2}
             stepNames={CONST.BANK_ACCOUNT.STEP_NAMES}
         >
-            <SubStep
-                isEditing={isEditing}
-                onNext={nextScreen}
-                onMove={moveTo}
-            />
+            {isRedirecting ? (
+                <FullScreenLoadingIndicator reasonAttributes={{context: 'PersonalInfo', isRedirecting}} />
+            ) : (
+                <CurrentPage
+                    isEditing={isEditing}
+                    onNext={nextPage}
+                    onMove={moveTo}
+                    currentPageName={currentPageName}
+                />
+            )}
         </InteractiveStepWrapper>
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Address.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Address.tsx
index cc63886621ce..39c912e0ce38 100644
--- a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Address.tsx
+++ b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Address.tsx
@@ -4,7 +4,7 @@ import AddressStep from '@components/SubStepForms/AddressStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -22,7 +22,7 @@ const INPUT_KEYS = {
 
 const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.STREET, PERSONAL_INFO_STEP_KEY.CITY, PERSONAL_INFO_STEP_KEY.STATE, PERSONAL_INFO_STEP_KEY.ZIP_CODE];
 
-function Address({onNext, onMove, isEditing}: SubStepProps) {
+function Address({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount, reimbursementAccountResult] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
diff --git a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Confirmation.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Confirmation.tsx
index 17c29db3ce12..e9c1a8749b9c 100644
--- a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Confirmation.tsx
+++ b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Confirmation.tsx
@@ -2,7 +2,7 @@ import React, {useMemo} from 'react';
 import ConfirmationStep from '@components/SubStepForms/ConfirmationStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import {getLatestErrorMessage} from '@libs/ErrorUtils';
 import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues';
 import CONST from '@src/CONST';
@@ -12,7 +12,7 @@ import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
 const PERSONAL_INFO_STEP_KEYS = INPUT_IDS.PERSONAL_INFO_STEP;
 const PERSONAL_INFO_STEP_INDEXES = CONST.REIMBURSEMENT_ACCOUNT.SUBSTEP_INDEX.PERSONAL_INFO;
 
-function Confirmation({onNext, onMove, isEditing}: SubStepProps) {
+function Confirmation({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
diff --git a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/DateOfBirth.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/DateOfBirth.tsx
index cde22e01ed97..54adf2a4be87 100644
--- a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/DateOfBirth.tsx
+++ b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/DateOfBirth.tsx
@@ -4,7 +4,7 @@ import DateOfBirthStep from '@components/SubStepForms/DateOfBirthStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import HelpLinks from '@pages/ReimbursementAccount/USD/Requestor/PersonalInfo/HelpLinks';
@@ -16,7 +16,7 @@ import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 const PERSONAL_INFO_DOB_KEY = INPUT_IDS.PERSONAL_INFO_STEP.DOB;
 const STEP_FIELDS = [PERSONAL_INFO_DOB_KEY];
 
-function DateOfBirth({onNext, onMove, isEditing}: SubStepProps) {
+function DateOfBirth({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
 
diff --git a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/FullName.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/FullName.tsx
index a1f841963792..6093b3c2a77a 100644
--- a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/FullName.tsx
+++ b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/FullName.tsx
@@ -3,7 +3,7 @@ import FullNameStep from '@components/SubStepForms/FullNameStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
@@ -11,7 +11,7 @@ import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
 const PERSONAL_INFO_STEP_KEY = INPUT_IDS.PERSONAL_INFO_STEP;
 const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.FIRST_NAME, PERSONAL_INFO_STEP_KEY.LAST_NAME];
 
-function FullName({onNext, onMove, isEditing}: SubStepProps) {
+function FullName({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
diff --git a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/SocialSecurityNumber.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/SocialSecurityNumber.tsx
index ff9d07476a6a..6e7384be05ab 100644
--- a/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/SocialSecurityNumber.tsx
+++ b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/SocialSecurityNumber.tsx
@@ -5,7 +5,7 @@ import SingleFieldStep from '@components/SubStepForms/SingleFieldStep';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
-import type {SubStepProps} from '@hooks/useSubStep/types';
+import type {SubPageProps} from '@hooks/useSubPage/types';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {getFieldRequiredErrors, isValidSSNLastFour} from '@libs/ValidationUtils';
 import CONST from '@src/CONST';
@@ -16,7 +16,7 @@ import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 const PERSONAL_INFO_STEP_KEY = INPUT_IDS.PERSONAL_INFO_STEP;
 const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.SSN_LAST_4];
 
-function SocialSecurityNumber({onNext, onMove, isEditing}: SubStepProps) {
+function SocialSecurityNumber({onNext, onMove, isEditing}: SubPageProps) {
     const {translate} = useLocalize();
 
     const [reimbursementAccount, reimbursementAccountResult] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
@@ -68,6 +68,7 @@ function SocialSecurityNumber({onNext, onMove, isEditing}: SubStepProps) {
             maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.SSN}
             enabledWhenOffline
             forwardedFSClass={CONST.FULLSTORY.CLASS.MASK}
+            shouldDelayAutoFocus
         />
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/Requestor/RequestorStep.tsx b/src/pages/ReimbursementAccount/USD/Requestor/RequestorStep.tsx
index 4a9de8d65704..f02b5186081d 100644
--- a/src/pages/ReimbursementAccount/USD/Requestor/RequestorStep.tsx
+++ b/src/pages/ReimbursementAccount/USD/Requestor/RequestorStep.tsx
@@ -2,28 +2,28 @@ import React from 'react';
 import type {ForwardedRef} from 'react';
 import type {View} from 'react-native';
 import PersonalInfo from './PersonalInfo/PersonalInfo';
-import VerifyIdentity from './VerifyIdentity/VerifyIdentity';
 
 type RequestorStepProps = {
     /** Goes to the previous step */
     onBackButtonPress: () => void;
 
-    /** If we should show Onfido flow */
-    shouldShowOnfido: boolean;
+    /** Handles submit button press (URL-based navigation) */
+    onSubmit?: () => void;
 
     /** Reference to the outer element */
     ref?: ForwardedRef<View>;
-};
 
-function RequestorStep({shouldShowOnfido, onBackButtonPress, ref}: RequestorStepProps) {
-    if (shouldShowOnfido) {
-        return <VerifyIdentity onBackButtonPress={onBackButtonPress} />;
-    }
+    /** Back to URL for preserving navigation context */
+    backTo?: string;
+};
 
+function RequestorStep({onBackButtonPress, onSubmit, ref, backTo}: RequestorStepProps) {
     return (
         <PersonalInfo
             ref={ref}
             onBackButtonPress={onBackButtonPress}
+            onSubmit={onSubmit}
+            backTo={backTo}
         />
     );
 }
diff --git a/src/pages/ReimbursementAccount/USD/Requestor/VerifyIdentity/VerifyIdentity.tsx b/src/pages/ReimbursementAccount/USD/Requestor/VerifyIdentity/VerifyIdentity.tsx
index 5947ef3f01f8..c739dd63a433 100644
--- a/src/pages/ReimbursementAccount/USD/Requestor/VerifyIdentity/VerifyIdentity.tsx
+++ b/src/pages/ReimbursementAccount/USD/Requestor/VerifyIdentity/VerifyIdentity.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useState} from 'react';
+import React, {useCallback, useEffect, useRef, useState} from 'react';
 import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
 import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import Onfido from '@components/Onfido';
@@ -8,18 +8,21 @@ import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Growl from '@libs/Growl';
-import {clearOnfidoToken, goToWithdrawalAccountSetupStep, updateReimbursementAccountDraft, verifyIdentityForBankAccount} from '@userActions/BankAccounts';
+import {clearOnfidoToken, updateReimbursementAccountDraft, verifyIdentityForBankAccount} from '@userActions/BankAccounts';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 
 type VerifyIdentityProps = {
     /** Goes to the previous step */
     onBackButtonPress: () => void;
+
+    /** Navigates to the next step */
+    onSubmit?: () => void;
 };
 
 const ONFIDO_ERROR_DISPLAY_DURATION = 10000;
 
-function VerifyIdentity({onBackButtonPress}: VerifyIdentityProps) {
+function VerifyIdentity({onBackButtonPress, onSubmit}: VerifyIdentityProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
 
@@ -31,25 +34,37 @@ function VerifyIdentity({onBackButtonPress}: VerifyIdentityProps) {
     const policyID = reimbursementAccount?.achData?.policyID;
     const bankAccountID = reimbursementAccount?.achData?.bankAccountID;
 
+    const isOnfidoAlreadyComplete = useRef(reimbursementAccount?.achData?.isOnfidoSetupComplete);
+    const onSubmitRef = useRef(onSubmit);
+
+    // If Onfido is already complete (e.g. direct URL navigation), skip to next step
+    useEffect(() => {
+        if (!isOnfidoAlreadyComplete.current) {
+            return;
+        }
+        onSubmitRef.current?.();
+    }, []);
+
     const handleOnfidoSuccess = useCallback(
         (onfidoData: OnfidoData) => {
             verifyIdentityForBankAccount(Number(bankAccountID), {...onfidoData, applicantID: onfidoApplicantID}, policyID);
             updateReimbursementAccountDraft({isOnfidoSetupComplete: true});
+            onSubmit?.();
         },
-        [bankAccountID, onfidoApplicantID, policyID],
+        [bankAccountID, onfidoApplicantID, policyID, onSubmit],
     );
 
     const handleOnfidoError = () => {
         // In case of any unexpected error we log it to the server, show a growl, and return the user back to the requestor step so they can try again.
         Growl.error(translate('onfidoStep.genericError'), ONFIDO_ERROR_DISPLAY_DURATION);
         clearOnfidoToken();
-        goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.REQUESTOR);
+        onBackButtonPress();
     };
 
     const handleOnfidoUserExit = (isUserInitiated?: boolean) => {
         if (isUserInitiated) {
             clearOnfidoToken();
-            goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.REQUESTOR);
+            onBackButtonPress();
         } else {
             setOnfidoKey(Math.floor(Math.random() * 1000000));
         }
diff --git a/src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlow.tsx b/src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlow.tsx
deleted file mode 100644
index c13784998b2a..000000000000
--- a/src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlow.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-import React from 'react';
-import {View} from 'react-native';
-import useOnyx from '@hooks/useOnyx';
-import useThemeStyles from '@hooks/useThemeStyles';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import BankInfo from './BankInfo/BankInfo';
-import BeneficialOwnersStep from './BeneficialOwnerInfo/BeneficialOwnersStep';
-import BusinessInfo from './BusinessInfo/BusinessInfo';
-import CompleteVerification from './CompleteVerification/CompleteVerification';
-import ConnectBankAccount from './ConnectBankAccount/ConnectBankAccount';
-import Country from './Country';
-import RequestorStep from './Requestor/RequestorStep';
-
-type USDVerifiedBankAccountFlowProps = {
-    USDBankAccountStep: string;
-    policyID: string | undefined;
-    onBackButtonPress: () => void;
-    requestorStepRef: React.RefObject<View | null>;
-    onfidoToken: string;
-    setUSDBankAccountStep: (step: string | null) => void;
-    setShouldShowConnectedVerifiedBankAccount: (shouldShowConnectedVerifiedBankAccount: boolean) => void;
-};
-
-function USDVerifiedBankAccountFlow({
-    USDBankAccountStep,
-    policyID = '',
-    onBackButtonPress,
-    requestorStepRef,
-    onfidoToken,
-    setUSDBankAccountStep,
-    setShouldShowConnectedVerifiedBankAccount,
-}: USDVerifiedBankAccountFlowProps) {
-    const styles = useThemeStyles();
-    const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
-
-    let CurrentStep: React.JSX.Element | null;
-    switch (USDBankAccountStep) {
-        case CONST.BANK_ACCOUNT.STEP.COUNTRY:
-            CurrentStep = (
-                <Country
-                    onBackButtonPress={onBackButtonPress}
-                    policyID={policyID}
-                    setUSDBankAccountStep={setUSDBankAccountStep}
-                    stepNames={CONST.BANK_ACCOUNT.STEP_NAMES}
-                />
-            );
-            break;
-        case CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT:
-            CurrentStep = (
-                <BankInfo
-                    onBackButtonPress={onBackButtonPress}
-                    policyID={policyID}
-                    setUSDBankAccountStep={setUSDBankAccountStep}
-                />
-            );
-            break;
-        case CONST.BANK_ACCOUNT.STEP.REQUESTOR:
-            CurrentStep = (
-                <RequestorStep
-                    ref={requestorStepRef}
-                    shouldShowOnfido={!!(onfidoToken && !reimbursementAccount?.achData?.isOnfidoSetupComplete)}
-                    onBackButtonPress={onBackButtonPress}
-                />
-            );
-            break;
-        case CONST.BANK_ACCOUNT.STEP.COMPANY:
-            CurrentStep = <BusinessInfo onBackButtonPress={onBackButtonPress} />;
-            break;
-        case CONST.BANK_ACCOUNT.STEP.BENEFICIAL_OWNERS:
-            CurrentStep = <BeneficialOwnersStep onBackButtonPress={onBackButtonPress} />;
-            break;
-        case CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT:
-            CurrentStep = <CompleteVerification onBackButtonPress={onBackButtonPress} />;
-            break;
-        case CONST.BANK_ACCOUNT.STEP.VALIDATION:
-            CurrentStep = (
-                <ConnectBankAccount
-                    onBackButtonPress={onBackButtonPress}
-                    setUSDBankAccountStep={setUSDBankAccountStep}
-                    setShouldShowConnectedVerifiedBankAccount={setShouldShowConnectedVerifiedBankAccount}
-                />
-            );
-            break;
-        default:
-            CurrentStep = null;
-            break;
-    }
-
-    if (CurrentStep) {
-        return <View style={styles.flex1}>{CurrentStep}</View>;
-    }
-
-    return null;
-}
-
-export default USDVerifiedBankAccountFlow;
diff --git a/src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlowPage.tsx b/src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlowPage.tsx
new file mode 100644
index 000000000000..d721d8155e1c
--- /dev/null
+++ b/src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlowPage.tsx
@@ -0,0 +1,135 @@
+import React, {useCallback, useMemo, useRef} from 'react';
+import {View} from 'react-native';
+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 type {ReimbursementAccountNavigatorParamList} from '@libs/Navigation/types';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import type SCREENS from '@src/SCREENS';
+import BankInfo from './BankInfo/BankInfo';
+import BeneficialOwnersStep from './BeneficialOwnerInfo/BeneficialOwnersStep';
+import BusinessInfo from './BusinessInfo/BusinessInfo';
+import CompleteVerification from './CompleteVerification/CompleteVerification';
+import ConnectBankAccount from './ConnectBankAccount/ConnectBankAccount';
+import Country from './Country';
+import RequestorStep from './Requestor/RequestorStep';
+import VerifyIdentity from './Requestor/VerifyIdentity/VerifyIdentity';
+import type USDPageProps from './types';
+
+const PAGE_NAMES = CONST.BANK_ACCOUNT.PAGE_NAMES;
+const BANK_INFO_SUB_PAGES = CONST.BANK_ACCOUNT.BANK_INFO_STEP.SUB_PAGE_NAMES;
+const PERSONAL_INFO_SUB_PAGES = CONST.BANK_ACCOUNT.PERSONAL_INFO_STEP.SUB_PAGE_NAMES;
+const BUSINESS_INFO_SUB_PAGES = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.SUB_PAGE_NAMES;
+const BENEFICIAL_OWNERS_SUB_PAGES = CONST.BANK_ACCOUNT.BENEFICIAL_OWNERS_STEP.SUB_PAGE_NAMES;
+const COMPLETE_VERIFICATION_SUB_PAGES = CONST.BANK_ACCOUNT.COMPLETE_VERIFICATION_STEP.SUB_PAGE_NAMES;
+
+type PageEntry = {
+    pageName: string;
+    component: React.ComponentType<USDPageProps>;
+    firstSubPage?: string;
+    lastSubPage?: string;
+};
+
+const pages: PageEntry[] = [
+    {pageName: PAGE_NAMES.COUNTRY, component: Country as React.ComponentType<USDPageProps>},
+    {pageName: PAGE_NAMES.BANK_ACCOUNT, component: BankInfo as React.ComponentType<USDPageProps>, firstSubPage: BANK_INFO_SUB_PAGES.PLAID, lastSubPage: BANK_INFO_SUB_PAGES.PLAID},
+    {
+        pageName: PAGE_NAMES.REQUESTOR,
+        component: RequestorStep as React.ComponentType<USDPageProps>,
+        firstSubPage: PERSONAL_INFO_SUB_PAGES.FULL_NAME,
+        lastSubPage: PERSONAL_INFO_SUB_PAGES.CONFIRMATION,
+    },
+    {pageName: PAGE_NAMES.VERIFY_IDENTITY, component: VerifyIdentity as React.ComponentType<USDPageProps>},
+    {
+        pageName: PAGE_NAMES.COMPANY,
+        component: BusinessInfo as React.ComponentType<USDPageProps>,
+        firstSubPage: BUSINESS_INFO_SUB_PAGES.NAME,
+        lastSubPage: BUSINESS_INFO_SUB_PAGES.CONFIRMATION,
+    },
+    {
+        pageName: PAGE_NAMES.BENEFICIAL_OWNERS,
+        component: BeneficialOwnersStep as React.ComponentType<USDPageProps>,
+        firstSubPage: BENEFICIAL_OWNERS_SUB_PAGES.IS_USER_UBO,
+        lastSubPage: undefined,
+    },
+    {
+        pageName: PAGE_NAMES.ACH_CONTRACT,
+        component: CompleteVerification as React.ComponentType<USDPageProps>,
+        firstSubPage: COMPLETE_VERIFICATION_SUB_PAGES.CONFIRM_AGREEMENTS,
+        lastSubPage: COMPLETE_VERIFICATION_SUB_PAGES.CONFIRM_AGREEMENTS,
+    },
+    {pageName: PAGE_NAMES.VALIDATION, component: ConnectBankAccount as React.ComponentType<USDPageProps>},
+];
+
+type USDVerifiedBankAccountFlowPageProps = PlatformStackScreenProps<ReimbursementAccountNavigatorParamList, typeof SCREENS.REIMBURSEMENT_ACCOUNT_USD>;
+
+function USDVerifiedBankAccountFlowPage({route}: USDVerifiedBankAccountFlowPageProps) {
+    const styles = useThemeStyles();
+    const policyID = route.params?.policyID;
+    const currentPage = route.params?.page;
+    const currentSubPage = route.params?.subPage;
+    const backTo = route.params?.backTo;
+
+    const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
+
+    const requestorStepRef = useRef<View>(null);
+    const isOnfidoSetupComplete = reimbursementAccount?.achData?.isOnfidoSetupComplete;
+
+    const currentPageIndex = useMemo(() => {
+        const index = pages.findIndex((p) => p.pageName === currentPage);
+        return index >= 0 ? index : 0;
+    }, [currentPage]);
+
+    const currentEntry = pages.at(currentPageIndex);
+    const CurrentPage = currentEntry?.component ?? (Country as React.ComponentType<USDPageProps>);
+    const isRequestorStep = currentEntry?.pageName === PAGE_NAMES.REQUESTOR;
+
+    const shouldSkipVerifyIdentity = useCallback((pageName?: string) => pageName === PAGE_NAMES.VERIFY_IDENTITY && isOnfidoSetupComplete, [isOnfidoSetupComplete]);
+
+    const onSubmit = useCallback(() => {
+        let nextIndex = currentPageIndex + 1;
+        if (shouldSkipVerifyIdentity(pages.at(nextIndex)?.pageName)) {
+            nextIndex += 1;
+        }
+        if (nextIndex >= pages.length) {
+            Navigation.goBack();
+            return;
+        }
+        const nextPage = pages.at(nextIndex);
+        Navigation.navigate(ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID, page: nextPage?.pageName, subPage: nextPage?.firstSubPage, backTo}));
+    }, [backTo, currentPageIndex, policyID, shouldSkipVerifyIdentity]);
+
+    const onBackButtonPress = useCallback(() => {
+        let prevIndex = currentPageIndex - 1;
+        if (shouldSkipVerifyIdentity(pages.at(prevIndex)?.pageName)) {
+            prevIndex -= 1;
+        }
+        if (prevIndex < 0) {
+            Navigation.goBack();
+            return;
+        }
+        const prevPage = pages.at(prevIndex);
+        Navigation.goBack(ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID, page: prevPage?.pageName, subPage: prevPage?.lastSubPage, backTo}));
+    }, [backTo, currentPageIndex, policyID, shouldSkipVerifyIdentity]);
+
+    return (
+        <View style={[styles.flex1, styles.appBG]}>
+            <CurrentPage
+                onSubmit={onSubmit}
+                onBackButtonPress={onBackButtonPress}
+                policyID={policyID}
+                currentSubPage={currentSubPage}
+                stepNames={CONST.BANK_ACCOUNT.STEP_NAMES}
+                ref={isRequestorStep ? requestorStepRef : undefined}
+                backTo={backTo}
+            />
+        </View>
+    );
+}
+
+USDVerifiedBankAccountFlowPage.displayName = 'USDVerifiedBankAccountFlowPage';
+
+export default USDVerifiedBankAccountFlowPage;
diff --git a/src/pages/ReimbursementAccount/USD/types.ts b/src/pages/ReimbursementAccount/USD/types.ts
new file mode 100644
index 000000000000..c808a68bff8f
--- /dev/null
+++ b/src/pages/ReimbursementAccount/USD/types.ts
@@ -0,0 +1,28 @@
+import type {ForwardedRef} from 'react';
+import type {View} from 'react-native';
+import type {Route} from '@src/ROUTES';
+
+type USDPageProps = {
+    /** Handles submit button press */
+    onSubmit: () => void;
+
+    /** Handles back button press */
+    onBackButtonPress: () => void;
+
+    /** ID of current policy */
+    policyID?: string;
+
+    /** Name of the current sub page */
+    currentSubPage?: string;
+
+    /** Array of step names for the progress indicator */
+    stepNames?: readonly string[];
+
+    /** Reference to the outer element (used by RequestorStep) */
+    ref?: ForwardedRef<View>;
+
+    /** Back to URL for preserving navigation context */
+    backTo?: Route;
+};
+
+export default USDPageProps;
diff --git a/src/pages/ReimbursementAccount/VerifiedBankAccountFlowEntryPoint.tsx b/src/pages/ReimbursementAccount/VerifiedBankAccountFlowEntryPoint.tsx
index 4da763c2981f..8e6a747efcc5 100644
--- a/src/pages/ReimbursementAccount/VerifiedBankAccountFlowEntryPoint.tsx
+++ b/src/pages/ReimbursementAccount/VerifiedBankAccountFlowEntryPoint.tsx
@@ -123,10 +123,10 @@ function VerifiedBankAccountFlowEntryPoint({
     const prepareNextStep = useCallback(
         (setupType: ValueOf<typeof CONST.BANK_ACCOUNT.SETUP_TYPE>) => {
             setBankAccountSubStep(setupType);
-            setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
             goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
+            Navigation.navigate(ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID, page: CONST.BANK_ACCOUNT.PAGE_NAMES.COUNTRY, backTo}));
         },
-        [setUSDBankAccountStep],
+        [policyID, backTo],
     );
 
     /**
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
index dc08a6534505..24dd5d84896f 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
@@ -19,7 +19,6 @@ 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 {REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
 import Navigation from '@navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
@@ -67,7 +66,6 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
         Navigation.navigate(
             ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
                 policyID,
-                stepToOpen: REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW,
                 backTo: ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID),
             }),
         );
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
index 2c694a0253c8..063813a70834 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
@@ -20,7 +20,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 {hasInProgressUSDVBBA, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
+import {hasInProgressUSDVBBA} from '@libs/ReimbursementAccountUtils';
 import Navigation from '@navigation/Navigation';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
@@ -71,7 +71,6 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
             Navigation.navigate(
                 ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
                     policyID: policy?.id,
-                    stepToOpen: REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW,
                     backTo: ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policy?.id),
                 }),
             );
diff --git a/src/pages/workspace/travel/WorkspaceTravelInvoicingSection.tsx b/src/pages/workspace/travel/WorkspaceTravelInvoicingSection.tsx
index f8ce87367218..e4a6bc1b354f 100644
--- a/src/pages/workspace/travel/WorkspaceTravelInvoicingSection.tsx
+++ b/src/pages/workspace/travel/WorkspaceTravelInvoicingSection.tsx
@@ -30,7 +30,7 @@ import {getCardSettings, getEligibleBankAccountsForCard} from '@libs/CardUtils';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import {areTravelPersonalDetailsMissing} from '@libs/PersonalDetailsUtils';
-import {hasInProgressUSDVBBA, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
+import {hasInProgressUSDVBBA} from '@libs/ReimbursementAccountUtils';
 import {
     getIsTravelInvoicingEnabled,
     getTravelInvoicingCardSettingsKey,
@@ -175,7 +175,6 @@ function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSec
             Navigation.navigate(
                 ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
                     policyID,
-                    stepToOpen: REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW,
                     backTo: ROUTES.WORKSPACE_TRAVEL.getRoute(policyID),
                 }),
             );
diff --git a/src/pages/workspace/travel/WorkspaceTravelInvoicingSettlementAccountPage.tsx b/src/pages/workspace/travel/WorkspaceTravelInvoicingSettlementAccountPage.tsx
index 1203dfce00b2..981ab69e16ff 100644
--- a/src/pages/workspace/travel/WorkspaceTravelInvoicingSettlementAccountPage.tsx
+++ b/src/pages/workspace/travel/WorkspaceTravelInvoicingSettlementAccountPage.tsx
@@ -15,7 +15,6 @@ import {configureTravelInvoicingForPolicy, setTravelInvoicingSettlementAccount}
 import {getLastFourDigits} from '@libs/BankAccountUtils';
 import {getCardSettings, getEligibleBankAccountsForCard} from '@libs/CardUtils';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import {REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
 import {getIsTravelInvoicingEnabled, getTravelInvoicingCardSettingsKey} from '@libs/TravelInvoicingUtils';
 import Navigation from '@navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@navigation/types';
@@ -97,7 +96,6 @@ function WorkspaceTravelInvoicingSettlementAccountPage({route}: WorkspaceTravelI
         Navigation.navigate(
             ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
                 policyID,
-                stepToOpen: REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW,
                 backTo: ROUTES.WORKSPACE_TRAVEL_SETTINGS_ACCOUNT.getRoute(policyID),
             }),
         );
diff --git a/tests/unit/ReimbursementAccountUtilsTest.ts b/tests/unit/ReimbursementAccountUtilsTest.ts
index b531357e9865..e2f3be2e8703 100644
--- a/tests/unit/ReimbursementAccountUtilsTest.ts
+++ b/tests/unit/ReimbursementAccountUtilsTest.ts
@@ -1,19 +1,12 @@
 import Onyx from 'react-native-onyx';
 import CONST from '../../src/CONST';
-import {getBankAccountIDAsNumber, getRouteForCurrentStep, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '../../src/libs/ReimbursementAccountUtils';
+import {getBankAccountIDAsNumber} from '../../src/libs/ReimbursementAccountUtils';
 import ONYXKEYS from '../../src/ONYXKEYS';
 import type {ACHDataReimbursementAccount} from '../../src/types/onyx/ReimbursementAccount';
 
 Onyx.init({keys: ONYXKEYS});
 
 describe('ReimbursementAccountUtils', () => {
-    describe('getRouteForCurrentStep', () => {
-        it("should return 'new' step if 'BankAccountStep' or '' is provided", () => {
-            expect(getRouteForCurrentStep(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT)).toEqual(REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW);
-            expect(getRouteForCurrentStep('')).toEqual(REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW);
-        });
-    });
-
     describe('getBankAccountIDAsNumber', () => {
         it('should return DEFAULT_NUMBER_ID when achData is undefined', () => {
             // Given no ACH data

From b900245311f9d7f0c8ac3ec9790bab8acdff525e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Tue, 12 May 2026 10:29:09 +0200
Subject: [PATCH 02/11] fix: update details

---
 .../ConnectBankAccount/ConnectBankAccount.tsx   |  7 ++++++-
 .../components/FinishChatCard.tsx               | 17 +++++++++++++++--
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
index 640215e572f3..3b67b12cecca 100644
--- a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
+++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
@@ -18,6 +18,7 @@ import {navigateToConciergeChat} from '@userActions/Report';
 import CONST from '@src/CONST';
 import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
+import type {Route} from '@src/ROUTES';
 import BankAccountValidationForm from './components/BankAccountValidationForm';
 import FinishChatCard from './components/FinishChatCard';
 
@@ -30,9 +31,12 @@ type ConnectBankAccountProps = {
 
     /** Method to set the state of shouldShowConnectedVerifiedBankAccount */
     setUSDBankAccountStep?: (step: string | null) => void;
+
+    /** Route to return to when navigating back out of the flow */
+    backTo?: Route;
 };
 
-function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBankAccount, setUSDBankAccountStep}: ConnectBankAccountProps) {
+function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBankAccount, setUSDBankAccountStep, backTo}: ConnectBankAccountProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const topmostFullScreenRoute = useRootNavigationState((state) => state?.routes.findLast((lastRoute) => isFullScreenName(lastRoute.name)));
@@ -116,6 +120,7 @@ function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBa
                     requiresTwoFactorAuth={requiresTwoFactorAuth}
                     reimbursementAccount={reimbursementAccount}
                     setUSDBankAccountStep={setUSDBankAccountStep}
+                    backTo={backTo}
                 />
             )}
         </ScreenWrapper>
diff --git a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx
index b7e469bbe45e..812757880738 100644
--- a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx
+++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx
@@ -10,11 +10,14 @@ import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
 import WorkspaceResetBankAccountModal from '@pages/workspace/WorkspaceResetBankAccountModal';
 import {goToWithdrawalAccountSetupStep, requestResetBankAccount, setBankAccountSubStep} from '@userActions/BankAccounts';
 import {navigateToConciergeChat} from '@userActions/Report';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import type {Route} from '@src/ROUTES';
 import type {ReimbursementAccount} from '@src/types/onyx';
 import Enable2FACard from './Enable2FACard';
 
@@ -27,9 +30,12 @@ type FinishChatCardProps = {
 
     /** Method to set the state of USD bank account step */
     setUSDBankAccountStep?: (step: string | null) => void;
+
+    /** Route to return to when navigating back out of the flow */
+    backTo?: Route;
 };
 
-function FinishChatCard({requiresTwoFactorAuth, reimbursementAccount, setUSDBankAccountStep}: FinishChatCardProps) {
+function FinishChatCard({requiresTwoFactorAuth, reimbursementAccount, setUSDBankAccountStep, backTo}: FinishChatCardProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
@@ -77,8 +83,15 @@ function FinishChatCard({requiresTwoFactorAuth, reimbursementAccount, setUSDBank
                     title={translate('workspace.bankAccount.updateDetails')}
                     onPress={() => {
                         setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL).then(() => {
-                            setUSDBankAccountStep?.(CONST.BANK_ACCOUNT.STEP.REQUESTOR);
                             goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.REQUESTOR);
+                            Navigation.navigate(
+                                ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({
+                                    policyID,
+                                    page: CONST.BANK_ACCOUNT.PAGE_NAMES.REQUESTOR,
+                                    subPage: CONST.BANK_ACCOUNT.PERSONAL_INFO_STEP.SUB_PAGE_NAMES.FULL_NAME,
+                                    backTo,
+                                }),
+                            );
                         });
                     }}
                     outerWrapperStyle={shouldUseNarrowLayout ? styles.mhn5 : styles.mhn8}

From ca7494a614f3cf8b0c30637c03dfd535810e72b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Tue, 12 May 2026 12:29:46 +0200
Subject: [PATCH 03/11] fix: hide date picker on navigating forward via
 hardware button

---
 src/components/DatePicker/index.tsx | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index ef1a17889f85..c3f813054e2a 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -175,6 +175,7 @@ function DatePicker({
                 anchorPosition={popoverPosition}
                 shouldPositionFromTop={!isInverted}
                 forwardedFSClass={forwardedFSClass}
+                shouldCloseWhenBrowserNavigationChanged
             />
         </>
     );

From 74ff832403db46aa41a304df2857e470277f8147 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Thu, 14 May 2026 11:18:39 +0200
Subject: [PATCH 04/11] fix: allow resubmitting after going back

---
 .../CompleteVerification/CompleteVerification.tsx   | 13 +++++++++++--
 .../subSteps/ConfirmAgreements.tsx                  |  2 +-
 src/types/onyx/ReimbursementAccount.ts              |  3 +++
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx b/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx
index 4110007599d6..a428397b24b1 100644
--- a/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx
+++ b/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx
@@ -39,13 +39,22 @@ function CompleteVerification({onBackButtonPress, onSubmit}: CompleteVerificatio
             {
                 isAuthorizedToUseBankAccount: values.isAuthorizedToUseBankAccount,
                 certifyTrueInformation: values.certifyTrueInformation,
-                acceptTermsAndConditions: values.acceptTermsAndConditions,
+                acceptTermsAndConditions: (values.acceptTermsAndConditions || reimbursementAccount?.achData?.acceptTerms) ?? false,
             },
             policyID,
             policyID ? lastPaymentMethod?.[policyID] : undefined,
         );
         markSubmitting();
-    }, [bankAccountID, values.isAuthorizedToUseBankAccount, values.certifyTrueInformation, values.acceptTermsAndConditions, policyID, lastPaymentMethod, markSubmitting]);
+    }, [
+        bankAccountID,
+        values.isAuthorizedToUseBankAccount,
+        values.certifyTrueInformation,
+        values.acceptTermsAndConditions,
+        reimbursementAccount?.achData?.acceptTerms,
+        policyID,
+        lastPaymentMethod,
+        markSubmitting,
+    ]);
 
     return (
         <InteractiveStepWrapper
diff --git a/src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx b/src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx
index ad825930e2f1..34b648cea0dc 100644
--- a/src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx
+++ b/src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx
@@ -52,7 +52,7 @@ function ConfirmAgreements({onNext}: ConfirmAgreementsProps) {
     const defaultValues = {
         isAuthorizedToUseBankAccount: confirmAgreementsValues.isAuthorizedToUseBankAccount ?? false,
         certifyTrueInformation: confirmAgreementsValues.certifyTrueInformation ?? false,
-        acceptTermsAndConditions: confirmAgreementsValues.acceptTermsAndConditions ?? false,
+        acceptTermsAndConditions: (confirmAgreementsValues.acceptTermsAndConditions || reimbursementAccount?.achData?.acceptTerms) ?? false,
     };
     const validate = useCallback(
         (values: FormOnyxValues<typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM> => {
diff --git a/src/types/onyx/ReimbursementAccount.ts b/src/types/onyx/ReimbursementAccount.ts
index ba47e03db79f..a107c8dee8ad 100644
--- a/src/types/onyx/ReimbursementAccount.ts
+++ b/src/types/onyx/ReimbursementAccount.ts
@@ -175,6 +175,9 @@ type ACHData = Partial<BeneficialOwnersStepProps & CompanyStepProps & RequestorS
     /** Weather Onfido setup is complete */
     isOnfidoSetupComplete?: boolean;
 
+    /** Confirmation that the user accepted the ACH terms. The form input key is `acceptTermsAndConditions`; the achData field uses the shorter `acceptTerms`. */
+    acceptTerms?: boolean;
+
     /** Last 4 digits of the account number */
     mask?: string;
 

From 7a32a738af878c62db866ac10aed477ce54cd689 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Fri, 15 May 2026 12:58:04 +0200
Subject: [PATCH 05/11] fix: reseting freshly connected acc

---
 .../resetUSDBankAccount.ts                    |  8 +++++-
 .../ConnectBankAccount/ConnectBankAccount.tsx | 25 +++++++++++++++++--
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/src/libs/actions/ReimbursementAccount/resetUSDBankAccount.ts b/src/libs/actions/ReimbursementAccount/resetUSDBankAccount.ts
index 15d5e13f43f4..b1b3a6df7190 100644
--- a/src/libs/actions/ReimbursementAccount/resetUSDBankAccount.ts
+++ b/src/libs/actions/ReimbursementAccount/resetUSDBankAccount.ts
@@ -88,7 +88,13 @@ function resetUSDBankAccount(
             {
                 onyxMethod: Onyx.METHOD.SET,
                 key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
-                value: CONST.REIMBURSEMENT_ACCOUNT.DEFAULT_DATA,
+                value: {
+                    ...CONST.REIMBURSEMENT_ACCOUNT.DEFAULT_DATA,
+                    achData: {
+                        ...CONST.REIMBURSEMENT_ACCOUNT.DEFAULT_DATA.achData,
+                        policyID,
+                    },
+                },
             },
             {
                 onyxMethod: Onyx.METHOD.SET,
diff --git a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
index 3b67b12cecca..060901a2ad92 100644
--- a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
+++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
@@ -1,8 +1,9 @@
 import {hasSeenTourSelector} from '@selectors/Onboarding';
-import React from 'react';
+import React, {useEffect, useRef} from 'react';
 import {View} from 'react-native';
 import ConfirmationPage from '@components/ConfirmationPage';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ReimbursementAccountLoadingIndicator from '@components/ReimbursementAccountLoadingIndicator';
 import ScreenWrapper from '@components/ScreenWrapper';
 import Text from '@components/Text';
 import TextLink from '@components/TextLink';
@@ -18,6 +19,7 @@ import {navigateToConciergeChat} from '@userActions/Report';
 import CONST from '@src/CONST';
 import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import type {Route} from '@src/ROUTES';
 import BankAccountValidationForm from './components/BankAccountValidationForm';
 import FinishChatCard from './components/FinishChatCard';
@@ -32,11 +34,14 @@ type ConnectBankAccountProps = {
     /** Method to set the state of shouldShowConnectedVerifiedBankAccount */
     setUSDBankAccountStep?: (step: string | null) => void;
 
+    /** ID of current policy */
+    policyID?: string;
+
     /** Route to return to when navigating back out of the flow */
     backTo?: Route;
 };
 
-function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBankAccount, setUSDBankAccountStep, backTo}: ConnectBankAccountProps) {
+function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBankAccount, setUSDBankAccountStep, policyID, backTo}: ConnectBankAccountProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const topmostFullScreenRoute = useRootNavigationState((state) => state?.routes.findLast((lastRoute) => isFullScreenName(lastRoute.name)));
@@ -52,6 +57,22 @@ function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBa
 
     const handleNavigateToConciergeChat = () => navigateToConciergeChat(conciergeReportID, introSelected, currentUserAccountID, isSelfTourViewed, betas, true);
     const bankAccountState = reimbursementAccount?.achData?.state ?? '';
+    const pendingAction = reimbursementAccount?.pendingAction;
+
+    // After a disconnect, wait for the reset API to finish before navigating to the entry point.
+    const prevPendingActionRef = useRef(pendingAction);
+    useEffect(() => {
+        const prev = prevPendingActionRef.current;
+        prevPendingActionRef.current = pendingAction;
+        if (prev === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) {
+            Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID, backTo}));
+        }
+    }, [pendingAction, policyID, backTo]);
+
+    // While the disconnect is in flight, show the existing flow loader so the success screen doesn't re-render with cleared bank data
+    if (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) {
+        return <ReimbursementAccountLoadingIndicator onBackButtonPress={onBackButtonPress} />;
+    }
 
     // If a user tries to navigate directly to the validate page we'll show them the EnableStep
     if (bankAccountState === CONST.BANK_ACCOUNT.STATE.OPEN) {

From d7e09b348ac8fe7f08d2afcbefbd60af243895ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Tue, 19 May 2026 11:28:45 +0200
Subject: [PATCH 06/11] fix: modal closing on its own

---
 src/components/Modal/index.tsx                |  3 +-
 src/components/Modal/internalPopstateGuard.ts | 17 +++++
 src/components/Popover/index.tsx              |  6 ++
 tests/unit/internalPopstateGuardTest.ts       | 74 +++++++++++++++++++
 4 files changed, 99 insertions(+), 1 deletion(-)
 create mode 100644 src/components/Modal/internalPopstateGuard.ts
 create mode 100644 tests/unit/internalPopstateGuardTest.ts

diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx
index 332c92cd71a3..f2d799a5ef54 100644
--- a/src/components/Modal/index.tsx
+++ b/src/components/Modal/index.tsx
@@ -4,6 +4,7 @@ import useTheme from '@hooks/useTheme';
 import StatusBar from '@libs/StatusBar';
 import CONST from '@src/CONST';
 import BaseModal from './BaseModal';
+import {withInternalPopstate} from './internalPopstateGuard';
 import type BaseModalProps from './types';
 import type {WindowState} from './types';
 
@@ -55,7 +56,7 @@ function Modal({fullscreen = true, onModalHide = () => {}, type, onModalShow = (
                 if (!(window.history.state as WindowState)?.shouldGoBack) {
                     return;
                 }
-                window.history.back();
+                withInternalPopstate(() => window.history.back());
             }, 0);
         } else {
             onModalHide();
diff --git a/src/components/Modal/internalPopstateGuard.ts b/src/components/Modal/internalPopstateGuard.ts
new file mode 100644
index 000000000000..1992e0b5ef02
--- /dev/null
+++ b/src/components/Modal/internalPopstateGuard.ts
@@ -0,0 +1,17 @@
+let isInternal = false;
+
+function isInternalPopstateInProgress(): boolean {
+    return isInternal;
+}
+
+function withInternalPopstate(action: () => void) {
+    isInternal = true;
+    const clear = () => {
+        isInternal = false;
+        window.removeEventListener('popstate', clear);
+    };
+    window.addEventListener('popstate', clear);
+    action();
+}
+
+export {isInternalPopstateInProgress, withInternalPopstate};
diff --git a/src/components/Popover/index.tsx b/src/components/Popover/index.tsx
index e5849d72d6a7..2434545ddb77 100644
--- a/src/components/Popover/index.tsx
+++ b/src/components/Popover/index.tsx
@@ -1,6 +1,7 @@
 import React, {useRef} from 'react';
 import {createPortal} from 'react-dom';
 import Modal from '@components/Modal';
+import {isInternalPopstateInProgress} from '@components/Modal/internalPopstateGuard';
 import {usePopoverActions, usePopoverState} from '@components/PopoverProvider';
 import PopoverWithoutOverlay from '@components/PopoverWithoutOverlay';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
@@ -59,6 +60,11 @@ function Popover(props: PopoverProps) {
             if (!isVisible) {
                 return;
             }
+            // A nested Modal closing itself fires history.back() to drop its guard entry;
+            // that popstate is not a real user navigation, so skip closing.
+            if (isInternalPopstateInProgress()) {
+                return;
+            }
             onClose?.();
         };
         window.addEventListener('popstate', listener);
diff --git a/tests/unit/internalPopstateGuardTest.ts b/tests/unit/internalPopstateGuardTest.ts
new file mode 100644
index 000000000000..875088da3e1b
--- /dev/null
+++ b/tests/unit/internalPopstateGuardTest.ts
@@ -0,0 +1,74 @@
+import {isInternalPopstateInProgress, withInternalPopstate} from '@components/Modal/internalPopstateGuard';
+
+describe('internalPopstateGuard', () => {
+    afterEach(() => {
+        // Drain any lingering popstate listener so the module-scoped flag is back to false before the next case.
+        window.dispatchEvent(new PopStateEvent('popstate'));
+    });
+
+    it('reports false by default', () => {
+        expect(isInternalPopstateInProgress()).toBe(false);
+    });
+
+    it('reports true synchronously after withInternalPopstate is called, before any popstate fires', () => {
+        withInternalPopstate(() => {});
+        expect(isInternalPopstateInProgress()).toBe(true);
+    });
+
+    it('runs the action synchronously', () => {
+        const action = jest.fn();
+        withInternalPopstate(action);
+        expect(action).toHaveBeenCalledTimes(1);
+    });
+
+    it('clears the flag after the next popstate event fires', () => {
+        withInternalPopstate(() => {});
+        expect(isInternalPopstateInProgress()).toBe(true);
+
+        window.dispatchEvent(new PopStateEvent('popstate'));
+
+        expect(isInternalPopstateInProgress()).toBe(false);
+    });
+
+    it('detaches its popstate listener after one event (subsequent popstates do not flip the flag)', () => {
+        withInternalPopstate(() => {});
+        window.dispatchEvent(new PopStateEvent('popstate'));
+        expect(isInternalPopstateInProgress()).toBe(false);
+
+        window.dispatchEvent(new PopStateEvent('popstate'));
+        expect(isInternalPopstateInProgress()).toBe(false);
+    });
+
+    it('a listener registered before withInternalPopstate sees the flag as true during the same popstate', () => {
+        let observedDuringEvent: boolean | undefined;
+        const popoverListener = () => {
+            observedDuringEvent = isInternalPopstateInProgress();
+        };
+        window.addEventListener('popstate', popoverListener);
+
+        withInternalPopstate(() => {});
+        window.dispatchEvent(new PopStateEvent('popstate'));
+
+        expect(observedDuringEvent).toBe(true);
+        expect(isInternalPopstateInProgress()).toBe(false);
+
+        window.removeEventListener('popstate', popoverListener);
+    });
+
+    it('a listener registered after withInternalPopstate sees the flag already cleared', () => {
+        withInternalPopstate(() => {});
+
+        let observedDuringEvent: boolean | undefined;
+        const lateListener = () => {
+            observedDuringEvent = isInternalPopstateInProgress();
+        };
+        window.addEventListener('popstate', lateListener);
+
+        window.dispatchEvent(new PopStateEvent('popstate'));
+
+        // Clear listener was registered before lateListener, so by the time lateListener runs the flag is already released.
+        expect(observedDuringEvent).toBe(false);
+
+        window.removeEventListener('popstate', lateListener);
+    });
+});

From be352963024c1f1724842a65013d85a5578d45be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Tue, 19 May 2026 13:00:13 +0200
Subject: [PATCH 07/11] fix: lint

---
 src/ROUTES.ts | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 290b780e3b0f..2caa6453d25f 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -868,17 +868,15 @@ const ROUTES = {
     BANK_ACCOUNT_WITH_STEP_TO_OPEN: {
         route: 'bank-account/new',
         getRoute: ({policyID, bankAccountID, backTo}: {policyID: string | undefined; bankAccountID?: number; backTo?: string}) => {
-            if (!policyID && !bankAccountID) {
-                return getUrlWithBackToParam(`bank-account/new`, backTo);
-            }
-
+            let queryString = '';
             if (bankAccountID) {
-                return getUrlWithBackToParam(`bank-account/new?bankAccountID=${bankAccountID}`, backTo);
+                queryString = `?bankAccountID=${bankAccountID}`;
+            } else if (policyID) {
+                queryString = `?policyID=${policyID}`;
             }
             // TODO this backTo comes from drilling it through bank account form screens
             // should be removed once https://github.com/Expensify/App/pull/72219 is resolved
-
-            return getUrlWithBackToParam(`bank-account/new?policyID=${policyID}`, backTo);
+            return getUrlWithBackToParam(`bank-account/new${queryString}`, backTo);
         },
     },
     BANK_ACCOUNT_ENTER_SIGNER_INFO: {
@@ -916,7 +914,7 @@ const ROUTES = {
             const subPagePart = subPage ? `/${subPage}` : '';
             const actionPart = action ? `/${action}` : '';
             const queryString = policyID ? `?policyID=${policyID}` : '';
-            // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
+
             return getUrlWithBackToParam(`${base}${pagePart}${subPagePart}${actionPart}${queryString}`, backTo);
         },
     },

From 9e056f4ac41685a21fbf28192694ab580b3720b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Wed, 20 May 2026 08:32:18 +0200
Subject: [PATCH 08/11] prettier

---
 src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index a401d3580ca7..ac4f1a0e3b9a 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -3,8 +3,8 @@ import React, {useCallback} from 'react';
 import {View} from 'react-native';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
-import withAgentAccessDenied from '@libs/Navigation/AppNavigator/withAgentAccessDenied';
 import {isMobileChrome} from '@libs/Browser';
+import withAgentAccessDenied from '@libs/Navigation/AppNavigator/withAgentAccessDenied';
 import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator';
 import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation';
 import type {PlatformStackNavigationOptions} from '@libs/Navigation/PlatformStackNavigation/types';

From 169e0b5b463bec73e7ea0284a594af7886517f74 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Mon, 25 May 2026 08:40:42 +0200
Subject: [PATCH 09/11] fix: auto checks

---
 .../USD/ConnectBankAccount/ConnectBankAccount.tsx      |  1 +
 .../ConnectBankAccount/components/FinishChatCard.tsx   | 10 +++++++---
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
index 060901a2ad92..e64d20446ed0 100644
--- a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
+++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx
@@ -142,6 +142,7 @@ function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBa
                     reimbursementAccount={reimbursementAccount}
                     setUSDBankAccountStep={setUSDBankAccountStep}
                     backTo={backTo}
+                    policy={policy}
                 />
             )}
         </ScreenWrapper>
diff --git a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx
index 812757880738..840f07c0b9eb 100644
--- a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx
+++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx
@@ -1,5 +1,6 @@
 import {hasSeenTourSelector} from '@selectors/Onboarding';
 import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
 import MenuItem from '@components/MenuItem';
 import ScrollView from '@components/ScrollView';
 import Section from '@components/Section';
@@ -18,7 +19,7 @@ import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type {Route} from '@src/ROUTES';
-import type {ReimbursementAccount} from '@src/types/onyx';
+import type {Policy, ReimbursementAccount} from '@src/types/onyx';
 import Enable2FACard from './Enable2FACard';
 
 type FinishChatCardProps = {
@@ -28,6 +29,9 @@ type FinishChatCardProps = {
     /** Boolean required to display Enable2FACard component */
     requiresTwoFactorAuth: boolean;
 
+    /** The policy which the user has access to and which the report is tied to */
+    policy: OnyxEntry<Policy>;
+
     /** Method to set the state of USD bank account step */
     setUSDBankAccountStep?: (step: string | null) => void;
 
@@ -35,7 +39,7 @@ type FinishChatCardProps = {
     backTo?: Route;
 };
 
-function FinishChatCard({requiresTwoFactorAuth, reimbursementAccount, setUSDBankAccountStep, backTo}: FinishChatCardProps) {
+function FinishChatCard({requiresTwoFactorAuth, reimbursementAccount, policy, setUSDBankAccountStep, backTo}: FinishChatCardProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
@@ -86,7 +90,7 @@ function FinishChatCard({requiresTwoFactorAuth, reimbursementAccount, setUSDBank
                             goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.REQUESTOR);
                             Navigation.navigate(
                                 ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({
-                                    policyID,
+                                    policyID: policy?.id,
                                     page: CONST.BANK_ACCOUNT.PAGE_NAMES.REQUESTOR,
                                     subPage: CONST.BANK_ACCOUNT.PERSONAL_INFO_STEP.SUB_PAGE_NAMES.FULL_NAME,
                                     backTo,

From e9a2719209ed327b58ea948def83d0f320c2249d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Wed, 27 May 2026 13:24:21 +0200
Subject: [PATCH 10/11] fix: review

---
 src/components/Modal/internalPopstateGuard.ts                  | 2 ++
 .../Navigation/AppNavigator/ModalStackNavigators/index.tsx     | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/components/Modal/internalPopstateGuard.ts b/src/components/Modal/internalPopstateGuard.ts
index 1992e0b5ef02..96cdd3d52533 100644
--- a/src/components/Modal/internalPopstateGuard.ts
+++ b/src/components/Modal/internalPopstateGuard.ts
@@ -1,9 +1,11 @@
 let isInternal = false;
 
+/** Returns true when the next `popstate` was triggered by our own `history.back()`, not a real user back navigation. */
 function isInternalPopstateInProgress(): boolean {
     return isInternal;
 }
 
+/** Runs `action` (e.g. `history.back()`) while flagging the resulting `popstate` as internal, so listeners can ignore it. */
 function withInternalPopstate(action: () => void) {
     isInternal = true;
     const clear = () => {
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index ac4f1a0e3b9a..11bdb5dc7fef 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -65,7 +65,6 @@ const loadAttachmentModalScreen = () => require<ReactComponentModule>('../../../
 
 type Screens = Partial<Record<Screen, () => React.ComponentType>>;
 
-// Reimbursement Account flow animations glitch on low-end Android devices in Chrome mWeb https://github.com/Expensify/App/issues/87658 so we intentionally disable them
 const IS_MOBILE_CHROME = isMobileChrome();
 
 const REIMBURSEMENT_ACCOUNT_FLOW_SCREENS: Screen[] = [
@@ -143,6 +142,8 @@ const OPTIONS_PER_SCREEN: Partial<Record<Screen, PlatformStackNavigationOptions>
     [SCREENS.TWO_FACTOR_AUTH.SUCCESS]: {
         animationTypeForReplace: 'push',
     },
+    // Reimbursement Account flow animations glitch on low-end Android devices in Chrome mWeb so we intentionally disable them here.
+    // see https://github.com/Expensify/App/issues/87658
     ...(IS_MOBILE_CHROME ? Object.fromEntries(REIMBURSEMENT_ACCOUNT_FLOW_SCREENS.map((screen) => [screen, {animation: Animations.NONE}])) : {}),
 };
 

From 220b7d34718176d2d2cbbb5de6349284c21cb4ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muzyk?= <mimuzyk@gmail.com>
Date: Wed, 27 May 2026 13:35:30 +0200
Subject: [PATCH 11/11] fix: ts

---
 src/components/Navigation/DebugTabView.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/components/Navigation/DebugTabView.tsx b/src/components/Navigation/DebugTabView.tsx
index 9280c430554b..837cecadcfe3 100644
--- a/src/components/Navigation/DebugTabView.tsx
+++ b/src/components/Navigation/DebugTabView.tsx
@@ -21,7 +21,6 @@ import useWindowDimensions from '@hooks/useWindowDimensions';
 import getFocusedLeafScreenName from '@libs/Navigation/helpers/getFocusedLeafScreenName';
 import isTabRouteAtRoot from '@libs/Navigation/helpers/isTabRouteAtRoot';
 import Navigation from '@libs/Navigation/Navigation';
-import {getRouteForCurrentStep as getReimbursementAccountRouteForCurrentStep} from '@libs/ReimbursementAccountUtils';
 import {getChatTabBrickRoadReportID} from '@libs/WorkspacesSettingsUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
