diff --git a/src/App.tsx b/src/App.tsx
index 8ef6d1a55f19..3f0117cf275d 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,6 +1,6 @@
 import {PortalProvider} from '@gorhom/portal';
 import * as Sentry from '@sentry/react-native';
-import React from 'react';
+import React, {useEffect} from 'react';
 import {LogBox, View} from 'react-native';
 import {GestureHandlerRootView} from 'react-native-gesture-handler';
 import {PickerStateProvider} from 'react-native-picker-select';
@@ -51,6 +51,7 @@ import useDefaultDragAndDrop from './hooks/useDefaultDragAndDrop';
 import HybridAppHandler from './HybridAppHandler';
 import OnyxUpdateManager from './libs/actions/OnyxUpdateManager';
 import './libs/HybridApp';
+import NavigationFocusManager from './libs/NavigationFocusManager';
 import {AttachmentModalContextProvider} from './pages/media/AttachmentModalScreen/AttachmentModalContext';
 import ExpensifyCardContextProvider from './pages/settings/Wallet/ExpensifyCardPage/ExpensifyCardContextProvider';
 import TravelCVVContextProvider from './pages/settings/Wallet/TravelCVVPage/TravelCVVContextProvider';
@@ -75,6 +76,16 @@ function App() {
     useDefaultDragAndDrop();
     OnyxUpdateManager();
 
+    // Initialize NavigationFocusManager for web focus restoration during back navigation
+    // This captures focus on pointerdown/keydown before navigation changes focus to body
+    useEffect(() => {
+        NavigationFocusManager.initialize();
+
+        return () => {
+            NavigationFocusManager.destroy();
+        };
+    }, []);
+
     return (
         <StrictModeWrapper>
             <SplashScreenStateContextProvider>
diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index c218909a6a3d..7a4ef6dd9a1f 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -71,6 +71,8 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
                         </Text>
                     </View>
                 )}
+                {/* MenuItems are display-only (interactive={false}) because the outer
+                    PressableWithoutFeedback handles all click interactions. */}
                 <MenuItem
                     title={translate('workflowsExpensesFromPage.title')}
                     style={styles.p0}
@@ -84,7 +86,7 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
                     iconHeight={20}
                     iconWidth={20}
                     iconFill={theme.icon}
-                    onPress={onPress}
+                    interactive={false}
                     shouldRemoveBackground
                     sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.WORKFLOWS.APPROVAL_SECTION_EXPENSES_FROM}
                 />
@@ -106,7 +108,7 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
                             iconWidth={20}
                             numberOfLinesDescription={1}
                             iconFill={theme.icon}
-                            onPress={onPress}
+                            interactive={false}
                             shouldRemoveBackground
                             helperText={getApprovalLimitDescription({approver, currency, translate, personalDetailsByEmail})}
                             helperTextStyle={styles.workflowApprovalLimitText}
diff --git a/src/components/ButtonWithDropdownMenu/index.tsx b/src/components/ButtonWithDropdownMenu/index.tsx
index afe40ec903ef..014b9bba18de 100644
--- a/src/components/ButtonWithDropdownMenu/index.tsx
+++ b/src/components/ButtonWithDropdownMenu/index.tsx
@@ -1,4 +1,4 @@
-import type {RefObject} from 'react';
+import type {RefCallback} from 'react';
 import React, {useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
 import {View} from 'react-native';
 import type {GestureResponderEvent} from 'react-native';
@@ -14,9 +14,11 @@ import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import mergeRefs from '@libs/mergeRefs';
+import NavigationFocusManager from '@libs/NavigationFocusManager';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import type {AnchorPosition} from '@src/styles';
+import viewRef from '@src/types/utils/viewRef';
 import type {ButtonWithDropdownMenuProps} from './types';
 
 const defaultAnchorAlignment = {
@@ -25,6 +27,8 @@ const defaultAnchorAlignment = {
     vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP,
 };
 
+type DropdownAnchor = View | HTMLDivElement | null;
+
 function ButtonWithDropdownMenu<IValueType>({ref, ...props}: ButtonWithDropdownMenuProps<IValueType>) {
     const {
         success = true,
@@ -74,18 +78,22 @@ function ButtonWithDropdownMenu<IValueType>({ref, ...props}: ButtonWithDropdownM
     // In tests, skip the popover anchor position calculation. The default values are needed for popover menu to be rendered in tests.
     const defaultPopoverAnchorPosition = process.env.NODE_ENV === 'test' ? {horizontal: 100, vertical: 100} : null;
     const [popoverAnchorPosition, setPopoverAnchorPosition] = useState<AnchorPosition | null>(defaultPopoverAnchorPosition);
-    const dropdownAnchor = useRef<View | null>(null);
+    const dropdownAnchor = useRef<DropdownAnchor>(null);
+    const [wasOpenedViaKeyboard, setWasOpenedViaKeyboard] = useState(false);
     // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout to apply correct popover styles
     // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
     const {isSmallScreenWidth} = useResponsiveLayout();
-    const dropdownButtonRef = isSplitButton ? buttonRef : mergeRefs(buttonRef, dropdownAnchor);
+    const setDropdownAnchor: RefCallback<View> = useCallback((node: DropdownAnchor) => {
+        dropdownAnchor.current = node;
+    }, []);
+    // eslint-disable-next-line react-hooks/refs -- mergeRefs creates a ref callback and does not read ref.current during render
+    const dropdownButtonRef = isSplitButton ? buttonRef : mergeRefs(buttonRef, setDropdownAnchor);
     const selectedItem = options.at(selectedItemIndex) ?? options.at(0);
     const areAllOptionsDisabled = options.every((option) => option.disabled);
     const innerStyleDropButton = StyleUtils.getDropDownButtonHeight(buttonSize);
     const isButtonSizeLarge = buttonSize === CONST.DROPDOWN_BUTTON_SIZE.LARGE;
     const isButtonSizeSmall = buttonSize === CONST.DROPDOWN_BUTTON_SIZE.SMALL;
     const isButtonSizeExtraSmall = buttonSize === CONST.DROPDOWN_BUTTON_SIZE.EXTRA_SMALL;
-    const nullCheckRef = (refParam: RefObject<View | null>) => refParam ?? null;
     const shouldShowButtonRightIcon = !!options.at(0)?.shouldShowButtonRightIcon;
 
     useEffect(() => {
@@ -101,7 +109,7 @@ function ButtonWithDropdownMenu<IValueType>({ref, ...props}: ButtonWithDropdownM
             return;
         }
 
-        calculatePopoverPosition(dropdownAnchor, anchorAlignment).then(setPopoverAnchorPosition);
+        calculatePopoverPosition(viewRef(dropdownAnchor), anchorAlignment).then(setPopoverAnchorPosition);
     }, [isMenuVisible, calculatePopoverPosition, anchorAlignment]);
 
     const handleSingleOptionPress = useCallback(
@@ -123,12 +131,27 @@ function ButtonWithDropdownMenu<IValueType>({ref, ...props}: ButtonWithDropdownM
         [options, onPress, onOptionSelected, onSubItemSelected],
     );
 
+    /** Opens or closes the menu with keyboard tracking */
+    const toggleMenu = useCallback(() => {
+        if (!isMenuVisible) {
+            // Capture keyboard state BEFORE menu opens
+            const wasKeyboardInteraction = NavigationFocusManager.wasRecentKeyboardInteraction();
+            setWasOpenedViaKeyboard(wasKeyboardInteraction);
+            if (wasKeyboardInteraction) {
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+            }
+        } else {
+            setWasOpenedViaKeyboard(false);
+        }
+        setIsMenuVisible(!isMenuVisible);
+    }, [isMenuVisible]);
+
     useKeyboardShortcut(
         CONST.KEYBOARD_SHORTCUTS.CTRL_ENTER,
         (e) => {
             if (shouldAlwaysShowDropdownMenu || options.length) {
                 if (!isSplitButton) {
-                    setIsMenuVisible(!isMenuVisible);
+                    toggleMenu();
                     return;
                 }
                 if (selectedItem?.value) {
@@ -150,18 +173,28 @@ function ButtonWithDropdownMenu<IValueType>({ref, ...props}: ButtonWithDropdownM
     const handlePress = useCallback(
         (event?: GestureResponderEvent | KeyboardEvent) => {
             if (!isSplitButton) {
-                setIsMenuVisible(!isMenuVisible);
+                toggleMenu();
             } else if (selectedItem?.value) {
                 onPress(event, selectedItem.value);
             }
         },
-        [isMenuVisible, isSplitButton, onPress, selectedItem?.value],
+        [isSplitButton, onPress, selectedItem?.value, toggleMenu],
     );
 
     useImperativeHandle(ref, () => ({
         setIsMenuVisible,
     }));
 
+    const focusDropdownAnchor = useCallback(() => {
+        const anchor = dropdownAnchor.current;
+
+        if (!anchor || !('focus' in anchor) || typeof anchor.focus !== 'function') {
+            return;
+        }
+
+        anchor.focus();
+    }, []);
+
     return (
         <View style={wrapperStyle}>
             {shouldAlwaysShowDropdownMenu || options.length > 1 ? (
@@ -199,12 +232,12 @@ function ButtonWithDropdownMenu<IValueType>({ref, ...props}: ButtonWithDropdownM
 
                     {isSplitButton && (
                         <Button
-                            ref={dropdownAnchor}
+                            ref={setDropdownAnchor}
                             success={success}
                             isDisabled={isDisabled}
                             shouldStayNormalOnDisable={shouldStayNormalOnDisable}
                             style={[styles.pl0]}
-                            onPress={() => setIsMenuVisible(!isMenuVisible)}
+                            onPress={toggleMenu}
                             shouldRemoveLeftBorderRadius
                             extraSmall={buttonSize === CONST.DROPDOWN_BUTTON_SIZE.EXTRA_SMALL}
                             large={buttonSize === CONST.DROPDOWN_BUTTON_SIZE.LARGE}
@@ -271,9 +304,12 @@ function ButtonWithDropdownMenu<IValueType>({ref, ...props}: ButtonWithDropdownM
                     isVisible={isMenuVisible}
                     onClose={() => {
                         setIsMenuVisible(false);
+                        setWasOpenedViaKeyboard(false);
                         onOptionsMenuHide?.();
                     }}
+                    wasOpenedViaKeyboard={wasOpenedViaKeyboard}
                     onModalShow={onOptionsMenuShow}
+                    onModalHide={focusDropdownAnchor}
                     onItemSelected={(selectedSubitem, index, event) => {
                         onSubItemSelected?.(selectedSubitem, index, event);
                         if (selectedSubitem.shouldCloseModalOnSelect !== false) {
@@ -282,7 +318,7 @@ function ButtonWithDropdownMenu<IValueType>({ref, ...props}: ButtonWithDropdownM
                     }}
                     anchorPosition={popoverAnchorPosition}
                     shouldShowSelectedItemCheck={shouldShowSelectedItemCheck}
-                    anchorRef={nullCheckRef(dropdownAnchor)}
+                    anchorRef={dropdownAnchor}
                     scrollContainerStyle={!shouldUseModalPaddingStyle && isSmallScreenWidth && {...styles.pt4, paddingBottom}}
                     anchorAlignment={anchorAlignment}
                     shouldUseModalPaddingStyle={shouldUseModalPaddingStyle}
diff --git a/src/components/ConfirmModal.tsx b/src/components/ConfirmModal.tsx
index 02be40520fb3..cdeffaff08f0 100755
--- a/src/components/ConfirmModal.tsx
+++ b/src/components/ConfirmModal.tsx
@@ -1,12 +1,16 @@
 import type {ReactNode} from 'react';
-import React from 'react';
+import React, {useLayoutEffect, useRef} from 'react';
 import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
+import {View} from 'react-native';
 import usePrevious from '@hooks/usePrevious';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
+import getPlatform from '@libs/getPlatform';
+import NavigationFocusManager from '@libs/NavigationFocusManager';
 import CONST from '@src/CONST';
 import type IconAsset from '@src/types/utils/IconAsset';
 import ConfirmContent from './ConfirmContent';
+import {getInitialFocusTarget, isWebPlatform, restoreCapturedAnchorFocus, shouldTryKeyboardInitialFocus} from './ConfirmModal/focusRestore';
 import Modal from './Modal';
 import type BaseModalProps from './Modal/types';
 
@@ -161,6 +165,72 @@ function ConfirmModal({
     // Previous state needed for exiting animation to play correctly.
     const prevVisible = usePrevious(isVisible);
 
+    // Use undefined as initial value to distinguish "not yet captured" from "captured as false"
+    // This is critical for StrictMode double-invocation protection
+    const wasOpenedViaKeyboardRef = useRef<boolean | undefined>(undefined);
+
+    // Ref for scoping DOM queries to this modal's container
+    // CRITICAL: Prevents finding buttons from other modals in nested scenarios
+    const modalContainerRef = useRef<View>(null);
+
+    // Ref for storing the captured anchor element for focus restoration
+    // Captured when modal opens, used when modal closes
+    const capturedAnchorRef = useRef<HTMLElement | null>(null);
+
+    // Capture keyboard state and anchor element when modal opens
+    // useLayoutEffect ensures this runs synchronously before FocusTrap activates
+    useLayoutEffect(() => {
+        if (isVisible && !prevVisible) {
+            // StrictMode guard: Only capture if we haven't already
+            // In StrictMode, effects run twice. Without this guard:
+            //   1st run: reads true, clears flag, stores true in ref
+            //   2nd run: reads false (already cleared!), overwrites ref with false ← BUG!
+            if (wasOpenedViaKeyboardRef.current === undefined) {
+                const wasKeyboard = NavigationFocusManager.wasRecentKeyboardInteraction();
+                wasOpenedViaKeyboardRef.current = wasKeyboard;
+                if (wasKeyboard) {
+                    NavigationFocusManager.clearKeyboardInteractionFlag();
+                }
+            }
+
+            // Capture the anchor element for focus restoration
+            // This must happen NOW, before user clicks within the modal (which would overwrite it)
+            if (capturedAnchorRef.current === null) {
+                capturedAnchorRef.current = NavigationFocusManager.getCapturedAnchorElement();
+            }
+        } else if (!isVisible && prevVisible) {
+            // Reset keyboard ref when modal closes (allows next open to capture)
+            // NOTE: capturedAnchorRef is reset in onModalHide AFTER focus restoration
+            wasOpenedViaKeyboardRef.current = undefined;
+        }
+    }, [isVisible, prevVisible]);
+
+    /**
+     * Compute initialFocus for Modal's FocusTrap.
+     *
+     * IMPORTANT: This must be a function (not an IIFE) so the keyboard check
+     * happens at trap ACTIVATION time, not render time. The useLayoutEffect
+     * that sets wasOpenedViaKeyboardRef runs after render but before trap
+     * activation, so a lazy check will see the correct value.
+     *
+     * Returns false for mouse opens (no auto-focus) or non-web platforms.
+     * Returns HTMLElement (first button) for keyboard opens.
+     */
+    const computeInitialFocus = (): HTMLElement | false => {
+        const platform = getPlatform();
+        const shouldTryFocus = shouldTryKeyboardInitialFocus(!!wasOpenedViaKeyboardRef.current);
+
+        // Check ref LAZILY - this runs when FocusTrap activates (after useLayoutEffect)
+        if (!shouldTryFocus || !isWebPlatform(platform)) {
+            return false;
+        }
+
+        return getInitialFocusTarget({
+            isOpenedViaKeyboard: shouldTryFocus,
+            containerElementRef: modalContainerRef.current,
+        });
+    };
+
     // Perf: Prevents from rendering whole confirm modal on initial render.
     if (!isVisible && !prevVisible) {
         return null;
@@ -172,46 +242,60 @@ function ConfirmModal({
             onBackdropPress={onBackdropPress}
             isVisible={isVisible}
             shouldSetModalVisibility={shouldSetModalVisibility}
-            onModalHide={onModalHide}
+            onModalHide={() => {
+                if (isWebPlatform(getPlatform())) {
+                    restoreCapturedAnchorFocus(capturedAnchorRef.current);
+                }
+
+                // Reset the ref AFTER focus restoration (not in useLayoutEffect)
+                capturedAnchorRef.current = null;
+                onModalHide();
+            }}
             type={isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.CONFIRM}
             innerContainerStyle={styles.pv0}
             shouldEnableNewFocusManagement={shouldEnableNewFocusManagement}
             restoreFocusType={restoreFocusType}
             shouldHandleNavigationBack={shouldHandleNavigationBack}
             shouldIgnoreBackHandlerDuringTransition={shouldIgnoreBackHandlerDuringTransition}
+            initialFocus={computeInitialFocus}
         >
-            <ConfirmContent
-                title={title}
-                /* Disable onConfirm function if the modal is being dismissed, otherwise the confirmation
-            function can be triggered multiple times if the user clicks on the button multiple times. */
-                onConfirm={() => (isVisible ? onConfirm() : null)}
-                onCancel={onCancel}
-                confirmText={confirmText}
-                cancelText={cancelText}
-                prompt={prompt}
-                success={success}
-                danger={danger}
-                isVisible={isVisible}
-                shouldDisableConfirmButtonWhenOffline={shouldDisableConfirmButtonWhenOffline}
-                shouldShowCancelButton={shouldShowCancelButton}
-                shouldCenterContent={shouldCenterContent}
-                iconSource={iconSource}
-                contentStyles={isSmallScreenWidth && shouldShowDismissIcon ? styles.mt2 : undefined}
-                iconFill={iconFill}
-                iconHeight={iconHeight}
-                iconWidth={iconWidth}
-                shouldCenterIcon={shouldCenterIcon}
-                shouldShowDismissIcon={shouldShowDismissIcon}
-                titleContainerStyles={titleContainerStyles}
-                iconAdditionalStyles={iconAdditionalStyles}
-                titleStyles={titleStyles}
-                promptStyles={promptStyles}
-                shouldStackButtons={shouldStackButtons}
-                shouldReverseStackedButtons={shouldReverseStackedButtons}
-                image={image}
-                imageStyles={imageStyles}
-                isConfirmLoading={isConfirmLoading}
-            />
+            <View
+                ref={modalContainerRef}
+                testID="confirm-modal-container"
+            >
+                <ConfirmContent
+                    title={title}
+                    /* Disable onConfirm function if the modal is being dismissed, otherwise the confirmation
+                function can be triggered multiple times if the user clicks on the button multiple times. */
+                    onConfirm={() => (isVisible ? onConfirm() : null)}
+                    onCancel={onCancel}
+                    confirmText={confirmText}
+                    cancelText={cancelText}
+                    prompt={prompt}
+                    success={success}
+                    danger={danger}
+                    isVisible={isVisible}
+                    shouldDisableConfirmButtonWhenOffline={shouldDisableConfirmButtonWhenOffline}
+                    shouldShowCancelButton={shouldShowCancelButton}
+                    shouldCenterContent={shouldCenterContent}
+                    iconSource={iconSource}
+                    contentStyles={isSmallScreenWidth && shouldShowDismissIcon ? styles.mt2 : undefined}
+                    iconFill={iconFill}
+                    iconHeight={iconHeight}
+                    iconWidth={iconWidth}
+                    shouldCenterIcon={shouldCenterIcon}
+                    shouldShowDismissIcon={shouldShowDismissIcon}
+                    titleContainerStyles={titleContainerStyles}
+                    iconAdditionalStyles={iconAdditionalStyles}
+                    titleStyles={titleStyles}
+                    promptStyles={promptStyles}
+                    shouldStackButtons={shouldStackButtons}
+                    shouldReverseStackedButtons={shouldReverseStackedButtons}
+                    image={image}
+                    imageStyles={imageStyles}
+                    isConfirmLoading={isConfirmLoading}
+                />
+            </View>
         </Modal>
     );
 }
diff --git a/src/components/ConfirmModal/focusRestore/index.ts b/src/components/ConfirmModal/focusRestore/index.ts
new file mode 100644
index 000000000000..b4e4bf15e0ff
--- /dev/null
+++ b/src/components/ConfirmModal/focusRestore/index.ts
@@ -0,0 +1,12 @@
+import type {FocusRestoreModule} from './types';
+
+const focusRestore: FocusRestoreModule = {
+    getInitialFocusTarget: () => false,
+    restoreCapturedAnchorFocus: () => {},
+    shouldTryKeyboardInitialFocus: () => false,
+    isWebPlatform: () => false,
+};
+
+const {getInitialFocusTarget, restoreCapturedAnchorFocus, shouldTryKeyboardInitialFocus, isWebPlatform} = focusRestore;
+
+export {getInitialFocusTarget, restoreCapturedAnchorFocus, shouldTryKeyboardInitialFocus, isWebPlatform};
diff --git a/src/components/ConfirmModal/focusRestore/index.web.ts b/src/components/ConfirmModal/focusRestore/index.web.ts
new file mode 100644
index 000000000000..ad7f4215b56d
--- /dev/null
+++ b/src/components/ConfirmModal/focusRestore/index.web.ts
@@ -0,0 +1,60 @@
+import Log from '@libs/Log';
+import CONST from '@src/CONST';
+import type {FocusRestoreModule, InitialFocusParams} from './types';
+
+const DIALOG_SELECTOR = '[role="dialog"]';
+const CONFIRM_MODAL_CONTAINER_SELECTOR = '[data-testid="confirm-modal-container"]';
+const FIRST_BUTTON_SELECTOR = 'button';
+
+function getHTMLElementFromUnknown(value: unknown): HTMLElement | null {
+    return value instanceof HTMLElement ? value : null;
+}
+
+function findFirstButtonInLastDialog(): HTMLElement | false {
+    const dialogs = document.querySelectorAll(DIALOG_SELECTOR);
+    const lastDialog = dialogs[dialogs.length - 1];
+    const firstButton = lastDialog?.querySelector(FIRST_BUTTON_SELECTOR);
+    return firstButton instanceof HTMLElement ? firstButton : false;
+}
+
+function findFirstButtonInLastConfirmModalContainer(): HTMLElement | false {
+    const containers = document.querySelectorAll(CONFIRM_MODAL_CONTAINER_SELECTOR);
+    const lastContainer = containers[containers.length - 1];
+    const firstButton = lastContainer?.querySelector(FIRST_BUTTON_SELECTOR);
+    return firstButton instanceof HTMLElement ? firstButton : false;
+}
+
+const focusRestore: FocusRestoreModule = {
+    getInitialFocusTarget: ({isOpenedViaKeyboard, containerElementRef}: InitialFocusParams) => {
+        if (!isOpenedViaKeyboard) {
+            return false;
+        }
+
+        const containerElement = getHTMLElementFromUnknown(containerElementRef);
+        if (!containerElement) {
+            const firstButtonInConfirmModal = findFirstButtonInLastConfirmModalContainer();
+            if (firstButtonInConfirmModal) {
+                return firstButtonInConfirmModal;
+            }
+
+            Log.warn('[ConfirmModal] modalContainerRef is null, falling back to last dialog');
+            return findFirstButtonInLastDialog();
+        }
+
+        const firstButton = containerElement.querySelector(FIRST_BUTTON_SELECTOR);
+        return firstButton instanceof HTMLElement ? firstButton : false;
+    },
+    restoreCapturedAnchorFocus: (capturedAnchorElement: HTMLElement | null): void => {
+        if (!capturedAnchorElement || !document.body.contains(capturedAnchorElement)) {
+            return;
+        }
+
+        capturedAnchorElement.focus();
+    },
+    shouldTryKeyboardInitialFocus: (isOpenedViaKeyboard: boolean): boolean => isOpenedViaKeyboard,
+    isWebPlatform: (platform: string): boolean => platform === CONST.PLATFORM.WEB,
+};
+
+const {getInitialFocusTarget, restoreCapturedAnchorFocus, shouldTryKeyboardInitialFocus, isWebPlatform} = focusRestore;
+
+export {getInitialFocusTarget, restoreCapturedAnchorFocus, shouldTryKeyboardInitialFocus, isWebPlatform};
diff --git a/src/components/ConfirmModal/focusRestore/types.ts b/src/components/ConfirmModal/focusRestore/types.ts
new file mode 100644
index 000000000000..d78d434254f4
--- /dev/null
+++ b/src/components/ConfirmModal/focusRestore/types.ts
@@ -0,0 +1,13 @@
+type InitialFocusParams = {
+    isOpenedViaKeyboard: boolean;
+    containerElementRef: unknown;
+};
+
+type FocusRestoreModule = {
+    getInitialFocusTarget: (params: InitialFocusParams) => HTMLElement | false;
+    restoreCapturedAnchorFocus: (capturedAnchorElement: HTMLElement | null) => void;
+    shouldTryKeyboardInitialFocus: (isOpenedViaKeyboard: boolean) => boolean;
+    isWebPlatform: (platform: string) => boolean;
+};
+
+export type {FocusRestoreModule, InitialFocusParams};
diff --git a/src/components/FocusTrap/FocusTrapForScreen/index.web.tsx b/src/components/FocusTrap/FocusTrapForScreen/index.web.tsx
index 595aae904b74..1cf7ab8acbd3 100644
--- a/src/components/FocusTrap/FocusTrapForScreen/index.web.tsx
+++ b/src/components/FocusTrap/FocusTrapForScreen/index.web.tsx
@@ -1,18 +1,67 @@
-import {useIsFocused, useRoute} from '@react-navigation/native';
+import {useIsFocused, useNavigation, useRoute} from '@react-navigation/native';
 import {FocusTrap} from 'focus-trap-react';
-import React, {useMemo} from 'react';
+import React, {useEffect, useLayoutEffect, useMemo, useRef} from 'react';
+import {View} from 'react-native';
 import sharedTrapStack from '@components/FocusTrap/sharedTrapStack';
 import TOP_TAB_SCREENS from '@components/FocusTrap/TOP_TAB_SCREENS';
 import WIDE_LAYOUT_INACTIVE_SCREENS from '@components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import FocusUtils from '@libs/focusUtils';
 import {isSidebarScreenName} from '@libs/Navigation/helpers/isNavigatorName';
+import NavigationFocusManager from '@libs/NavigationFocusManager';
+import {NAVIGATION_FOCUS_ROUTE_DATASET_KEY} from '@libs/NavigationFocusManager/constants';
 import CONST from '@src/CONST';
 import type FocusTrapProps from './FocusTrapProps';
 
 function FocusTrapForScreen({children, focusTrapSettings}: FocusTrapProps) {
     const isFocused = useIsFocused();
     const route = useRoute();
+    const navigation = useNavigation();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
+    // route.key is required by React Navigation type contracts, but we still guard malformed test mocks.
+    const routeKey = typeof route.key === 'string' && route.key.length > 0 ? route.key : undefined;
+
+    // Track previous focus state to detect transitions
+    const prevIsFocused = useRef(isFocused);
+
+    // Track if this screen was navigated to (vs initial page load)
+    // This prevents focus restoration on initial page load (Issue #46109)
+    const wasNavigatedTo = useRef(false);
+    const shouldRestoreFocusWithoutTrap = useRef(false);
+
+    // Unregister focused route on unmount
+    useEffect(() => {
+        return () => {
+            if (!routeKey) {
+                return;
+            }
+            NavigationFocusManager.unregisterFocusedRoute(routeKey);
+        };
+    }, [routeKey]);
+
+    // Register/unregister focused route for immediate capture
+    useEffect(() => {
+        if (!routeKey) {
+            return;
+        }
+        if (isFocused) {
+            NavigationFocusManager.registerFocusedRoute(routeKey);
+        } else {
+            NavigationFocusManager.unregisterFocusedRoute(routeKey);
+        }
+    }, [isFocused, routeKey]);
+
+    // Capture focus before screen is removed from navigation stack
+    // This handles back navigation where screen may unmount before useLayoutEffect runs
+    useEffect(() => {
+        if (!routeKey) {
+            return;
+        }
+        const unsubscribe = navigation.addListener('beforeRemove', () => {
+            NavigationFocusManager.captureForRoute(routeKey);
+        });
+        return unsubscribe;
+    }, [navigation, routeKey]);
 
     const isActive = useMemo(() => {
         if (typeof focusTrapSettings?.active !== 'undefined') {
@@ -23,7 +72,7 @@ function FocusTrapForScreen({children, focusTrapSettings}: FocusTrapProps) {
             return false;
         }
 
-        // in top tabs only focus trap for currently shown tab should be active
+        // In top tabs only focus trap for currently shown tab should be active
         if (TOP_TAB_SCREENS.find((screen) => screen === route.name)) {
             return isFocused;
         }
@@ -35,6 +84,72 @@ function FocusTrapForScreen({children, focusTrapSettings}: FocusTrapProps) {
         return isFocused;
     }, [isFocused, shouldUseNarrowLayout, route.name, focusTrapSettings?.active]);
 
+    const routeBoundaryDataSet = useMemo(
+        () =>
+            routeKey
+                ? {
+                      [NAVIGATION_FOCUS_ROUTE_DATASET_KEY]: routeKey,
+                  }
+                : undefined,
+        [routeKey],
+    );
+
+    // Capture focus transitions synchronously.
+    // Keep this effect minimal to avoid doing deferred restore work in layout phase.
+    useLayoutEffect(() => {
+        if (!routeKey) {
+            prevIsFocused.current = isFocused;
+            shouldRestoreFocusWithoutTrap.current = false;
+            return;
+        }
+
+        const wasFocused = prevIsFocused.current;
+        const isNowFocused = isFocused;
+        const hasStored = NavigationFocusManager.hasStoredFocus(routeKey);
+
+        // Detect returning to screen: either normal transition or fresh mount with stored focus
+        // Fresh mount case: non-persistent screens remount with isFocused=true, so prevIsFocused
+        // initializes to true. We use hasStoredFocus to detect this is a "return" not initial load.
+        const isTransitionToFocused = !wasFocused && isNowFocused;
+        const isFreshMountReturning = wasFocused && isNowFocused && hasStored;
+        const isReturningToScreen = isTransitionToFocused || isFreshMountReturning;
+
+        if (wasFocused && !isNowFocused) {
+            // Screen is losing focus (forward navigation) - capture the focused element
+            NavigationFocusManager.captureForRoute(routeKey);
+        }
+
+        if (isReturningToScreen && hasStored) {
+            if (!isActive) {
+                shouldRestoreFocusWithoutTrap.current = true;
+            } else {
+                // For active traps, let initialFocus handle it
+                wasNavigatedTo.current = true;
+                shouldRestoreFocusWithoutTrap.current = false;
+            }
+        } else {
+            shouldRestoreFocusWithoutTrap.current = false;
+        }
+
+        prevIsFocused.current = isFocused;
+    }, [isFocused, routeKey, isActive]);
+
+    useEffect(() => {
+        if (!routeKey || !isFocused || isActive || !shouldRestoreFocusWithoutTrap.current) {
+            return;
+        }
+
+        shouldRestoreFocusWithoutTrap.current = false;
+        const capturedElement = NavigationFocusManager.retrieveForRoute(routeKey);
+        if (!capturedElement || !FocusUtils.isElementFocusRestorable(capturedElement)) {
+            return;
+        }
+
+        requestAnimationFrame(() => {
+            capturedElement.focus();
+        });
+    }, [isActive, isFocused, routeKey]);
+
     return (
         <FocusTrap
             active={isActive}
@@ -42,11 +157,11 @@ function FocusTrapForScreen({children, focusTrapSettings}: FocusTrapProps) {
             containerElements={focusTrapSettings?.containerElements?.length ? focusTrapSettings.containerElements : undefined}
             focusTrapOptions={{
                 onActivate: () => {
+                    // Blur non-input elements to prevent visual artifacts
                     const activeElement = document?.activeElement as HTMLElement;
-                    if (activeElement?.nodeName === CONST.ELEMENT_NAME.INPUT || activeElement?.nodeName === CONST.ELEMENT_NAME.TEXTAREA) {
-                        return;
+                    if (activeElement?.nodeName !== CONST.ELEMENT_NAME.INPUT && activeElement?.nodeName !== CONST.ELEMENT_NAME.TEXTAREA) {
+                        activeElement?.blur();
                     }
-                    activeElement?.blur();
                 },
                 trapStack: sharedTrapStack,
                 allowOutsideClick: true,
@@ -54,12 +169,55 @@ function FocusTrapForScreen({children, focusTrapSettings}: FocusTrapProps) {
                 clickOutsideDeactivates: true,
                 fallbackFocus: document.body,
                 delayInitialFocus: CONST.ANIMATED_TRANSITION,
-                initialFocus: false,
-                setReturnFocus: false,
+
+                // initialFocus is called when the trap ACTIVATES (returning to a screen)
+                // This is the correct place to restore focus, NOT setReturnFocus
+                initialFocus: () => {
+                    // Don't restore focus on initial page load (Issue #46109)
+                    if (!wasNavigatedTo.current) {
+                        return false;
+                    }
+
+                    // Reset the flag
+                    wasNavigatedTo.current = false;
+
+                    if (!routeKey) {
+                        return false;
+                    }
+
+                    // Retrieve the element captured when we left this screen
+                    const capturedElement = NavigationFocusManager.retrieveForRoute(routeKey);
+
+                    // Use captured element if it's still focusable
+                    if (capturedElement && FocusUtils.isElementFocusRestorable(capturedElement)) {
+                        return capturedElement;
+                    }
+
+                    // Don't focus anything if no valid element
+                    return false;
+                },
+
+                // setReturnFocus handles non-navigation deactivation (e.g., click outside)
+                // It should NOT handle navigation focus restoration
+                setReturnFocus: (triggerElement) => {
+                    // For click-outside deactivation, return to trigger element if focusable
+                    if (FocusUtils.isElementFocusRestorable(triggerElement)) {
+                        return triggerElement;
+                    }
+                    return false;
+                },
+
                 ...(focusTrapSettings?.focusTrapOptions ?? {}),
             }}
         >
-            {children}
+            <View
+                // Keep the route marker inside the web-only FocusTrap path so
+                // shared containers do not need a dedicated forwarding prop.
+                style={{flex: 1}}
+                dataSet={routeBoundaryDataSet}
+            >
+                {children}
+            </View>
         </FocusTrap>
     );
 }
diff --git a/src/components/FocusTrap/__mocks__/TOP_TAB_SCREENS.ts b/src/components/FocusTrap/__mocks__/TOP_TAB_SCREENS.ts
new file mode 100644
index 000000000000..49cfc133f6b7
--- /dev/null
+++ b/src/components/FocusTrap/__mocks__/TOP_TAB_SCREENS.ts
@@ -0,0 +1,7 @@
+/**
+ * Mock for TOP_TAB_SCREENS used in tests.
+ * These are screen names where focus trap activation depends on isFocused state.
+ */
+const TOP_TAB_SCREENS: string[] = ['NewChat', 'NewRoom'];
+
+export default TOP_TAB_SCREENS;
diff --git a/src/components/FocusTrap/__mocks__/WIDE_LAYOUT_INACTIVE_SCREENS.ts b/src/components/FocusTrap/__mocks__/WIDE_LAYOUT_INACTIVE_SCREENS.ts
new file mode 100644
index 000000000000..e07533437938
--- /dev/null
+++ b/src/components/FocusTrap/__mocks__/WIDE_LAYOUT_INACTIVE_SCREENS.ts
@@ -0,0 +1,7 @@
+/**
+ * Mock for WIDE_LAYOUT_INACTIVE_SCREENS used in tests.
+ * These are screens where focus trap should be inactive in wide layout mode.
+ */
+const WIDE_LAYOUT_INACTIVE_SCREENS: string[] = ['Home', 'Report'];
+
+export default WIDE_LAYOUT_INACTIVE_SCREENS;
diff --git a/src/components/FocusTrap/__mocks__/sharedTrapStack.ts b/src/components/FocusTrap/__mocks__/sharedTrapStack.ts
new file mode 100644
index 000000000000..ba7ba454567c
--- /dev/null
+++ b/src/components/FocusTrap/__mocks__/sharedTrapStack.ts
@@ -0,0 +1,8 @@
+/**
+ * Mock for sharedTrapStack used in tests.
+ * The shared trap stack is used by focus-trap-react to coordinate multiple focus traps.
+ * In tests, we use an empty array as there's no actual focus trap coordination needed.
+ */
+const sharedTrapStack: Element[] = [];
+
+export default sharedTrapStack;
diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx
index b4d71df7d8e1..19a3003dec28 100644
--- a/src/components/MenuItem.tsx
+++ b/src/components/MenuItem.tsx
@@ -633,7 +633,10 @@ function MenuItem({
         if (!title || !shouldParseTitle) {
             return '';
         }
-        return Parser.replace(title, {shouldEscapeText, disabledRules: excludedMarkdownRules});
+        return Parser.replace(title, {
+            shouldEscapeText,
+            disabledRules: excludedMarkdownRules,
+        });
     }, [title, shouldParseTitle, shouldEscapeText, excludedMarkdownRules]);
 
     const helperHtml = useMemo(() => {
@@ -744,6 +747,20 @@ function MenuItem({
         enhancedAccessibilityLabel = `${enhancedAccessibilityLabel}. ${translate('common.opensInNewTab')}`;
     }
 
+    // When interactive={false}, don't pass onPress to allow events to bubble to parent wrapper.
+    // This is critical for components like ApprovalWorkflowSection where outer PressableWithoutFeedback
+    // handles all clicks and inner MenuItems are display-only.
+    const getResolvedOnPress = () => {
+        if (!interactive) {
+            return undefined;
+        }
+        if (shouldCheckActionAllowedOnPress) {
+            return callFunctionIfActionIsAllowed(onPressAction, isAnonymousAction);
+        }
+        return onPressAction;
+    };
+    const resolvedOnPress = getResolvedOnPress();
+
     return (
         <View
             style={rootWrapperStyle}
@@ -769,7 +786,7 @@ function MenuItem({
                     <Hoverable isFocused={isFocused}>
                         {(isHovered) => (
                             <PressableWithSecondaryInteraction
-                                onPress={shouldCheckActionAllowedOnPress ? callFunctionIfActionIsAllowed(onPressAction, isAnonymousAction) : onPressAction}
+                                onPress={resolvedOnPress}
                                 onPressIn={() => shouldBlockSelection && shouldUseNarrowLayout && canUseTouchScreen() && ControlSelection.block()}
                                 onPressOut={ControlSelection.unblock}
                                 onSecondaryInteraction={copyable && !deviceHasHoverSupport ? secondaryInteraction : onSecondaryInteraction}
@@ -946,7 +963,9 @@ function MenuItem({
                                                                     <Text
                                                                         style={combinedTitleTextStyle}
                                                                         numberOfLines={numberOfLinesTitle || undefined}
-                                                                        dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: interactive && disabled}}
+                                                                        dataSet={{
+                                                                            [CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: interactive && disabled,
+                                                                        }}
                                                                         accessibilityRole={titleAccessibilityRole}
                                                                     >
                                                                         {renderTitleContent()}
diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx
index feb75bfef566..60b2ca283144 100644
--- a/src/components/MoneyRequestConfirmationList.tsx
+++ b/src/components/MoneyRequestConfirmationList.tsx
@@ -15,7 +15,7 @@ import usePolicyForTransaction from '@hooks/usePolicyForTransaction';
 import usePreferredPolicy from '@hooks/usePreferredPolicy';
 import usePrevious from '@hooks/usePrevious';
 import useThemeStyles from '@hooks/useThemeStyles';
-import blurActiveElement from '@libs/Accessibility/blurActiveElement';
+import blurActiveInputElement from '@libs/Accessibility/blurActiveInputElement';
 import {
     setCustomUnitRateID,
     setMoneyRequestAmount,
@@ -1154,7 +1154,9 @@ function MoneyRequestConfirmationList({
             focusTimeoutRef.current = setTimeout(() => {
                 // eslint-disable-next-line @typescript-eslint/no-deprecated
                 InteractionManager.runAfterInteractions(() => {
-                    blurActiveElement();
+                    // Only blur input elements to dismiss keyboard.
+                    // Don't blur other elements to preserve focus restoration on back navigation.
+                    blurActiveInputElement();
                 });
             }, CONST.ANIMATED_TRANSITION);
             return () => focusTimeoutRef.current && clearTimeout(focusTimeoutRef.current);
diff --git a/src/components/PopoverMenu.tsx b/src/components/PopoverMenu.tsx
index fb835b55f4bb..e9b15269cd0c 100644
--- a/src/components/PopoverMenu.tsx
+++ b/src/components/PopoverMenu.tsx
@@ -1,7 +1,7 @@
 /* eslint-disable react/jsx-props-no-spreading */
 import {deepEqual} from 'fast-equals';
 import type {ReactNode, RefObject} from 'react';
-import React, {useCallback, useLayoutEffect, useMemo, useState} from 'react';
+import React, {useCallback, useLayoutEffect, useMemo, useRef, useState} from 'react';
 import {StyleSheet, View} from 'react-native';
 import type {GestureResponderEvent, LayoutChangeEvent, StyleProp, TextStyle, ViewStyle} from 'react-native';
 import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager';
@@ -15,6 +15,7 @@ import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {isSafari} from '@libs/Browser';
 import getPlatform from '@libs/getPlatform';
+import Log from '@libs/Log';
 import variables from '@styles/variables';
 import {close} from '@userActions/Modal';
 import CONST from '@src/CONST';
@@ -29,6 +30,7 @@ import MenuItem from './MenuItem';
 import type ReanimatedModalProps from './Modal/ReanimatedModal/types';
 import type BaseModalProps from './Modal/types';
 import OfflineWithFeedback from './OfflineWithFeedback';
+import {buildKeyPathFromIndexPath, getInitialFocusTargetFromContainer, resolveIndexPathByKeyPath} from './PopoverMenuUtils';
 import PopoverWithMeasuredContent from './PopoverWithMeasuredContent';
 import ScrollView from './ScrollView';
 import Text from './Text';
@@ -88,6 +90,13 @@ type PopoverMenuItem = MenuItemProps & {
 type ModalAnimationProps = Pick<ReanimatedModalProps, 'animationInDelay' | 'animationIn' | 'animationInTiming' | 'animationOut' | 'animationOutTiming'>;
 
 type PopoverMenuProps = Partial<ModalAnimationProps> & {
+    /**
+     * Whether the menu was opened via keyboard (for auto-focus on first item).
+     * Consumers must capture this state BEFORE opening the menu using:
+     *   NavigationFocusManager.wasRecentKeyboardInteraction()
+     */
+    wasOpenedViaKeyboard?: boolean;
+
     /** Callback method fired when the user requests to close the modal */
     onClose: () => void;
 
@@ -196,60 +205,8 @@ function getSelectedItemIndex(menuItems: PopoverMenuItem[]) {
     return menuItems.findIndex((option) => option.isSelected);
 }
 
-/**
- * Return a stable string key for a menu item.
- * Prefers explicit `key` property on the item. If missing, falls back to `text`.
- *
- * IMPORTANT: the key must be stable and unique across the whole menu tree for the
- * path-resolution algorithm to work reliably when menu arrays change.
- */
-const getItemKey = (item: PopoverMenuItem) => item.key ?? item.text;
-
-/**
- * Build a key-path (array of keys) by walking the `root` using `indexPath`.
- *
- * The `indexPath` is an array of indexes which represent the path previously
- * selected by the user (e.g. [1, 2] means: at root index 1, then its subMenuItems index 2).
- *
- * We iterate down the `root` following `indexPath` and collect getItemKey(node)
- * for each visited node. If any index is out-of-bounds for a level, we stop
- * and return the keys collected so far (could be empty).
- */
-function buildKeyPathFromIndexPath(root: PopoverMenuItem[], indexPath: readonly number[]): string[] {
-    const keys: string[] = [];
-    let level: PopoverMenuItem[] | undefined = root;
-
-    for (const idx of indexPath) {
-        const node: PopoverMenuItem | undefined = level?.[idx];
-        if (!node) {
-            break;
-        }
-        keys.push(getItemKey(node));
-        level = node.subMenuItems;
-    }
-    return keys;
-}
-
-/**
- * Try to resolve a key-path against the current `root` and return the corresponding index-path
- * and the `itemsAtLeaf` (the subMenuItems array of the final matched node, or an empty array).
- *
- * Returns `{found: false}` if any key in keyPath cannot be found at the expected level.
- */
-function resolveIndexPathByKeyPath(root: PopoverMenuItem[], keyPath: string[]) {
-    let level: PopoverMenuItem[] = root;
-    const indexes: number[] = [];
-
-    for (const key of keyPath) {
-        const i = level.findIndex((n) => getItemKey(n) === key);
-        if (i === -1) {
-            return {found: false as const};
-        }
-        indexes.push(i);
-        const next = level.at(i)?.subMenuItems;
-        level = next ?? [];
-    }
-    return {found: true as const, indexes, itemsAtLeaf: level};
+function getMenuContainerElement(containerRefValue: unknown): HTMLElement | null {
+    return containerRefValue instanceof HTMLElement ? containerRefValue : null;
 }
 
 function PopoverMenu(props: PopoverMenuProps) {
@@ -273,6 +230,7 @@ function BasePopoverMenu({
     onModalHide,
     headerText,
     fromSidebarMediumScreen,
+    wasOpenedViaKeyboard,
     shouldHandleNavigationBack,
     anchorAlignment = {
         horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT,
@@ -318,6 +276,37 @@ function BasePopoverMenu({
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['BackArrow', 'ReceiptScan', 'MoneyCircle']);
     const prevMenuItems = usePrevious(menuItems);
 
+    // Ref for scoping DOM queries to this menu's container
+    // CRITICAL: Prevents finding menuitems from other modals in nested scenarios
+    const menuContainerRef = useRef<View>(null);
+
+    /**
+     * Compute initialFocus for FocusTrapForModal.
+     * Returns a function that finds the first menuitem when trap activates.
+     * Returns false for mouse opens (no auto-focus) or non-web platforms.
+     */
+    const computeInitialFocus = (() => {
+        // Skip for mouse/touch opens or non-web platforms
+        if (!wasOpenedViaKeyboard || !isWeb) {
+            return false;
+        }
+
+        // Return function that will be called when FocusTrap activates
+        // At activation time, content is already rendered in the DOM
+        return () => {
+            // CRITICAL: Scope query to this menu's container
+            // This prevents focusing menuitems from OTHER open modals
+            // in nested scenarios (e.g., ThreeDotsMenu → PopoverMenu → ConfirmModal)
+            const container = getMenuContainerElement(menuContainerRef.current);
+            if (!container) {
+                Log.warn('[PopoverMenu] menuContainerRef is null during initialFocus');
+                return false;
+            }
+
+            return getInitialFocusTargetFromContainer(container);
+        };
+    })();
+
     const selectItem = (index: number, event?: GestureResponderEvent | KeyboardEvent) => {
         const selectedItem = currentMenuItems.at(index);
         if (!selectedItem) {
@@ -618,11 +607,14 @@ function BasePopoverMenu({
         >
             <FocusTrapForModal
                 active={isVisible}
+                initialFocus={computeInitialFocus}
                 shouldReturnFocus={!shouldEnableNewFocusManagement}
             >
                 <View
+                    ref={menuContainerRef}
                     onLayout={onLayout}
                     style={[restMenuContainerStyle, restContainerStyles, isWeb ? styles.flex1 : styles.flexGrow1]}
+                    testID="popover-menu-container"
                 >
                     {renderWithConditionalWrapper(
                         shouldUseScrollView,
@@ -654,8 +646,8 @@ export default React.memo(
         prevProps.animationOut === nextProps.animationOut &&
         prevProps.animationInTiming === nextProps.animationInTiming &&
         prevProps.disableAnimation === nextProps.disableAnimation &&
+        prevProps.wasOpenedViaKeyboard === nextProps.wasOpenedViaKeyboard &&
         prevProps.withoutOverlay === nextProps.withoutOverlay &&
         prevProps.shouldSetModalVisibility === nextProps.shouldSetModalVisibility,
 );
 export type {PopoverMenuItem, PopoverMenuProps};
-export {getItemKey, buildKeyPathFromIndexPath, resolveIndexPathByKeyPath};
diff --git a/src/components/PopoverMenuUtils.ts b/src/components/PopoverMenuUtils.ts
new file mode 100644
index 000000000000..f28192dd4aaa
--- /dev/null
+++ b/src/components/PopoverMenuUtils.ts
@@ -0,0 +1,61 @@
+import FocusUtils from '@libs/focusUtils';
+
+type PopoverMenuTreeItem = {
+    text: string;
+    key?: string;
+    subMenuItems?: PopoverMenuTreeItem[];
+};
+
+function getInitialFocusTargetFromContainer(container: HTMLElement): HTMLElement | false {
+    const candidates = container.querySelectorAll('[role="button"], [role="menuitem"]');
+    for (const candidate of candidates) {
+        if (FocusUtils.isFocusableActionableElement(candidate)) {
+            return candidate;
+        }
+    }
+    return false;
+}
+
+function getItemKey(item: Pick<PopoverMenuTreeItem, 'key' | 'text'>): string {
+    return item.key ?? item.text;
+}
+
+function getItemAtIndex(items: PopoverMenuTreeItem[] | undefined, index: number): PopoverMenuTreeItem | undefined {
+    return items?.find((_item, itemIndex) => itemIndex === index);
+}
+
+function buildKeyPathFromIndexPath(root: PopoverMenuTreeItem[], indexPath: readonly number[]): string[] {
+    const keys: string[] = [];
+    let level: PopoverMenuTreeItem[] | undefined = root;
+
+    for (const idx of indexPath) {
+        const node = getItemAtIndex(level, idx);
+        if (!node) {
+            break;
+        }
+        keys.push(getItemKey(node));
+        level = node.subMenuItems;
+    }
+
+    return keys;
+}
+
+function resolveIndexPathByKeyPath(root: PopoverMenuTreeItem[], keyPath: string[]) {
+    let level: PopoverMenuTreeItem[] = root;
+    const indexes: number[] = [];
+
+    for (const key of keyPath) {
+        const index = level.findIndex((node) => getItemKey(node) === key);
+        if (index === -1) {
+            return {found: false as const};
+        }
+
+        indexes.push(index);
+        const selectedItem = getItemAtIndex(level, index);
+        level = selectedItem?.subMenuItems ?? [];
+    }
+
+    return {found: true as const, indexes, itemsAtLeaf: level};
+}
+
+export {buildKeyPathFromIndexPath, getInitialFocusTargetFromContainer, getItemKey, resolveIndexPathByKeyPath};
diff --git a/src/components/ScreenWrapper/ScreenWrapperContainer.tsx b/src/components/ScreenWrapper/ScreenWrapperContainer.tsx
index 4daecfda89f3..a2dc736594d2 100644
--- a/src/components/ScreenWrapper/ScreenWrapperContainer.tsx
+++ b/src/components/ScreenWrapper/ScreenWrapperContainer.tsx
@@ -1,5 +1,5 @@
 import type {ForwardedRef, ReactNode} from 'react';
-import React, {useContext, useEffect, useMemo, useRef} from 'react';
+import React, {useContext, useEffect, useMemo} from 'react';
 import type {StyleProp, ViewStyle} from 'react-native';
 import {Keyboard, PanResponder, View} from 'react-native';
 import {PickerAvoidingView} from 'react-native-picker-select';
@@ -167,24 +167,28 @@ function ScreenWrapperContainer({
         [isUsingEdgeToEdgeMode, edgeToEdgeBottomContentStyle, legacyBottomContentStyle, bottomContentStyleProp],
     );
 
-    const panResponder = useRef(
-        PanResponder.create({
-            onStartShouldSetPanResponderCapture: (_e, gestureState) => gestureState.numberActiveTouches === CONST.TEST_TOOL.NUMBER_OF_TAPS,
-            onPanResponderRelease: toggleTestToolsModal,
-        }),
-    ).current;
-
-    const keyboardDismissPanResponder = useRef(
-        PanResponder.create({
-            onMoveShouldSetPanResponderCapture: (_e, gestureState) => {
-                const isHorizontalSwipe = Math.abs(gestureState.dx) > Math.abs(gestureState.dy);
-                const shouldDismissKeyboard = shouldDismissKeyboardBeforeClose && Keyboard.isVisible() && isMobile();
-
-                return isHorizontalSwipe && shouldDismissKeyboard;
-            },
-            onPanResponderGrant: Keyboard.dismiss,
-        }),
-    ).current;
+    const panResponder = useMemo(
+        () =>
+            PanResponder.create({
+                onStartShouldSetPanResponderCapture: (_e, gestureState) => gestureState.numberActiveTouches === CONST.TEST_TOOL.NUMBER_OF_TAPS,
+                onPanResponderRelease: toggleTestToolsModal,
+            }),
+        [],
+    );
+
+    const keyboardDismissPanResponder = useMemo(
+        () =>
+            PanResponder.create({
+                onMoveShouldSetPanResponderCapture: (_e, gestureState) => {
+                    const isHorizontalSwipe = Math.abs(gestureState.dx) > Math.abs(gestureState.dy);
+                    const shouldDismissKeyboard = shouldDismissKeyboardBeforeClose && Keyboard.isVisible() && isMobile();
+
+                    return isHorizontalSwipe && shouldDismissKeyboard;
+                },
+                onPanResponderGrant: Keyboard.dismiss,
+            }),
+        [shouldDismissKeyboardBeforeClose],
+    );
 
     useEffect(() => {
         /**
diff --git a/src/components/ThreeDotsMenu/index.tsx b/src/components/ThreeDotsMenu/index.tsx
index 774b22bec18b..f3914370a1c3 100644
--- a/src/components/ThreeDotsMenu/index.tsx
+++ b/src/components/ThreeDotsMenu/index.tsx
@@ -16,6 +16,7 @@ import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useWindowDimensions from '@hooks/useWindowDimensions';
 import {isMobile} from '@libs/Browser';
+import NavigationFocusManager from '@libs/NavigationFocusManager';
 import type {AnchorPosition} from '@styles/index';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
@@ -55,6 +56,7 @@ function ThreeDotsMenu({
     const [restoreFocusType, setRestoreFocusType] = useState<BaseModalProps['restoreFocusType']>();
     const [position, setPosition] = useState<AnchorPosition>();
     const buttonRef = useRef<View>(null);
+    const wasOpenedViaKeyboardRef = useRef(false);
     const {translate} = useLocalize();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['ThreeDots']);
     const isBehindModal = modal?.willAlertModalBecomeVisible && !modal?.isPopover && !shouldOverlay;
@@ -68,6 +70,7 @@ function ThreeDotsMenu({
             return;
         }
         setPopupMenuVisible(false);
+        wasOpenedViaKeyboardRef.current = false;
     }, []);
 
     const {calculatePopoverPosition} = usePopoverPosition();
@@ -84,6 +87,13 @@ function ThreeDotsMenu({
         hideProductTrainingTooltip?.();
         buttonRef.current?.blur();
 
+        // Capture keyboard state BEFORE menu opens
+        // NavigationFocusManager sets flag on Enter/Space keydown (capture phase)
+        wasOpenedViaKeyboardRef.current = NavigationFocusManager.wasRecentKeyboardInteraction();
+        if (wasOpenedViaKeyboardRef.current) {
+            NavigationFocusManager.clearKeyboardInteractionFlag();
+        }
+
         if (getMenuPosition) {
             getMenuPosition?.().then((value) => {
                 setPosition(value);
@@ -142,6 +152,18 @@ function ThreeDotsMenu({
                     <PressableWithoutFeedback
                         onPress={onThreeDotsPress}
                         disabled={disabled}
+                        onKeyDown={(e: React.KeyboardEvent) => {
+                            // When nested inside another pressable (e.g., workspace row), keyboard activation
+                            // propagates to the parent due to role="presentation". We intercept Enter/Space
+                            // to open the menu directly. Double activation is prevented by blur() in
+                            // onThreeDotsPress() which moves focus away before RNW's keyup handler fires.
+                            if (!isNested || (e.key !== 'Enter' && e.key !== ' ')) {
+                                return;
+                            }
+                            e.stopPropagation();
+                            e.preventDefault();
+                            onThreeDotsPress();
+                        }}
                         onMouseDown={(e) => {
                             /* Keep the focus state on mWeb like we did on the native apps. */
                             if (!isMobile()) {
@@ -179,6 +201,7 @@ function ThreeDotsMenu({
                 anchorRef={buttonRef}
                 shouldEnableNewFocusManagement
                 restoreFocusType={restoreFocusType}
+                wasOpenedViaKeyboard={wasOpenedViaKeyboardRef.current}
             />
         </>
     );
diff --git a/src/hooks/useAutoFocusInput.ts b/src/hooks/useAutoFocusInput.ts
index c7b3d471279a..6d412dd01df4 100644
--- a/src/hooks/useAutoFocusInput.ts
+++ b/src/hooks/useAutoFocusInput.ts
@@ -19,6 +19,19 @@ type UseAutoFocusInput = {
     inputRef: RefObject<TextInput | null>;
 };
 
+function shouldPreserveExistingFocus(target: TextInput | null): boolean {
+    if (typeof document === 'undefined') {
+        return false;
+    }
+
+    const activeElement = document.activeElement;
+    if (!activeElement || activeElement === document.body || activeElement === document.documentElement) {
+        return false;
+    }
+
+    return !target?.isFocused?.();
+}
+
 export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInput {
     const [isInputInitialized, setIsInputInitialized] = useState(false);
     const [isScreenTransitionEnded, setIsScreenTransitionEnded] = useState(false);
@@ -45,10 +58,21 @@ export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInpu
         }
         // eslint-disable-next-line @typescript-eslint/no-deprecated
         const focusTaskHandle = InteractionManager.runAfterInteractions(() => {
-            if (inputRef.current && isMultiline) {
-                moveSelectionToEnd(inputRef.current);
+            const currentInput = inputRef.current;
+            if (shouldPreserveExistingFocus(currentInput)) {
+                setIsScreenTransitionEnded(false);
+                return;
+            }
+
+            if (currentInput && isMultiline) {
+                moveSelectionToEnd(currentInput);
             }
-            isWindowReadyToFocus().then(() => inputRef.current?.focus());
+            isWindowReadyToFocus().then(() => {
+                if (shouldPreserveExistingFocus(inputRef.current)) {
+                    return;
+                }
+                inputRef.current?.focus();
+            });
             setIsScreenTransitionEnded(false);
         });
 
diff --git a/src/hooks/useSyncFocus/useSyncFocusImplementation.ts b/src/hooks/useSyncFocus/useSyncFocusImplementation.ts
index df6bfe6fadb8..3cb82543c686 100644
--- a/src/hooks/useSyncFocus/useSyncFocusImplementation.ts
+++ b/src/hooks/useSyncFocus/useSyncFocusImplementation.ts
@@ -30,6 +30,13 @@ const useSyncFocusImplementation = (ref: RefObject<View | HTMLElement | null>, i
             return;
         }
 
+        // Don't steal focus from already-focused interactive elements
+        // This preserves focus restoration from NavigationFocusManager
+        const activeElement = document.activeElement;
+        if (activeElement && activeElement !== document.body && activeElement !== document.documentElement && activeElement !== ref.current) {
+            return;
+        }
+
         ref.current?.focus({preventScroll: true});
         // eslint-disable-next-line react-hooks/exhaustive-deps
     }, [didScreenTransitionEnd, isFocused, ref]);
diff --git a/src/libs/Accessibility/blurActiveInputElement/index.native.ts b/src/libs/Accessibility/blurActiveInputElement/index.native.ts
new file mode 100644
index 000000000000..8cc5009631bc
--- /dev/null
+++ b/src/libs/Accessibility/blurActiveInputElement/index.native.ts
@@ -0,0 +1,5 @@
+import type BlurActiveInputElement from './types';
+
+const blurActiveInputElement: BlurActiveInputElement = () => {};
+
+export default blurActiveInputElement;
diff --git a/src/libs/Accessibility/blurActiveInputElement/index.ts b/src/libs/Accessibility/blurActiveInputElement/index.ts
new file mode 100644
index 000000000000..6c12af631a03
--- /dev/null
+++ b/src/libs/Accessibility/blurActiveInputElement/index.ts
@@ -0,0 +1,19 @@
+import blurActiveElement from '@libs/Accessibility/blurActiveElement';
+import CONST from '@src/CONST';
+import type BlurActiveInputElement from './types';
+
+const blurActiveInputElement: BlurActiveInputElement = () => {
+    const activeElement = document.activeElement;
+
+    if (!(activeElement instanceof HTMLElement)) {
+        return;
+    }
+
+    if (activeElement.tagName !== CONST.ELEMENT_NAME.INPUT && activeElement.tagName !== CONST.ELEMENT_NAME.TEXTAREA) {
+        return;
+    }
+
+    blurActiveElement();
+};
+
+export default blurActiveInputElement;
diff --git a/src/libs/Accessibility/blurActiveInputElement/types.ts b/src/libs/Accessibility/blurActiveInputElement/types.ts
new file mode 100644
index 000000000000..32722165c560
--- /dev/null
+++ b/src/libs/Accessibility/blurActiveInputElement/types.ts
@@ -0,0 +1,3 @@
+type BlurActiveInputElement = () => void;
+
+export default BlurActiveInputElement;
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 2844878af164..1086a576483c 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -12,6 +12,7 @@ import useTheme from '@hooks/useTheme';
 import useThemePreference from '@hooks/useThemePreference';
 import FS from '@libs/Fullstory';
 import Log from '@libs/Log';
+import NavigationFocusManager from '@libs/NavigationFocusManager';
 import shouldOpenLastVisitedPath from '@libs/shouldOpenLastVisitedPath';
 import {getPathFromURL} from '@libs/Url';
 import {updateLastVisitedPath} from '@userActions/App';
@@ -240,6 +241,7 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady}: N
         // We want to clean saved scroll offsets for screens that aren't anymore in the state.
         cleanStaleScrollOffsets(state);
         cleanPreservedNavigatorStates(state);
+        NavigationFocusManager.cleanupRemovedRoutes(state);
     };
 
     const onReadyWithSentry = useCallback(() => {
diff --git a/src/libs/NavigationFocusManager/constants.ts b/src/libs/NavigationFocusManager/constants.ts
new file mode 100644
index 000000000000..c1c2ed079beb
--- /dev/null
+++ b/src/libs/NavigationFocusManager/constants.ts
@@ -0,0 +1,5 @@
+const NAVIGATION_FOCUS_ROUTE_DATASET_KEY = 'navigationFocusRouteKey' as const;
+const NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE = 'data-navigation-focus-route-key' as const;
+const NAVIGATION_FOCUS_ROUTE_SELECTOR = `[${NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE}]` as const;
+
+export {NAVIGATION_FOCUS_ROUTE_DATASET_KEY, NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE, NAVIGATION_FOCUS_ROUTE_SELECTOR};
diff --git a/src/libs/NavigationFocusManager/index.ts b/src/libs/NavigationFocusManager/index.ts
new file mode 100644
index 000000000000..2c2c8e226155
--- /dev/null
+++ b/src/libs/NavigationFocusManager/index.ts
@@ -0,0 +1,18 @@
+import type NavigationFocusManagerModule from './types';
+
+const NavigationFocusManager: NavigationFocusManagerModule = {
+    initialize: () => {},
+    destroy: () => {},
+    captureForRoute: () => {},
+    retrieveForRoute: () => null,
+    clearForRoute: () => {},
+    hasStoredFocus: () => false,
+    registerFocusedRoute: () => {},
+    unregisterFocusedRoute: () => {},
+    wasRecentKeyboardInteraction: () => false,
+    clearKeyboardInteractionFlag: () => {},
+    getCapturedAnchorElement: () => null,
+    cleanupRemovedRoutes: () => {},
+};
+
+export default NavigationFocusManager;
diff --git a/src/libs/NavigationFocusManager/index.web.ts b/src/libs/NavigationFocusManager/index.web.ts
new file mode 100644
index 000000000000..32dd76cf23b9
--- /dev/null
+++ b/src/libs/NavigationFocusManager/index.web.ts
@@ -0,0 +1,825 @@
+/**
+ * NavigationFocusManager handles focus capture and restoration during screen navigation.
+ *
+ * Problem: When navigating between screens, focus moves to body BEFORE the new screen's
+ * FocusTrap can capture it (click -> navigation -> focus lost -> FocusTrap activates too late).
+ *
+ * Solution: Capture the focused element during pointerdown/keydown BEFORE navigation.
+ * Each capture is tagged with the current route key for state-based validation.
+ *
+ * Lifecycle: cleanupRemovedRoutes() is called from NavigationRoot on state change,
+ * removing focus data for routes no longer in the navigation state. Route existence
+ * is the source of truth - no timestamps needed.
+ *
+ * Focus restoration uses `initialFocus` (trap activation), not `setReturnFocus`
+ * (trap deactivation), because we restore focus when RETURNING to a screen.
+ */
+import Log from '@libs/Log';
+import extractNavigationKeys from '@libs/Navigation/helpers/extractNavigationKeys';
+import type {State} from '@libs/Navigation/types';
+import {NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE, NAVIGATION_FOCUS_ROUTE_SELECTOR} from './constants';
+import type NavigationFocusManagerModule from './types';
+
+type InteractionType = 'keyboard' | 'pointer' | 'unknown';
+
+type InteractionTrigger = 'enterOrSpace' | 'escape' | 'pointer' | 'unknown';
+
+type InteractionProvenance = {
+    interactionType: InteractionType;
+    interactionTrigger: InteractionTrigger;
+    routeKey: string | null;
+};
+
+/**
+ * Scoring weights for element matching during focus restoration.
+ * Higher score = higher confidence the candidate is the correct element.
+ * Used by findMatchingElement() to identify elements after screen remount.
+ *
+ * Pattern: Follows the MATCH_RANK constant object pattern from
+ * src/libs/filterArrayByMatch.ts for consistent codebase style.
+ */
+const ELEMENT_MATCH_SCORE = {
+    /** aria-label exact match - often unique for interactive elements */
+    ARIA_LABEL: 10,
+    /** role attribute match - weak signal, many elements share roles */
+    ROLE: 5,
+    /** data-testid exact match - explicitly unique, highest confidence */
+    DATA_TESTID: 50,
+    /** Text content prefix match (first N chars) - fuzzy matching */
+    TEXT_PREFIX: 30,
+    /** Text content exact match - full text identical */
+    TEXT_EXACT: 40,
+} as const;
+
+/** Minimum score required to consider an element a valid match */
+const MIN_MATCH_SCORE = 15;
+
+/** Max characters stored for text content preview */
+const TEXT_CONTENT_PREVIEW_LENGTH = 100;
+
+/** Characters to compare for fuzzy text prefix matching */
+const TEXT_CONTENT_PREFIX_LENGTH = 20;
+
+const SHOULD_LOG_DEBUG_INFO = typeof __DEV__ === 'boolean' ? __DEV__ : process.env.NODE_ENV !== 'production';
+
+/**
+ * Element identification info for restoring focus after screen remount.
+ * Unlike storing DOM element references (which become invalid after unmount),
+ * this stores attributes that can be used to find the equivalent element
+ * in the new DOM.
+ *
+ * Lifecycle is managed by cleanupRemovedRoutes() - no timestamp needed.
+ */
+type ElementIdentifier = {
+    tagName: string;
+    ariaLabel: string | null;
+    role: string | null;
+    /** First TEXT_CONTENT_PREVIEW_LENGTH chars of textContent for unique identification (e.g., workspace name) */
+    textContentPreview: string;
+    dataTestId: string | null;
+};
+
+type CapturedFocus = {
+    element: HTMLElement;
+    /** Route key this capture belongs to, for state-based validation */
+    forRoute: string | null;
+};
+
+type ElementQueryStrategy = (tagNameSelector: string) => readonly HTMLElement[];
+
+type CandidateMatch = {
+    element: HTMLElement;
+    score: number;
+    hasDataTestIdMatch: boolean;
+    hasAriaLabelMatch: boolean;
+    hasRoleMatch: boolean;
+    hasTextExactMatch: boolean;
+    hasTextPrefixMatch: boolean;
+    isPrefixOnlyMatch: boolean;
+};
+
+const defaultElementQueryStrategy: ElementQueryStrategy = (tagNameSelector) => Array.from(document.querySelectorAll<HTMLElement>(tagNameSelector));
+
+type ListenerRegistry = {
+    pointerdown: ((event: PointerEvent) => void) | null;
+    keydown: ((event: KeyboardEvent) => void) | null;
+    owner: symbol | null;
+};
+
+const LISTENER_REGISTRY_KEY = Symbol.for('expensify.NavigationFocusManager.listeners');
+const listenerOwnerToken = Symbol('NavigationFocusManager.instance');
+
+function getListenerRegistry(): ListenerRegistry {
+    const globalObject = globalThis as Record<PropertyKey, unknown>;
+    const existingRegistry = globalObject[LISTENER_REGISTRY_KEY] as ListenerRegistry | undefined;
+    if (existingRegistry) {
+        return existingRegistry;
+    }
+
+    const nextRegistry: ListenerRegistry = {
+        pointerdown: null,
+        keydown: null,
+        owner: null,
+    };
+    globalObject[LISTENER_REGISTRY_KEY] = nextRegistry;
+    return nextRegistry;
+}
+
+// Module-level state (following ComposerFocusManager pattern)
+let lastInteractionCapture: CapturedFocus | null = null;
+/** Stores element identifiers for non-persistent screens (that unmount on navigation) */
+const routeElementIdentifierMap = new Map<string, ElementIdentifier>();
+/** Legacy: stores element references for persistent screens (that stay mounted) */
+const routeFocusMap = new Map<string, CapturedFocus>();
+let isInitialized = false;
+
+// Track current focused screen's route key for immediate capture
+// This allows capturing to routeFocusMap during interaction, before screen unmounts
+let currentFocusedRouteKey: string | null = null;
+
+// Track if the most recent user interaction was via keyboard (Enter/Space)
+// Used by modals to determine if they should auto-focus their content on open
+let wasKeyboardInteraction = false;
+let lastInteractionProvenance: InteractionProvenance | null = null;
+
+function logFocusDebug(message: string, metadata?: Record<string, unknown>): void {
+    if (!SHOULD_LOG_DEBUG_INFO) {
+        return;
+    }
+    Log.info(message, false, metadata);
+}
+
+type RouteFocusEntryUpdate = {
+    element?: CapturedFocus | null;
+    identifier?: ElementIdentifier | null;
+};
+
+function updateRouteFocusEntry(routeKey: string, update: RouteFocusEntryUpdate): void {
+    if (update.element !== undefined) {
+        if (update.element) {
+            routeFocusMap.set(routeKey, update.element);
+        } else {
+            routeFocusMap.delete(routeKey);
+        }
+    }
+
+    if (update.identifier !== undefined) {
+        if (update.identifier) {
+            routeElementIdentifierMap.set(routeKey, update.identifier);
+        } else {
+            routeElementIdentifierMap.delete(routeKey);
+        }
+    }
+}
+
+function clearRouteFocusEntry(routeKey: string): void {
+    updateRouteFocusEntry(routeKey, {element: null, identifier: null});
+}
+
+function setInteractionProvenance(provenance: InteractionProvenance): void {
+    lastInteractionProvenance = provenance;
+}
+
+function clearInteractionProvenance(): void {
+    lastInteractionProvenance = null;
+}
+
+function clearInteractionProvenanceForRoute(routeKey: string): void {
+    if (lastInteractionProvenance?.routeKey !== routeKey) {
+        return;
+    }
+    clearInteractionProvenance();
+}
+
+function resolveRouteKeyForElement(element: HTMLElement | null): string | null {
+    if (!element) {
+        return currentFocusedRouteKey;
+    }
+
+    const routeBoundary = element.closest<HTMLElement>(NAVIGATION_FOCUS_ROUTE_SELECTOR);
+    return routeBoundary?.getAttribute(NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE) ?? currentFocusedRouteKey;
+}
+
+function buildCandidateMatch(candidate: HTMLElement, identifier: ElementIdentifier): CandidateMatch {
+    const hasAriaLabelMatch = !!identifier.ariaLabel && candidate.getAttribute('aria-label') === identifier.ariaLabel;
+    const hasRoleMatch = !!identifier.role && candidate.getAttribute('role') === identifier.role;
+    const hasDataTestIdMatch = !!identifier.dataTestId && candidate.getAttribute('data-testid') === identifier.dataTestId;
+
+    const candidateText = (candidate.textContent ?? '').slice(0, TEXT_CONTENT_PREVIEW_LENGTH).trim();
+    const textPrefix = identifier.textContentPreview.slice(0, TEXT_CONTENT_PREFIX_LENGTH);
+
+    const hasTextExactMatch = !!identifier.textContentPreview && candidateText === identifier.textContentPreview;
+    const hasTextPrefixMatch = !!identifier.textContentPreview && !!textPrefix && !hasTextExactMatch && candidateText.startsWith(textPrefix);
+
+    const isPrefixOnlyMatch = hasTextPrefixMatch && !hasAriaLabelMatch && !hasRoleMatch && !hasDataTestIdMatch;
+
+    let score = 0;
+    if (hasAriaLabelMatch) {
+        score += ELEMENT_MATCH_SCORE.ARIA_LABEL;
+    }
+    if (hasRoleMatch) {
+        score += ELEMENT_MATCH_SCORE.ROLE;
+    }
+    if (hasDataTestIdMatch) {
+        score += ELEMENT_MATCH_SCORE.DATA_TESTID;
+    }
+    if (hasTextExactMatch) {
+        score += ELEMENT_MATCH_SCORE.TEXT_EXACT;
+    } else if (hasTextPrefixMatch) {
+        score += ELEMENT_MATCH_SCORE.TEXT_PREFIX;
+    }
+
+    return {
+        element: candidate,
+        score,
+        hasDataTestIdMatch,
+        hasAriaLabelMatch,
+        hasRoleMatch,
+        hasTextExactMatch,
+        hasTextPrefixMatch,
+        isPrefixOnlyMatch,
+    };
+}
+
+function isCandidateBetter(candidate: CandidateMatch, bestCandidate: CandidateMatch | null): boolean {
+    if (!bestCandidate) {
+        return true;
+    }
+
+    if (candidate.score !== bestCandidate.score) {
+        return candidate.score > bestCandidate.score;
+    }
+
+    if (candidate.hasDataTestIdMatch !== bestCandidate.hasDataTestIdMatch) {
+        return candidate.hasDataTestIdMatch;
+    }
+
+    if (candidate.hasAriaLabelMatch !== bestCandidate.hasAriaLabelMatch) {
+        return candidate.hasAriaLabelMatch;
+    }
+
+    if (candidate.hasTextExactMatch !== bestCandidate.hasTextExactMatch) {
+        return candidate.hasTextExactMatch;
+    }
+
+    if (candidate.hasRoleMatch !== bestCandidate.hasRoleMatch) {
+        return candidate.hasRoleMatch;
+    }
+
+    if (candidate.hasTextPrefixMatch !== bestCandidate.hasTextPrefixMatch) {
+        return candidate.hasTextPrefixMatch;
+    }
+
+    // Preserve original DOM order for full ties by keeping existing best candidate.
+    return false;
+}
+
+/**
+ * Extract identification info from an element that can be used to find
+ * the equivalent element in a new DOM after screen remount.
+ * Lifecycle is managed by cleanupRemovedRoutes() - no timestamp needed.
+ */
+function extractElementIdentifier(element: HTMLElement): ElementIdentifier {
+    return {
+        tagName: element.tagName,
+        ariaLabel: element.getAttribute('aria-label'),
+        role: element.getAttribute('role'),
+        textContentPreview: (element.textContent ?? '').slice(0, TEXT_CONTENT_PREVIEW_LENGTH).trim(),
+        dataTestId: element.getAttribute('data-testid'),
+    };
+}
+
+/**
+ * Find an element in the current DOM that matches the stored identifier.
+ * Uses a scoring system to find the best match.
+ */
+function findMatchingElement(identifier: ElementIdentifier): HTMLElement | null {
+    const candidates = Array.from(defaultElementQueryStrategy(identifier.tagName));
+
+    if (candidates.length === 0) {
+        return null;
+    }
+
+    let bestMatch: CandidateMatch | null = null;
+    let prefixOnlyCandidateCount = 0;
+
+    for (const candidate of candidates) {
+        const candidateMatch = buildCandidateMatch(candidate, identifier);
+
+        if (candidateMatch.isPrefixOnlyMatch) {
+            prefixOnlyCandidateCount += 1;
+        }
+
+        if (isCandidateBetter(candidateMatch, bestMatch)) {
+            bestMatch = candidateMatch;
+        }
+    }
+
+    if (!bestMatch || bestMatch.score < MIN_MATCH_SCORE) {
+        return null;
+    }
+
+    // Prefix-only matches are weak signals. If multiple elements are prefix-only matches,
+    // we avoid restoring to any of them to prevent unstable or incorrect focus targets.
+    if (bestMatch.isPrefixOnlyMatch && prefixOnlyCandidateCount > 1) {
+        logFocusDebug('[NavigationFocusManager] Prefix-only match is ambiguous, skipping restoration', {
+            tagName: identifier.tagName,
+            prefix: identifier.textContentPreview.slice(0, TEXT_CONTENT_PREFIX_LENGTH),
+            candidateCount: prefixOnlyCandidateCount,
+        });
+        return null;
+    }
+
+    return bestMatch.element;
+}
+
+/**
+ * Capture the element being interacted with.
+ * This runs in capture phase, before any click handlers.
+ */
+function handleInteraction(event: PointerEvent): void {
+    // Mouse/touch interaction clears any pending keyboard flag
+    wasKeyboardInteraction = false;
+
+    const targetElement = event.target as HTMLElement;
+    const routeKey = resolveRouteKeyForElement(targetElement);
+
+    setInteractionProvenance({
+        interactionType: 'pointer',
+        interactionTrigger: 'pointer',
+        routeKey,
+    });
+
+    if (targetElement && targetElement !== document.body && targetElement.tagName !== 'HTML') {
+        // Menu items are transient (exist only while popover is open) and will be
+        // removed from DOM before focus restoration can use them. We use STATE-BASED
+        // protection (not time-based) to preserve the anchor element (e.g., "More" button)
+        // that opened the menu. This ensures focus restoration works regardless of how
+        // long the user takes to click a menu item. See issue #76921 for details.
+        const isMenuitem = !!targetElement.closest('[role="menuitem"]');
+        const isPriorCaptureAnchor = lastInteractionCapture && !lastInteractionCapture.element.closest('[role="menuitem"]');
+        if (isMenuitem && isPriorCaptureAnchor) {
+            logFocusDebug('[NavigationFocusManager] Skipped menuitem capture - preserving non-menuitem anchor', {
+                menuitemLabel: targetElement.closest('[role="menuitem"]')?.getAttribute('aria-label'),
+                anchorLabel: lastInteractionCapture?.element.getAttribute('aria-label'),
+            });
+            return;
+        }
+
+        // Selector excludes tabindex="-1" elements (non-focusable) to skip display-only
+        // elements and capture the outer interactive container for focus restoration.
+        // Note: [role="menuitem"] is intentionally excluded - we skip those above.
+        const interactiveElement = targetElement.closest<HTMLElement>('button, a, [role="button"], [tabindex]:not([tabindex="-1"])');
+        const elementToCapture = interactiveElement ?? targetElement;
+        const captureRouteKey = resolveRouteKeyForElement(elementToCapture);
+
+        setInteractionProvenance({
+            interactionType: 'pointer',
+            interactionTrigger: 'pointer',
+            routeKey: captureRouteKey,
+        });
+
+        lastInteractionCapture = {
+            element: elementToCapture,
+            forRoute: captureRouteKey,
+        };
+
+        // IMMEDIATE CAPTURE: Store element identifier for non-persistent screens
+        // This enables focus restoration even after screen unmounts and remounts with new DOM
+        if (captureRouteKey) {
+            const identifier = extractElementIdentifier(elementToCapture);
+            updateRouteFocusEntry(captureRouteKey, {
+                element: {
+                    element: elementToCapture,
+                    forRoute: captureRouteKey,
+                },
+                identifier,
+            });
+        }
+
+        logFocusDebug('[NavigationFocusManager] Captured element on pointerdown', {
+            tagName: elementToCapture.tagName,
+            ariaLabel: elementToCapture.getAttribute('aria-label'),
+            role: elementToCapture.getAttribute('role'),
+            isMenuitem,
+        });
+    }
+}
+
+/**
+ * For keyboard navigation (Enter/Space key triggers navigation like a click)
+ * Also tracks Escape for back navigation detection.
+ */
+function handleKeyDown(event: KeyboardEvent): void {
+    // Track Enter/Space for forward navigation, Escape for back navigation
+    if (event.key !== 'Enter' && event.key !== ' ' && event.key !== 'Escape') {
+        return;
+    }
+
+    // ALWAYS set keyboard interaction flag for modal auto-focus and navigation
+    // This must happen BEFORE any early returns (e.g., menuitem protection)
+    wasKeyboardInteraction = true;
+    const activeElement = document.activeElement as HTMLElement;
+    const routeKey = resolveRouteKeyForElement(activeElement);
+
+    setInteractionProvenance({
+        interactionType: 'keyboard',
+        interactionTrigger: event.key === 'Escape' ? 'escape' : 'enterOrSpace',
+        routeKey,
+    });
+
+    // For Escape key (back navigation), we only need the flag, not element capture
+    // Element capture is for forward navigation to know where to return focus
+    if (event.key === 'Escape') {
+        return;
+    }
+
+    if (activeElement && activeElement !== document.body && activeElement.tagName !== 'HTML') {
+        const isMenuitem = !!activeElement.closest('[role="menuitem"]');
+        const isPriorCaptureAnchor = lastInteractionCapture && !lastInteractionCapture.element.closest('[role="menuitem"]');
+        if (isMenuitem && isPriorCaptureAnchor) {
+            logFocusDebug('[NavigationFocusManager] Skipped menuitem capture on keydown - preserving non-menuitem anchor', {
+                menuitemLabel: activeElement.closest('[role="menuitem"]')?.getAttribute('aria-label'),
+                anchorLabel: lastInteractionCapture?.element.getAttribute('aria-label'),
+            });
+            return;
+        }
+
+        lastInteractionCapture = {
+            element: activeElement,
+            forRoute: routeKey,
+        };
+
+        // IMMEDIATE CAPTURE: Store element identifier for non-persistent screens
+        if (routeKey) {
+            const identifier = extractElementIdentifier(activeElement);
+            updateRouteFocusEntry(routeKey, {
+                element: {
+                    element: activeElement,
+                    forRoute: routeKey,
+                },
+                identifier,
+            });
+        }
+
+        logFocusDebug('[NavigationFocusManager] Captured element on keydown', {
+            tagName: activeElement.tagName,
+            ariaLabel: activeElement.getAttribute('aria-label'),
+            role: activeElement.getAttribute('role'),
+            key: event.key,
+        });
+    }
+}
+
+function clearLocalStateOnDestroy(): void {
+    isInitialized = false;
+    routeFocusMap.clear();
+    routeElementIdentifierMap.clear();
+    lastInteractionCapture = null;
+    clearInteractionProvenance();
+    currentFocusedRouteKey = null;
+    wasKeyboardInteraction = false;
+}
+
+/**
+ * Initialize the manager by attaching global capture-phase listeners.
+ * Should be called once at app startup.
+ */
+function initialize(): void {
+    if (isInitialized || typeof document === 'undefined') {
+        return;
+    }
+
+    const listenerRegistry = getListenerRegistry();
+    const hasCurrentListeners = listenerRegistry.pointerdown === handleInteraction && listenerRegistry.keydown === handleKeyDown;
+    if (hasCurrentListeners) {
+        listenerRegistry.owner = listenerOwnerToken;
+        isInitialized = true;
+        return;
+    }
+
+    if (listenerRegistry.pointerdown) {
+        document.removeEventListener('pointerdown', listenerRegistry.pointerdown, {capture: true});
+    }
+    if (listenerRegistry.keydown) {
+        document.removeEventListener('keydown', listenerRegistry.keydown, {capture: true});
+    }
+
+    // Capture phase runs BEFORE the event reaches target handlers
+    // This ensures we capture the focused element before any navigation logic
+    document.addEventListener('pointerdown', handleInteraction, {capture: true});
+    document.addEventListener('keydown', handleKeyDown, {capture: true});
+
+    listenerRegistry.pointerdown = handleInteraction;
+    listenerRegistry.keydown = handleKeyDown;
+    listenerRegistry.owner = listenerOwnerToken;
+    isInitialized = true;
+}
+
+/**
+ * Cleanup listeners. Should be called on app unmount.
+ */
+function destroy(): void {
+    if (typeof document !== 'undefined') {
+        const listenerRegistry = getListenerRegistry();
+
+        if (listenerRegistry.pointerdown === handleInteraction) {
+            document.removeEventListener('pointerdown', handleInteraction, {capture: true});
+            listenerRegistry.pointerdown = null;
+        }
+
+        if (listenerRegistry.keydown === handleKeyDown) {
+            document.removeEventListener('keydown', handleKeyDown, {capture: true});
+            listenerRegistry.keydown = null;
+        }
+
+        if (!listenerRegistry.pointerdown && !listenerRegistry.keydown) {
+            listenerRegistry.owner = null;
+        } else if (listenerRegistry.owner === listenerOwnerToken && listenerRegistry.pointerdown !== handleInteraction && listenerRegistry.keydown !== handleKeyDown) {
+            listenerRegistry.owner = null;
+        }
+    }
+
+    clearLocalStateOnDestroy();
+}
+
+/**
+ * Called when a screen loses focus (isFocused becomes false).
+ * Stores the most recently captured element for this route.
+ *
+ * Uses state-based validation: capture is valid if it belongs to this specific route.
+ * This replaces time-based validation which had edge cases on slow devices and
+ * incorrectly accepted captures from wrong routes.
+ *
+ * @param routeKey - The route.key from React Navigation
+ */
+function captureForRoute(routeKey: string): void {
+    let elementToStore: HTMLElement | null = null;
+    let captureSource: 'interaction' | 'activeElement' | 'none' = 'none';
+
+    // Try to use the element captured during user interaction if it belongs to this route
+    if (lastInteractionCapture) {
+        const {element: capturedElement, forRoute} = lastInteractionCapture;
+        const isInDOM = document.body.contains(capturedElement);
+
+        // State-based validity: capture MUST be for THIS specific route
+        // Reject null forRoute - if we don't know the origin, we can't validate it
+        const isValidCapture = forRoute === routeKey;
+
+        if (forRoute === null) {
+            logFocusDebug('[NavigationFocusManager] Capture has no route - rejecting for safety', {
+                requestedRoute: routeKey,
+                capturedLabel: capturedElement.getAttribute('aria-label'),
+            });
+        } else if (!isValidCapture) {
+            logFocusDebug('[NavigationFocusManager] Capture is for different route - rejecting', {
+                captureRoute: forRoute,
+                requestedRoute: routeKey,
+            });
+        } else if (!isInDOM) {
+            logFocusDebug('[NavigationFocusManager] Captured element no longer in DOM - falling back to activeElement', {
+                routeKey,
+                capturedLabel: capturedElement.getAttribute('aria-label'),
+            });
+        } else {
+            elementToStore = capturedElement;
+            captureSource = 'interaction';
+        }
+    }
+
+    // Fallback: use current activeElement if captured element is invalid or missing
+    // This is critical for dropdown menus where the clicked menu item is removed,
+    // but focus has been restored to the anchor button (via onModalHide focus call)
+    if (!elementToStore) {
+        const activeElement = document.activeElement as HTMLElement;
+        // Exclude document.body and document.documentElement:
+        // - body: Common fallback when no element is focused
+        // - documentElement (HTML): Can be activeElement in edge cases, e.g., after
+        //   all focusable elements are removed, or in certain browser/JSDOM states.
+        //   Neither represents a meaningful focus target for restoration.
+        if (activeElement && activeElement !== document.body && activeElement !== document.documentElement) {
+            elementToStore = activeElement;
+            captureSource = 'activeElement';
+        }
+    }
+
+    // Store the element if we found a valid one
+    if (elementToStore) {
+        updateRouteFocusEntry(routeKey, {
+            element: {
+                element: elementToStore,
+                forRoute: routeKey,
+            },
+        });
+        logFocusDebug('[NavigationFocusManager] Stored focus for route', {
+            routeKey,
+            source: captureSource,
+            tagName: elementToStore.tagName,
+            ariaLabel: elementToStore.getAttribute('aria-label'),
+            role: elementToStore.getAttribute('role'),
+        });
+    } else {
+        logFocusDebug('[NavigationFocusManager] No valid element to store for route', {
+            routeKey,
+            activeElement: document.activeElement?.tagName,
+        });
+    }
+
+    // Clear the interaction capture after use
+    lastInteractionCapture = null;
+    clearInteractionProvenance();
+}
+
+/**
+ * Called when a screen regains focus (via initialFocus callback).
+ * Returns the stored element if it's still valid, or finds a matching element
+ * in the new DOM for non-persistent screens that remounted.
+ *
+ * Lifecycle is managed by cleanupRemovedRoutes() - if data exists, it's valid.
+ * No time-based expiry checks needed.
+ *
+ * @param routeKey - The route.key from React Navigation
+ * @returns The element to focus, or null if none available
+ */
+function retrieveForRoute(routeKey: string): HTMLElement | null {
+    const captured = routeFocusMap.get(routeKey);
+    const identifier = routeElementIdentifierMap.get(routeKey);
+
+    // Remove from maps regardless (one-time use)
+    clearRouteFocusEntry(routeKey);
+
+    // Strategy 1: Try element reference (works for persistent screens)
+    if (captured && document.body.contains(captured.element)) {
+        logFocusDebug('[NavigationFocusManager] Retrieved focus for route (element reference)', {
+            routeKey,
+            tagName: captured.element.tagName,
+            ariaLabel: captured.element.getAttribute('aria-label'),
+        });
+        return captured.element;
+    }
+
+    // Strategy 2: Use element identifier to find matching element in new DOM
+    if (identifier) {
+        const matchedElement = findMatchingElement(identifier);
+        if (matchedElement) {
+            logFocusDebug('[NavigationFocusManager] Retrieved focus for route (identifier match)', {
+                routeKey,
+                tagName: matchedElement.tagName,
+                ariaLabel: matchedElement.getAttribute('aria-label'),
+            });
+            return matchedElement;
+        }
+
+        logFocusDebug('[NavigationFocusManager] No matching element found for identifier', {
+            routeKey,
+            identifier: {
+                tagName: identifier.tagName,
+                ariaLabel: identifier.ariaLabel,
+                textContentPreview: identifier.textContentPreview.slice(0, 30),
+            },
+        });
+    }
+
+    if (!captured && !identifier) {
+        logFocusDebug('[NavigationFocusManager] No stored focus for route', {routeKey});
+    }
+
+    return null;
+}
+
+/**
+ * Clear the stored focus element for a specific route.
+ * Useful when a route is being unmounted or reset.
+ *
+ * @param routeKey - The route.key from React Navigation
+ */
+function clearForRoute(routeKey: string): void {
+    clearRouteFocusEntry(routeKey);
+    clearInteractionProvenanceForRoute(routeKey);
+}
+
+/**
+ * Check if there's a stored element for a route (without consuming it).
+ * Useful for determining if focus restoration should be attempted.
+ *
+ * @param routeKey - The route.key from React Navigation
+ * @returns true if there's a stored element or identifier for this route
+ */
+function hasStoredFocus(routeKey: string): boolean {
+    return routeFocusMap.has(routeKey) || routeElementIdentifierMap.has(routeKey);
+}
+
+/**
+ * Register the currently focused screen's route key.
+ * This enables immediate capture to routeFocusMap during interactions,
+ * which is critical for non-persistent screens that unmount before
+ * captureForRoute() can be called.
+ *
+ * @param routeKey - The route.key from React Navigation
+ */
+function registerFocusedRoute(routeKey: string): void {
+    if (currentFocusedRouteKey !== routeKey) {
+        clearInteractionProvenance();
+    }
+    currentFocusedRouteKey = routeKey;
+}
+
+/**
+ * Unregister the focused route when screen loses focus or unmounts.
+ *
+ * @param routeKey - The route.key to unregister (only clears if it matches current)
+ */
+function unregisterFocusedRoute(routeKey: string): void {
+    if (currentFocusedRouteKey !== routeKey) {
+        return;
+    }
+    currentFocusedRouteKey = null;
+}
+
+/**
+ * Check if the most recent user interaction was via keyboard (Enter/Space).
+ * Used by modals to determine if they should auto-focus their content.
+ */
+function wasRecentKeyboardInteraction(): boolean {
+    return wasKeyboardInteraction;
+}
+
+/**
+ * Clear the keyboard interaction flag after it has been consumed.
+ * Call this immediately after reading the flag to prevent stale reads.
+ */
+function clearKeyboardInteractionFlag(): void {
+    wasKeyboardInteraction = false;
+}
+
+/**
+ * Get the last captured element that is NOT a menuitem.
+ * Used for focus restoration when a modal triggered from a menu closes.
+ */
+function getCapturedAnchorElement(): HTMLElement | null {
+    // Only available on web where document exists
+    if (typeof document === 'undefined' || !lastInteractionCapture) {
+        return null;
+    }
+
+    const element = lastInteractionCapture.element;
+
+    // Verify element is still in DOM
+    if (!document.body.contains(element)) {
+        logFocusDebug('[NavigationFocusManager] getCapturedAnchorElement: element no longer in DOM');
+        return null;
+    }
+
+    // Only return non-menuitem elements (anchors like "More" button)
+    if (element.closest('[role="menuitem"]')) {
+        logFocusDebug('[NavigationFocusManager] getCapturedAnchorElement: element is menuitem, returning null');
+        return null;
+    }
+
+    logFocusDebug('[NavigationFocusManager] getCapturedAnchorElement: returning anchor', {
+        tagName: element.tagName,
+        ariaLabel: element.getAttribute('aria-label'),
+    });
+
+    return element;
+}
+
+/**
+ * Removes focus data for routes that are no longer in the navigation state.
+ * Called from handleStateChange in NavigationRoot.tsx.
+ */
+function cleanupRemovedRoutes(state: State): void {
+    const activeKeys = extractNavigationKeys(state.routes);
+    const knownRouteKeys = new Set<string>([...routeFocusMap.keys(), ...routeElementIdentifierMap.keys()]);
+    const provenanceRouteKey = lastInteractionProvenance?.routeKey;
+    if (provenanceRouteKey) {
+        knownRouteKeys.add(provenanceRouteKey);
+    }
+
+    for (const key of knownRouteKeys) {
+        if (activeKeys.has(key)) {
+            continue;
+        }
+
+        clearRouteFocusEntry(key);
+        clearInteractionProvenanceForRoute(key);
+        logFocusDebug('[NavigationFocusManager] Cleaned up focus data for removed route', {routeKey: key});
+    }
+}
+
+const NavigationFocusManager: NavigationFocusManagerModule = {
+    initialize,
+    destroy,
+    captureForRoute,
+    retrieveForRoute,
+    clearForRoute,
+    hasStoredFocus,
+    registerFocusedRoute,
+    unregisterFocusedRoute,
+    wasRecentKeyboardInteraction,
+    clearKeyboardInteractionFlag,
+    getCapturedAnchorElement,
+    cleanupRemovedRoutes,
+};
+
+export default NavigationFocusManager;
diff --git a/src/libs/NavigationFocusManager/types.ts b/src/libs/NavigationFocusManager/types.ts
new file mode 100644
index 000000000000..d4ea2476792e
--- /dev/null
+++ b/src/libs/NavigationFocusManager/types.ts
@@ -0,0 +1,18 @@
+import type {State} from '@libs/Navigation/types';
+
+type NavigationFocusManagerModule = {
+    initialize: () => void;
+    destroy: () => void;
+    captureForRoute: (routeKey: string) => void;
+    retrieveForRoute: (routeKey: string) => HTMLElement | null;
+    clearForRoute: (routeKey: string) => void;
+    hasStoredFocus: (routeKey: string) => boolean;
+    registerFocusedRoute: (routeKey: string) => void;
+    unregisterFocusedRoute: (routeKey: string) => void;
+    wasRecentKeyboardInteraction: () => boolean;
+    clearKeyboardInteractionFlag: () => void;
+    getCapturedAnchorElement: () => HTMLElement | null;
+    cleanupRemovedRoutes: (state: State) => void;
+};
+
+export default NavigationFocusManagerModule;
diff --git a/src/libs/focusComposerWithDelay/index.ts b/src/libs/focusComposerWithDelay/index.ts
index 1f18a4b9d4bc..395f8cfa2665 100644
--- a/src/libs/focusComposerWithDelay/index.ts
+++ b/src/libs/focusComposerWithDelay/index.ts
@@ -34,7 +34,9 @@ function focusComposerWithDelay(textInput: InputType | null, delay: number = CON
             }
             // When the closing modal has a focused text input focus() needs a delay to properly work.
             // Setting 150ms here is a temporary workaround for the Android HybridApp. It should be reverted once we identify the real root cause of this issue: https://github.com/Expensify/App/issues/56311.
-            setTimeout(() => textInput.focus(), delay);
+            setTimeout(() => {
+                textInput.focus();
+            }, delay);
             if (forcedSelectionRange) {
                 setTextInputSelection(textInput, forcedSelectionRange);
             }
diff --git a/src/libs/focusUtils/index.native.ts b/src/libs/focusUtils/index.native.ts
new file mode 100644
index 000000000000..a866e4743d62
--- /dev/null
+++ b/src/libs/focusUtils/index.native.ts
@@ -0,0 +1,8 @@
+import type FocusUtils from './types';
+
+const focusUtils: FocusUtils = {
+    isElementFocusRestorable: (_element): _element is HTMLElement => false,
+    isFocusableActionableElement: (_element): _element is HTMLElement => false,
+};
+
+export default focusUtils;
diff --git a/src/libs/focusUtils/index.ts b/src/libs/focusUtils/index.ts
new file mode 100644
index 000000000000..10b7fc3ee464
--- /dev/null
+++ b/src/libs/focusUtils/index.ts
@@ -0,0 +1,3 @@
+import focusUtils from './index.native';
+
+export default focusUtils;
diff --git a/src/libs/focusUtils/index.web.ts b/src/libs/focusUtils/index.web.ts
new file mode 100644
index 000000000000..e66f624035e4
--- /dev/null
+++ b/src/libs/focusUtils/index.web.ts
@@ -0,0 +1,45 @@
+import CONST from '@src/CONST';
+import type FocusUtils from './types';
+
+function hasFocusBlockingAttributes(element: HTMLElement): boolean {
+    return element.hasAttribute('disabled') || element.hasAttribute('inert') || !!element.closest('[inert]');
+}
+
+const focusUtils: FocusUtils = {
+    isElementFocusRestorable: (element): element is HTMLElement => {
+        if (!(element instanceof HTMLElement) || element === document.body || element === document.documentElement || !document.body.contains(element)) {
+            return false;
+        }
+
+        const style = window.getComputedStyle(element);
+        if (style.display === 'none' || style.visibility === 'hidden') {
+            return false;
+        }
+
+        const rect = element.getBoundingClientRect();
+        if (rect.width === 0 && rect.height === 0) {
+            return false;
+        }
+
+        return !hasFocusBlockingAttributes(element);
+    },
+
+    isFocusableActionableElement: (element): element is HTMLElement => {
+        if (!(element instanceof HTMLElement)) {
+            return false;
+        }
+
+        const role = element.getAttribute('role');
+        if (role !== CONST.ROLE.BUTTON && role !== CONST.ROLE.MENUITEM) {
+            return false;
+        }
+
+        if (element.tabIndex < 0 || element.getAttribute('aria-disabled') === 'true') {
+            return false;
+        }
+
+        return !hasFocusBlockingAttributes(element);
+    },
+};
+
+export default focusUtils;
diff --git a/src/libs/focusUtils/types.ts b/src/libs/focusUtils/types.ts
new file mode 100644
index 000000000000..ba7948e3900b
--- /dev/null
+++ b/src/libs/focusUtils/types.ts
@@ -0,0 +1,6 @@
+type FocusUtils = {
+    isElementFocusRestorable: (element: Element | null) => element is HTMLElement;
+    isFocusableActionableElement: (element: Element) => element is HTMLElement;
+};
+
+export default FocusUtils;
diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx
index cc6f4c94989b..3ae64bd4de2f 100644
--- a/src/pages/inbox/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx
+++ b/src/pages/inbox/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx
@@ -33,6 +33,7 @@ import type {ForwardedFSClassProps} from '@libs/Fullstory/types';
 import getPlatform from '@libs/getPlatform';
 import {addKeyDownPressListener, removeKeyDownPressListener} from '@libs/KeyboardShortcut/KeyDownPressListener';
 import {detectAndRewritePaste} from '@libs/MarkdownLinkHelpers';
+import NavigationFocusManager from '@libs/NavigationFocusManager';
 import Parser from '@libs/Parser';
 import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager';
 import {isValidReportIDFromPath, shouldAutoFocusOnKeyPress} from '@libs/ReportUtils';
@@ -800,10 +801,24 @@ function ComposerWithSuggestions({
             return;
         }
 
+        // Skip auto-focus for keyboard navigation returns
+        // This allows FocusTrapForScreen to restore focus to the original element
+        // Must check BOTH scenarios:
+        //   - Screen focus change (!prevIsFocused) - e.g., navigating between screens
+        //   - Modal/RHP close (!!prevIsModalVisible) - e.g., closing RHP overlay
+        // Note: RHP doesn't change isFocused, it triggers prevIsModalVisible change
+        const isScreenFocusChange = !prevIsFocused;
+        const isModalClose = !!prevIsModalVisible;
+        if ((isScreenFocusChange || isModalClose) && NavigationFocusManager.wasRecentKeyboardInteraction()) {
+            NavigationFocusManager.clearKeyboardInteractionFlag();
+            return;
+        }
+
         if (editFocused) {
             inputFocusChange(false);
             return;
         }
+
         focus(true);
     }, [focus, prevIsFocused, editFocused, prevIsModalVisible, isFocused, modal?.isVisible, isNextModalWillOpenRef, shouldAutoFocus, isSidePanelHiddenOrLargeScreen]);
 
diff --git a/src/pages/tasks/NewTaskPage.tsx b/src/pages/tasks/NewTaskPage.tsx
index 265b7f607bd7..f1a453a91cd2 100644
--- a/src/pages/tasks/NewTaskPage.tsx
+++ b/src/pages/tasks/NewTaskPage.tsx
@@ -15,7 +15,7 @@ import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings';
 import useThemeStyles from '@hooks/useThemeStyles';
-import blurActiveElement from '@libs/Accessibility/blurActiveElement';
+import blurActiveInputElement from '@libs/Accessibility/blurActiveInputElement';
 import {createTaskAndNavigate, dismissModalAndClearOutTaskInfo, getAssignee, getShareDestination, setShareDestinationValue} from '@libs/actions/Task';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
@@ -65,7 +65,7 @@ function NewTaskPage({route}: NewTaskPageProps) {
         focusTimeoutRef.current = setTimeout(() => {
             // eslint-disable-next-line @typescript-eslint/no-deprecated
             InteractionManager.runAfterInteractions(() => {
-                blurActiveElement();
+                blurActiveInputElement();
             });
         }, CONST.ANIMATED_TRANSITION);
         return () => focusTimeoutRef.current && clearTimeout(focusTimeoutRef.current);
diff --git a/src/pages/workspace/WorkspaceNamePage.tsx b/src/pages/workspace/WorkspaceNamePage.tsx
index 105001b4a6c4..a95f9994e732 100644
--- a/src/pages/workspace/WorkspaceNamePage.tsx
+++ b/src/pages/workspace/WorkspaceNamePage.tsx
@@ -6,6 +6,7 @@ import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
 import TextInput from '@components/TextInput';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {updateGeneralSettings} from '@libs/actions/Policy/Policy';
@@ -24,6 +25,7 @@ type Props = WithPolicyProps;
 function WorkspaceNamePage({policy}: Props) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
+    const {inputCallbackRef} = useAutoFocusInput();
 
     const submit = useCallback(
         (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_SETTINGS_FORM>) => {
@@ -91,7 +93,7 @@ function WorkspaceNamePage({policy}: Props) {
                             accessibilityLabel={translate('workspace.common.workspaceName')}
                             defaultValue={policy?.name}
                             spellCheck={false}
-                            autoFocus
+                            ref={inputCallbackRef}
                         />
                     </View>
                 </FormProvider>
diff --git a/tests/ui/components/ButtonWithDropdownMenuFocusCoverageTest.tsx b/tests/ui/components/ButtonWithDropdownMenuFocusCoverageTest.tsx
new file mode 100644
index 000000000000..8f6c1b2a670e
--- /dev/null
+++ b/tests/ui/components/ButtonWithDropdownMenuFocusCoverageTest.tsx
@@ -0,0 +1,175 @@
+import {fireEvent, render, screen} from '@testing-library/react-native';
+import React from 'react';
+import type {PropsWithChildren} from 'react';
+// Import after mocks
+// eslint-disable-next-line import/first
+import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
+
+type CapturedPopoverProps = {
+    isVisible?: boolean;
+    wasOpenedViaKeyboard?: boolean;
+    onModalHide?: () => void;
+};
+
+let mockLatestPopoverProps: CapturedPopoverProps | undefined;
+let mockLastButtonFocusSpy: jest.Mock | undefined;
+
+const mockWasRecentKeyboardInteraction = jest.fn<boolean, []>();
+const mockClearKeyboardInteractionFlag = jest.fn<void, []>();
+const mockCalculatePopoverPosition = jest.fn<Promise<{horizontal: number; vertical: number}>, []>(() => new Promise(() => {}));
+
+jest.mock(
+    'expo-web-browser',
+    () => ({
+        openAuthSessionAsync: jest.fn(),
+    }),
+    {virtual: true},
+);
+
+jest.mock('@components/PopoverMenu', () => {
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const ReactModule = jest.requireActual<typeof import('react')>('react');
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const {View} = jest.requireActual<typeof import('react-native')>('react-native');
+
+    return {
+        // eslint-disable-next-line @typescript-eslint/naming-convention
+        __esModule: true,
+        default: (props: PropsWithChildren<CapturedPopoverProps>) => {
+            mockLatestPopoverProps = props;
+            return ReactModule.createElement(View, {testID: 'mock-popover-menu'}, props.children);
+        },
+    };
+});
+
+jest.mock('@components/Button', () => {
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const ReactModule = jest.requireActual<typeof import('react')>('react');
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const {Pressable, Text} = jest.requireActual<typeof import('react-native')>('react-native');
+
+    const MockButton = ReactModule.forwardRef(
+        (
+            props: PropsWithChildren<{
+                onPress?: () => void;
+                text?: string;
+                children?: React.ReactNode;
+            }>,
+            ref: React.Ref<{focus: () => void}>,
+        ) => {
+            const focusSpy = jest.fn();
+            mockLastButtonFocusSpy = focusSpy;
+
+            ReactModule.useImperativeHandle(ref, () => ({focus: focusSpy}), [focusSpy]);
+
+            return (
+                <Pressable
+                    onPress={props.onPress}
+                    role="button"
+                >
+                    {props.text ? <Text>{props.text}</Text> : null}
+                    {props.children}
+                </Pressable>
+            );
+        },
+    );
+
+    MockButton.displayName = 'MockButton';
+
+    return {
+        // eslint-disable-next-line @typescript-eslint/naming-convention
+        __esModule: true,
+        default: MockButton,
+    };
+});
+
+jest.mock('@libs/NavigationFocusManager', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: {
+        wasRecentKeyboardInteraction: () => mockWasRecentKeyboardInteraction(),
+        clearKeyboardInteractionFlag: () => mockClearKeyboardInteractionFlag(),
+    },
+}));
+
+jest.mock('@hooks/usePopoverPosition', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: () => ({
+        calculatePopoverPosition: () => mockCalculatePopoverPosition(),
+    }),
+}));
+
+describe('ButtonWithDropdownMenu focus coverage', () => {
+    const options = [
+        {text: 'Option 1', value: 'one'},
+        {text: 'Option 2', value: 'two'},
+    ];
+
+    beforeEach(() => {
+        mockLatestPopoverProps = undefined;
+        mockLastButtonFocusSpy = undefined;
+        jest.clearAllMocks();
+        mockWasRecentKeyboardInteraction.mockReturnValue(false);
+    });
+
+    it('tracks keyboard open state in toggleMenu and clears it on close', () => {
+        mockWasRecentKeyboardInteraction.mockReturnValue(true);
+
+        render(
+            <ButtonWithDropdownMenu
+                options={options}
+                onPress={jest.fn()}
+                isSplitButton={false}
+            />,
+        );
+
+        expect(mockLatestPopoverProps?.isVisible).toBe(false);
+
+        fireEvent.press(screen.getByText('Option 1'));
+
+        expect(mockWasRecentKeyboardInteraction).toHaveBeenCalledTimes(1);
+        expect(mockClearKeyboardInteractionFlag).toHaveBeenCalledTimes(1);
+        expect(mockLatestPopoverProps?.isVisible).toBe(true);
+        expect(mockLatestPopoverProps?.wasOpenedViaKeyboard).toBe(true);
+
+        fireEvent.press(screen.getByText('Option 1'));
+
+        expect(mockLatestPopoverProps?.isVisible).toBe(false);
+        expect(mockLatestPopoverProps?.wasOpenedViaKeyboard).toBe(false);
+        expect(mockClearKeyboardInteractionFlag).toHaveBeenCalledTimes(1);
+    });
+
+    it('focuses the single-button anchor in onModalHide', () => {
+        render(
+            <ButtonWithDropdownMenu
+                options={options}
+                onPress={jest.fn()}
+                isSplitButton={false}
+            />,
+        );
+
+        expect(typeof mockLatestPopoverProps?.onModalHide).toBe('function');
+        expect(mockLastButtonFocusSpy).toBeDefined();
+
+        mockLatestPopoverProps?.onModalHide?.();
+
+        expect(mockLastButtonFocusSpy).toHaveBeenCalledTimes(1);
+    });
+
+    it('focuses the split-button anchor in onModalHide', () => {
+        render(
+            <ButtonWithDropdownMenu
+                options={options}
+                onPress={jest.fn()}
+            />,
+        );
+
+        expect(typeof mockLatestPopoverProps?.onModalHide).toBe('function');
+        expect(mockLastButtonFocusSpy).toBeDefined();
+
+        mockLatestPopoverProps?.onModalHide?.();
+
+        expect(mockLastButtonFocusSpy).toHaveBeenCalledTimes(1);
+    });
+});
diff --git a/tests/ui/components/PopoverMenu.tsx b/tests/ui/components/PopoverMenu.tsx
index cec79064953d..06af61a4da72 100644
--- a/tests/ui/components/PopoverMenu.tsx
+++ b/tests/ui/components/PopoverMenu.tsx
@@ -1,9 +1,48 @@
-import {fireEvent, render, screen, waitFor} from '@testing-library/react-native';
+import {act, fireEvent, render, screen, waitFor} from '@testing-library/react-native';
 import React from 'react';
 import type {PropsWithChildren} from 'react';
 import type {GestureResponderEvent, View} from 'react-native';
 import type {PopoverMenuItem} from '@components/PopoverMenu';
-import PopoverMenu, {buildKeyPathFromIndexPath, getItemKey, resolveIndexPathByKeyPath} from '@components/PopoverMenu';
+import PopoverMenu from '@components/PopoverMenu';
+import {buildKeyPathFromIndexPath, getInitialFocusTargetFromContainer, getItemKey, resolveIndexPathByKeyPath} from '@components/PopoverMenuUtils';
+import type FocusUtilsModule from '@libs/focusUtils/types';
+import CONST from '@src/CONST';
+
+jest.mock('@libs/Log');
+jest.mock('@expensify/react-native-hybrid-app', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: {
+        isHybridApp: () => false,
+    },
+}));
+
+jest.mock('@libs/focusUtils', () => {
+    const webFocusUtils = jest.requireActual<{default: FocusUtilsModule}>('../../../src/libs/focusUtils/index.web.ts');
+    return webFocusUtils;
+});
+
+const mockRegisteredKeyboardShortcuts = new Map<string, (event?: KeyboardEvent) => void>();
+let latestPopoverWithMeasuredContentProps: Record<string, unknown> | undefined;
+
+jest.mock('@hooks/useKeyboardShortcut', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: (shortcut: {shortcutKey: string}, callback: (event?: KeyboardEvent) => void, config?: {isActive?: boolean}) => {
+        if (config?.isActive === false) {
+            return;
+        }
+        mockRegisteredKeyboardShortcuts.set(shortcut.shortcutKey, callback);
+    },
+}));
+
+function triggerShortcut(shortcutKey: string, event?: KeyboardEvent) {
+    const callback = mockRegisteredKeyboardShortcuts.get(shortcutKey);
+    if (!callback) {
+        throw new Error(`Shortcut callback not registered for key: ${shortcutKey}`);
+    }
+    callback(event);
+}
 
 describe('PopoverMenu utils', () => {
     const menuItems: PopoverMenuItem[] = [
@@ -138,11 +177,153 @@ describe('PopoverMenu utils', () => {
     });
 });
 
+describe('PopoverMenu initialFocus role/query behavior', () => {
+    afterEach(() => {
+        document.body.innerHTML = '';
+    });
+
+    it('returns first item when role menuitem is present', () => {
+        const container = document.createElement('div');
+        const item1 = document.createElement('div');
+        item1.setAttribute('role', 'menuitem');
+        item1.tabIndex = 0;
+        item1.textContent = 'Settings';
+        const item2 = document.createElement('div');
+        item2.setAttribute('role', 'menuitem');
+        item2.tabIndex = 0;
+        item2.textContent = 'Sign out';
+
+        container.appendChild(item1);
+        container.appendChild(item2);
+        document.body.appendChild(container);
+
+        expect(getInitialFocusTargetFromContainer(container)).toBe(item1);
+    });
+
+    it('returns false when container is empty', () => {
+        const container = document.createElement('div');
+        document.body.appendChild(container);
+
+        expect(getInitialFocusTargetFromContainer(container)).toBe(false);
+    });
+
+    it('returns first actionable candidate for mixed roles', () => {
+        const container = document.createElement('div');
+        const roles = ['link', 'tab', 'button', 'option'];
+        for (const role of roles) {
+            const item = document.createElement('div');
+            item.setAttribute('role', role);
+            if (role === 'button') {
+                item.tabIndex = 0;
+            }
+            container.appendChild(item);
+        }
+        document.body.appendChild(container);
+
+        const firstActionable = container.querySelector('[role="button"]');
+        expect(getInitialFocusTargetFromContainer(container)).toBe(firstActionable);
+    });
+
+    it('skips disabled, aria-disabled, inert and tabIndex=-1 candidates', () => {
+        const container = document.createElement('div');
+
+        const disabled = document.createElement('div');
+        disabled.setAttribute('role', 'button');
+        disabled.setAttribute('disabled', '');
+
+        const ariaDisabled = document.createElement('div');
+        ariaDisabled.setAttribute('role', 'button');
+        ariaDisabled.setAttribute('aria-disabled', 'true');
+
+        const inertParent = document.createElement('div');
+        inertParent.setAttribute('inert', '');
+        const inertChild = document.createElement('div');
+        inertChild.setAttribute('role', 'button');
+        inertParent.appendChild(inertChild);
+
+        const nonFocusable = document.createElement('div');
+        nonFocusable.setAttribute('role', 'button');
+        nonFocusable.tabIndex = -1;
+
+        const actionable = document.createElement('div');
+        actionable.setAttribute('role', 'button');
+        actionable.tabIndex = 0;
+
+        container.appendChild(disabled);
+        container.appendChild(ariaDisabled);
+        container.appendChild(inertParent);
+        container.appendChild(nonFocusable);
+        container.appendChild(actionable);
+        document.body.appendChild(container);
+
+        expect(getInitialFocusTargetFromContainer(container)).toBe(actionable);
+    });
+
+    it('skips a candidate that is itself inert even when otherwise actionable', () => {
+        const container = document.createElement('div');
+
+        const selfInert = document.createElement('div');
+        selfInert.setAttribute('role', 'button');
+        selfInert.setAttribute('inert', '');
+        selfInert.tabIndex = 0;
+
+        const actionable = document.createElement('div');
+        actionable.setAttribute('role', 'button');
+        actionable.tabIndex = 0;
+
+        container.appendChild(selfInert);
+        container.appendChild(actionable);
+        document.body.appendChild(container);
+
+        expect(getInitialFocusTargetFromContainer(container)).toBe(actionable);
+    });
+
+    it('skips aria-disabled menuitems even when they are tabbable', () => {
+        const container = document.createElement('div');
+
+        const ariaDisabledMenuItem = document.createElement('div');
+        ariaDisabledMenuItem.setAttribute('role', 'menuitem');
+        ariaDisabledMenuItem.setAttribute('aria-disabled', 'true');
+        ariaDisabledMenuItem.tabIndex = 0;
+
+        const actionable = document.createElement('div');
+        actionable.setAttribute('role', 'menuitem');
+        actionable.tabIndex = 0;
+
+        container.appendChild(ariaDisabledMenuItem);
+        container.appendChild(actionable);
+        document.body.appendChild(container);
+
+        expect(getInitialFocusTargetFromContainer(container)).toBe(actionable);
+    });
+
+    it('skips wrong-role candidates even when they are tabbable', () => {
+        const container = document.createElement('div');
+
+        const wrongRole = document.createElement('div');
+        wrongRole.setAttribute('role', 'link');
+        wrongRole.tabIndex = 0;
+
+        const actionable = document.createElement('div');
+        actionable.setAttribute('role', 'button');
+        actionable.tabIndex = 0;
+
+        container.appendChild(wrongRole);
+        container.appendChild(actionable);
+        document.body.appendChild(container);
+
+        expect(getInitialFocusTargetFromContainer(container)).toBe(actionable);
+    });
+});
+
 jest.mock('@components/PopoverWithMeasuredContent', () => {
     return {
         // eslint-disable-next-line @typescript-eslint/naming-convention
         __esModule: true,
-        default: (props: PropsWithChildren<Record<string, unknown>>) => props.children,
+        default: (props: PropsWithChildren<Record<string, unknown>>) => {
+            latestPopoverWithMeasuredContentProps = props;
+            return props.children;
+        },
     };
 });
 
@@ -153,11 +334,13 @@ jest.mock('@components/FocusableMenuItem', () => {
     return {
         // eslint-disable-next-line @typescript-eslint/naming-convention
         __esModule: true,
-        default: (props: {title: string; pressableTestID?: string; onPress?: (event: GestureResponderEvent) => void}) => (
+        default: (props: {title: string; pressableTestID?: string; onPress?: (event: GestureResponderEvent) => void; onFocus?: () => void; focused?: boolean}) => (
             <Pressable
                 testID={props.pressableTestID}
                 onPress={props.onPress}
+                onFocus={props.onFocus}
                 accessibilityLabel="Pressable"
+                accessibilityState={{selected: !!props.focused}}
             >
                 <Text>{props.title}</Text>
             </Pressable>
@@ -165,6 +348,11 @@ jest.mock('@components/FocusableMenuItem', () => {
     };
 });
 
+afterEach(() => {
+    mockRegisteredKeyboardShortcuts.clear();
+    latestPopoverWithMeasuredContentProps = undefined;
+});
+
 describe('PopoverMenu integration — submenu open/close behaviors', () => {
     const baseMenu: PopoverMenuItem[] = [
         {text: 'Item A', key: 'A'},
@@ -327,3 +515,73 @@ describe('PopoverMenu integration — submenu open/close behaviors', () => {
         });
     });
 });
+
+describe('PopoverMenu prop forwarding', () => {
+    const anchorRef = React.createRef<View>();
+    const anchorPosition = {horizontal: 0, vertical: 0};
+
+    it('forwards shouldHandleNavigationBack to PopoverWithMeasuredContent', () => {
+        // Given a visible PopoverMenu configured to handle navigation back
+        render(
+            <PopoverMenu
+                isVisible
+                menuItems={[{text: 'Action'}]}
+                onClose={() => {}}
+                anchorPosition={anchorPosition}
+                anchorRef={anchorRef}
+                shouldHandleNavigationBack
+            />,
+        );
+
+        // When the PopoverMenu renders
+
+        // Then PopoverWithMeasuredContent should receive the back-navigation flag
+        expect(latestPopoverWithMeasuredContentProps?.shouldHandleNavigationBack).toBe(true);
+    });
+});
+
+describe('PopoverMenu keyboard focusedIndex synchronization', () => {
+    const anchorRef = React.createRef<View>();
+    const anchorPosition = {horizontal: 0, vertical: 0};
+
+    afterEach(() => {
+        jest.clearAllMocks();
+    });
+
+    it('syncs focusedIndex via onFocus and Enter activates the auto-focused row', () => {
+        const onItemSelected = jest.fn();
+        const menuItems: PopoverMenuItem[] = [{text: 'First action'}, {text: 'Second action'}];
+
+        render(
+            <PopoverMenu
+                isVisible
+                menuItems={menuItems}
+                onClose={() => {}}
+                onItemSelected={onItemSelected}
+                anchorPosition={anchorPosition}
+                anchorRef={anchorRef}
+                wasOpenedViaKeyboard
+            />,
+        );
+
+        // Before focus sync, Enter is a no-op because focusedIndex is -1.
+        act(() => {
+            triggerShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey);
+        });
+        expect(onItemSelected).not.toHaveBeenCalled();
+
+        // This mirrors the effect of keyboard initialFocus focusing the first actionable row.
+        // Even if focus is applied redundantly (FocusTrap + useSyncFocus), the onFocus-driven
+        // focusedIndex update is idempotent and harmless.
+        fireEvent(screen.getByTestId('PopoverMenuItem-First action'), 'focus');
+        const firstActionItem = screen.getByTestId('PopoverMenuItem-First action');
+        const accessibilityState = firstActionItem.props.accessibilityState as {selected?: boolean} | undefined;
+        expect(accessibilityState?.selected).toBe(true);
+
+        act(() => {
+            triggerShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey);
+        });
+
+        expect(onItemSelected).toHaveBeenCalledWith(expect.objectContaining({text: 'First action'}), 0, undefined);
+    });
+});
diff --git a/tests/ui/components/ScreenWrapperRouteBoundaryTest.tsx b/tests/ui/components/ScreenWrapperRouteBoundaryTest.tsx
new file mode 100644
index 000000000000..f870f335f04a
--- /dev/null
+++ b/tests/ui/components/ScreenWrapperRouteBoundaryTest.tsx
@@ -0,0 +1,151 @@
+import * as NativeNavigation from '@react-navigation/native';
+import {act, render, screen} from '@testing-library/react-native';
+import React from 'react';
+import {View} from 'react-native';
+import Onyx from 'react-native-onyx';
+import {LocaleContextProvider} from '@components/LocaleContextProvider';
+import OnyxListItemProvider from '@components/OnyxListItemProvider';
+import ScreenWrapper from '@components/ScreenWrapper';
+import {NAVIGATION_FOCUS_ROUTE_DATASET_KEY} from '@libs/NavigationFocusManager/constants';
+import ONYXKEYS from '@src/ONYXKEYS';
+import waitForBatchedUpdatesWithAct from '../../utils/waitForBatchedUpdatesWithAct';
+
+jest.mock('@libs/Log');
+jest.mock('@expensify/react-native-hybrid-app', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: {
+        isHybridApp: () => false,
+    },
+}));
+jest.mock('@react-navigation/native');
+jest.mock('@components/LocaleContextProvider', () => {
+    const ReactModule = jest.requireActual<typeof React>('react');
+
+    return {
+        LocaleContext: ReactModule.createContext({
+            translate: () => '',
+            numberFormat: () => '',
+            getLocalDateFromDatetime: () => new Date(),
+            datetimeToRelative: () => '',
+            datetimeToCalendarTime: () => '',
+            formatPhoneNumber: () => '',
+            toLocaleDigit: () => '',
+            toLocaleOrdinal: () => '',
+            fromLocaleDigit: () => '',
+            localeCompare: () => 0,
+            formatTravelDate: () => '',
+            preferredLocale: undefined,
+        }),
+        LocaleContextProvider: ({children}: {children: React.ReactNode}) => children,
+    };
+});
+
+// Force the real web implementation so this test covers the same route-marker path
+// used by desktop web and mWeb rather than Jest's default no-op implementation.
+jest.mock('@components/FocusTrap/FocusTrapForScreen', () => {
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const webFocusTrapForScreen = jest.requireActual<typeof import('@components/FocusTrap/FocusTrapForScreen/index.web')>('@components/FocusTrap/FocusTrapForScreen/index.web');
+
+    return webFocusTrapForScreen;
+});
+
+jest.mock('focus-trap-react', () => {
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const ReactModule = jest.requireActual<typeof import('react')>('react');
+
+    return {
+        FocusTrap: ({children}: {children: React.ReactNode}) => ReactModule.createElement(ReactModule.Fragment, null, children),
+    };
+});
+
+const wrapper = ({children}: {children: React.ReactNode}) => (
+    <OnyxListItemProvider>
+        <LocaleContextProvider>{children}</LocaleContextProvider>
+    </OnyxListItemProvider>
+);
+
+function getDataSet(nodeProps: unknown): Record<string, string> | undefined {
+    if (!nodeProps || typeof nodeProps !== 'object' || !('dataSet' in nodeProps)) {
+        return undefined;
+    }
+
+    const {dataSet} = nodeProps as {dataSet?: unknown};
+    if (!dataSet || typeof dataSet !== 'object') {
+        return undefined;
+    }
+
+    return dataSet as Record<string, string>;
+}
+
+function countRouteBoundaryNodes(tree: unknown, routeKey: string): number {
+    if (!tree) {
+        return 0;
+    }
+
+    if (Array.isArray(tree)) {
+        let total = 0;
+
+        for (const child of tree) {
+            total += countRouteBoundaryNodes(child, routeKey);
+        }
+
+        return total;
+    }
+
+    if (typeof tree !== 'object') {
+        return 0;
+    }
+
+    const node = tree as {props?: unknown; children?: unknown};
+    const childNodes: unknown[] = Array.isArray(node.children) ? node.children : [];
+    const isRouteBoundary = getDataSet(node.props)?.[NAVIGATION_FOCUS_ROUTE_DATASET_KEY] === routeKey ? 1 : 0;
+    let childRouteBoundaryCount = 0;
+
+    for (const child of childNodes) {
+        childRouteBoundaryCount += countRouteBoundaryNodes(child, routeKey);
+    }
+
+    return isRouteBoundary + childRouteBoundaryCount;
+}
+
+describe('ScreenWrapper route boundary forwarding', () => {
+    beforeAll(() => {
+        Onyx.init({
+            keys: ONYXKEYS,
+        });
+    });
+
+    beforeEach(() => {
+        jest.clearAllMocks();
+        jest.spyOn(NativeNavigation, 'useRoute').mockReturnValue({key: 'workspace-overview-route', name: 'Report'} as never);
+        jest.spyOn(NativeNavigation, 'useIsFocused').mockReturnValue(true);
+    });
+
+    afterEach(async () => {
+        await act(async () => {
+            await Onyx.clear();
+        });
+        await waitForBatchedUpdatesWithAct();
+    });
+
+    it('should keep the current route marker inside the web FocusTrap wrapper without widening the ScreenWrapper host', async () => {
+        // Given: ScreenWrapper is rendered through the real web FocusTrapForScreen path
+        const {toJSON} = render(
+            <ScreenWrapper testID="screen-wrapper">
+                <View testID="screen-content" />
+            </ScreenWrapper>,
+            {wrapper},
+        );
+        await waitForBatchedUpdatesWithAct();
+
+        // When: The ScreenWrapperContainer host is resolved by testID
+        const screenWrapperHost = screen.getByTestId('screen-wrapper');
+
+        // Then: ScreenWrapperContainer should remain free of the web-only marker
+        // while the rendered tree still contains a stamped route boundary for
+        // NavigationFocusManager ownership resolution.
+        expect(screenWrapperHost.props.dataSet).toBeUndefined();
+        expect(countRouteBoundaryNodes(toJSON(), 'workspace-overview-route')).toBe(1);
+    });
+});
diff --git a/tests/ui/components/ThreeDotsMenuFocusCoverageTest.tsx b/tests/ui/components/ThreeDotsMenuFocusCoverageTest.tsx
new file mode 100644
index 000000000000..38b355b3bdda
--- /dev/null
+++ b/tests/ui/components/ThreeDotsMenuFocusCoverageTest.tsx
@@ -0,0 +1,207 @@
+/* eslint-disable @typescript-eslint/naming-convention */
+import {act, fireEvent, render, screen} from '@testing-library/react-native';
+import React from 'react';
+import type {PropsWithChildren} from 'react';
+// Import after mocks
+// eslint-disable-next-line import/first
+import ThreeDotsMenu from '@components/ThreeDotsMenu';
+
+type CapturedPopoverProps = {
+    isVisible?: boolean;
+    wasOpenedViaKeyboard?: boolean;
+    onClose?: () => void;
+};
+
+type CapturedTriggerProps = {
+    onPress?: () => void;
+    onKeyDown?: (event: React.KeyboardEvent) => void;
+    children?: React.ReactNode;
+};
+
+let mockLatestPopoverProps: CapturedPopoverProps | undefined;
+let mockLatestTriggerProps: CapturedTriggerProps | undefined;
+const mockTriggerBlurSpy = jest.fn();
+
+const mockWasRecentKeyboardInteraction = jest.fn<boolean, []>();
+const mockClearKeyboardInteractionFlag = jest.fn<void, []>();
+
+jest.mock('@components/PopoverMenu', () => {
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const ReactModule = jest.requireActual<typeof import('react')>('react');
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const {View} = jest.requireActual<typeof import('react-native')>('react-native');
+
+    return {
+        __esModule: true,
+        default: (props: PropsWithChildren<CapturedPopoverProps>) => {
+            mockLatestPopoverProps = props;
+            return ReactModule.createElement(View, {testID: 'mock-popover-menu'}, props.children);
+        },
+    };
+});
+
+jest.mock('@components/Pressable/PressableWithoutFeedback', () => {
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const ReactModule = jest.requireActual<typeof import('react')>('react');
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const {Pressable} = jest.requireActual<typeof import('react-native')>('react-native');
+
+    const MockPressableWithoutFeedback = ReactModule.forwardRef((props: CapturedTriggerProps, ref: React.Ref<{blur: () => void}>) => {
+        mockLatestTriggerProps = props;
+
+        ReactModule.useImperativeHandle(ref, () => ({blur: mockTriggerBlurSpy}), []);
+
+        return (
+            <Pressable
+                testID="three-dots-trigger"
+                onPress={props.onPress}
+                accessibilityRole="button"
+            >
+                {props.children}
+            </Pressable>
+        );
+    });
+
+    MockPressableWithoutFeedback.displayName = 'MockPressableWithoutFeedback';
+
+    return {
+        __esModule: true,
+        default: MockPressableWithoutFeedback,
+    };
+});
+
+jest.mock('@components/Tooltip/EducationalTooltip', () => ({
+    __esModule: true,
+    default: ({children}: PropsWithChildren) => children,
+}));
+
+jest.mock('@components/Tooltip/PopoverAnchorTooltip', () => ({
+    __esModule: true,
+    default: ({children}: PropsWithChildren) => children,
+}));
+
+jest.mock('@components/Icon', () => ({
+    __esModule: true,
+    default: () => null,
+}));
+
+jest.mock('@components/Button/utils', () => ({
+    getButtonRole: () => 'button',
+}));
+
+jest.mock('@hooks/useLazyAsset', () => ({
+    useMemoizedLazyExpensifyIcons: () => ({ThreeDots: () => null}),
+}));
+
+jest.mock('@hooks/useLocalize', () => ({
+    __esModule: true,
+    default: () => ({translate: (value: string) => value}),
+}));
+
+jest.mock('@hooks/useOnyx', () => ({
+    __esModule: true,
+    default: () => [null],
+}));
+
+jest.mock('@hooks/usePopoverPosition', () => ({
+    __esModule: true,
+    default: () => ({calculatePopoverPosition: jest.fn()}),
+}));
+
+jest.mock('@hooks/useTheme', () => ({
+    __esModule: true,
+    default: () => ({success: 'green', icon: 'gray'}),
+}));
+
+jest.mock('@hooks/useThemeStyles', () => ({
+    __esModule: true,
+    default: () => ({
+        touchableButtonImage: {},
+        mh4: {},
+        pv2: {},
+        productTrainingTooltipWrapper: {},
+    }),
+}));
+
+jest.mock('@hooks/useWindowDimensions', () => ({
+    __esModule: true,
+    default: () => ({windowWidth: 1024, windowHeight: 768}),
+}));
+
+jest.mock('@libs/Browser', () => ({
+    isMobile: () => false,
+}));
+
+jest.mock('@libs/NavigationFocusManager', () => ({
+    __esModule: true,
+    default: {
+        wasRecentKeyboardInteraction: () => mockWasRecentKeyboardInteraction(),
+        clearKeyboardInteractionFlag: () => mockClearKeyboardInteractionFlag(),
+    },
+}));
+
+describe('ThreeDotsMenu focus coverage', () => {
+    const menuItems = [{text: 'First action'}];
+    const anchorPosition = {horizontal: 0, vertical: 0};
+
+    beforeEach(() => {
+        mockLatestPopoverProps = undefined;
+        mockLatestTriggerProps = undefined;
+        jest.clearAllMocks();
+        mockWasRecentKeyboardInteraction.mockReturnValue(false);
+    });
+
+    it('captures keyboard open state and resets it when the menu closes', () => {
+        mockWasRecentKeyboardInteraction.mockReturnValue(true);
+
+        render(
+            <ThreeDotsMenu
+                menuItems={menuItems}
+                anchorPosition={anchorPosition}
+            />,
+        );
+
+        expect(mockLatestPopoverProps?.isVisible).toBe(false);
+
+        fireEvent.press(screen.getByTestId('three-dots-trigger'));
+
+        expect(mockTriggerBlurSpy).toHaveBeenCalledTimes(1);
+        expect(mockWasRecentKeyboardInteraction).toHaveBeenCalledTimes(1);
+        expect(mockClearKeyboardInteractionFlag).toHaveBeenCalledTimes(1);
+        expect(mockLatestPopoverProps?.isVisible).toBe(true);
+        expect(mockLatestPopoverProps?.wasOpenedViaKeyboard).toBe(true);
+
+        act(() => {
+            mockLatestPopoverProps?.onClose?.();
+        });
+
+        expect(mockLatestPopoverProps?.isVisible).toBe(false);
+        expect(mockLatestPopoverProps?.wasOpenedViaKeyboard).toBe(false);
+    });
+
+    it('intercepts nested Enter key presses and opens the menu', () => {
+        render(
+            <ThreeDotsMenu
+                menuItems={menuItems}
+                anchorPosition={anchorPosition}
+                isNested
+            />,
+        );
+
+        const stopPropagation = jest.fn();
+        const preventDefault = jest.fn();
+        const event = {
+            key: 'Enter',
+            stopPropagation,
+            preventDefault,
+        } as unknown as React.KeyboardEvent;
+
+        act(() => {
+            mockLatestTriggerProps?.onKeyDown?.(event);
+        });
+
+        expect(stopPropagation).toHaveBeenCalledTimes(1);
+        expect(preventDefault).toHaveBeenCalledTimes(1);
+        expect(mockLatestPopoverProps?.isVisible).toBe(true);
+    });
+});
diff --git a/tests/unit/MenuItemInteractivePropsTest.tsx b/tests/unit/MenuItemInteractivePropsTest.tsx
new file mode 100644
index 000000000000..ebc5cb8069a0
--- /dev/null
+++ b/tests/unit/MenuItemInteractivePropsTest.tsx
@@ -0,0 +1,249 @@
+/**
+ * Unit Tests for MenuItem interactive={false} Fix - Issue #76921
+ *
+ * Tests the fix for MenuItem with interactive={false} inside wrapper Pressables.
+ *
+ * Problem (pre-fix):
+ * - ApprovalWorkflowSection wraps MenuItems in PressableWithoutFeedback
+ * - Inner MenuItems had onPress handlers that claimed responder status
+ * - Clicks on inner MenuItem text didn't trigger outer wrapper's onPress
+ *
+ * Solution (post-fix):
+ * - MenuItem with interactive={false} passes onPress={undefined} to inner Pressable
+ * - Combined with role={undefined} and tabIndex={-1}
+ * - Accessibility stays caller-controlled through shouldBeAccessible
+ * - Inner Pressable doesn't participate in responder negotiation
+ * - Events bubble to outer wrapper correctly
+ *
+ * Test Strategy:
+ * - Unit tests verify the correct props are rendered
+ * - Actual responder behavior requires browser testing (Playwright)
+ *
+ * Related files:
+ * - src/components/MenuItem.tsx (lines 691-703, 756-759)
+ * - src/components/ApprovalWorkflowSection.tsx
+ * - src/libs/NavigationFocusManager.ts
+ */
+import {render, screen} from '@testing-library/react-native';
+import React from 'react';
+import MenuItem from '@components/MenuItem';
+import OnyxListItemProvider from '@components/OnyxListItemProvider';
+import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
+
+jest.mock('@libs/Log');
+jest.mock('@expensify/react-native-hybrid-app', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: {
+        isHybridApp: () => false,
+    },
+}));
+jest.mock('@userActions/Session', () => ({
+    callFunctionIfActionIsAllowed: (callback: unknown) => callback,
+}));
+
+// Mock hooks and dependencies
+jest.mock('@hooks/useLocalize', () =>
+    jest.fn(() => ({
+        translate: jest.fn((key: string) => key),
+    })),
+);
+
+jest.mock('@hooks/useResponsiveLayout', () =>
+    jest.fn(() => ({
+        shouldUseNarrowLayout: false,
+    })),
+);
+
+// Mock Expensify icons
+jest.mock('@hooks/useLazyAsset', () => ({
+    useMemoizedLazyExpensifyIcons: jest.fn(() => ({
+        ArrowRight: () => null,
+        FallbackAvatar: () => null,
+    })),
+}));
+
+describe('MenuItem interactive prop behavior - Issue #76921', () => {
+    const renderWithProvider = (component: React.ReactElement) => {
+        return render(<OnyxListItemProvider>{component}</OnyxListItemProvider>);
+    };
+
+    beforeEach(() => {
+        jest.clearAllMocks();
+    });
+
+    describe('interactive={false} props', () => {
+        /**
+         * When interactive={false}, MenuItem should render with:
+         * - accessible remains caller-controlled
+         * - role={undefined} - no menuitem role (critical for .closest() selector)
+         * - tabIndex={-1} - not keyboard focusable
+         * - onPress={undefined} - doesn't claim responder status
+         */
+
+        it('should preserve accessible={true} by default when interactive={false}', () => {
+            renderWithProvider(
+                <MenuItem
+                    title="Display Only Item"
+                    interactive={false}
+                    pressableTestID="menu-item-non-interactive"
+                />,
+            );
+
+            const menuItem = screen.getByTestId('menu-item-non-interactive');
+
+            // Display-only content can still be readable to assistive tech unless the caller opts out.
+            expect(menuItem.props.accessible).toBe(true);
+            // onPress must be omitted so the outer wrapper can handle the interaction
+            expect(menuItem.props.onPress).toBeUndefined();
+        });
+
+        it('should respect explicit shouldBeAccessible={false} when interactive={false}', () => {
+            renderWithProvider(
+                <MenuItem
+                    title="Approval Workflow Inner Item"
+                    interactive={false}
+                    shouldBeAccessible={false}
+                    pressableTestID="menu-item-explicitly-hidden"
+                />,
+            );
+
+            const menuItem = screen.getByTestId('menu-item-explicitly-hidden');
+
+            expect(menuItem.props.accessible).toBe(false);
+            expect(menuItem.props.onPress).toBeUndefined();
+        });
+
+        it('should NOT have menuitem role when interactive={false}', () => {
+            renderWithProvider(
+                <MenuItem
+                    title="Display Only Item"
+                    interactive={false}
+                    pressableTestID="menu-item-no-role"
+                />,
+            );
+
+            const menuItem = screen.getByTestId('menu-item-no-role');
+
+            // role should be undefined, NOT "menuitem"
+            // This is critical for NavigationFocusManager's .closest() selector
+            // to skip this element and find the outer wrapper
+            expect(menuItem.props.accessibilityRole).toBeUndefined();
+        });
+
+        it('should set tabIndex={-1} when interactive={false}', () => {
+            renderWithProvider(
+                <MenuItem
+                    title="Non-focusable Item"
+                    interactive={false}
+                    pressableTestID="menu-item-non-focusable"
+                />,
+            );
+
+            const menuItem = screen.getByTestId('menu-item-non-focusable');
+
+            // tabIndex={-1} ensures the element is not keyboard focusable and won't match
+            // NavigationFocusManager's selector: [tabindex]:not([tabindex="-1"])
+            expect(menuItem.props.tabIndex).toBe(-1);
+        });
+    });
+
+    describe('interactive={true} (default) props', () => {
+        /**
+         * When interactive={true} (default), MenuItem should render with:
+         * - accessible={true} - announced as interactive element
+         * - role="menuitem" - proper ARIA role (via role prop, not accessibilityRole)
+         * - tabIndex={0} - keyboard focusable
+         * - onPress={handler} - claims responder status
+         */
+
+        it('should have role prop set when interactive={true}', () => {
+            renderWithProvider(
+                <MenuItem
+                    title="Clickable Item"
+                    interactive
+                    pressableTestID="menu-item-with-role"
+                />,
+            );
+
+            const menuItem = screen.getByTestId('menu-item-with-role');
+
+            // In React Native Web, role is passed as the `role` prop
+            // The key test is that it's NOT undefined (unlike interactive={false})
+            // Note: React Native Testing Library may render this differently than web
+            const hasRole = menuItem.props.role !== undefined || menuItem.props.accessibilityRole !== undefined;
+            expect(hasRole || menuItem.props.accessible).toBe(true);
+        });
+
+        it('should default to interactive={true}', () => {
+            renderWithProvider(
+                <MenuItem
+                    title="Default Interactive"
+                    pressableTestID="menu-item-default"
+                />,
+            );
+
+            const menuItem = screen.getByTestId('menu-item-default');
+
+            // Default behavior should be interactive (accessible=true is the key indicator)
+            expect(menuItem.props.accessible).toBe(true);
+        });
+    });
+
+    describe('Nested pressable structure for ApprovalWorkflowSection pattern', () => {
+        /**
+         * ApprovalWorkflowSection uses this pattern:
+         * <PressableWithoutFeedback role="button" onPress={navigate}>
+         *     <MenuItem interactive={false} shouldBeAccessible={false} /> <!-- display-only -->
+         *     <MenuItem interactive={false} shouldBeAccessible={false} /> <!-- display-only -->
+         * </PressableWithoutFeedback>
+         *
+         * The fix ensures:
+         * 1. Inner MenuItems don't claim responder status (onPress={undefined})
+         * 2. Inner MenuItems don't have role="menuitem" (skipped by .closest())
+         * 3. Outer wrapper has role="button" (captured by .closest())
+         */
+
+        it('should allow outer wrapper to be found by NavigationFocusManager selector', () => {
+            /**
+             * NavigationFocusManager uses this selector to find interactive elements:
+             * 'button, a, [role="menuitem"], [role="button"], [tabindex]:not([tabindex="-1"])'
+             *
+             * With the fix:
+             * - Inner MenuItem: no role, tabindex="-1" → NOT matched
+             * - Outer wrapper: role="button" → MATCHED
+             *
+             * This test verifies the props that enable this behavior.
+             */
+            renderWithProvider(
+                <PressableWithoutFeedback
+                    accessibilityRole="button"
+                    accessibilityLabel="Card"
+                    onPress={() => {}}
+                    sentryLabel="MenuItemInteractivePropsTest-OuterWrapper"
+                    testID="focusable-outer"
+                >
+                    <MenuItem
+                        title="Inner Content"
+                        interactive={false}
+                        shouldBeAccessible={false}
+                        pressableTestID="non-focusable-inner"
+                    />
+                </PressableWithoutFeedback>,
+            );
+
+            const outer = screen.getByTestId('focusable-outer');
+            const inner = screen.getByTestId('non-focusable-inner');
+
+            // Outer should match [role="button"]
+            expect(outer.props.accessibilityRole).toBe('button');
+
+            // Inner should NOT match any selector:
+            // - Not a button element
+            // - No role="menuitem" or role="button"
+            // - explicit shouldBeAccessible={false} keeps it out of accessibility navigation
+            expect(inner.props.accessibilityRole).toBeUndefined();
+            expect(inner.props.accessible).toBe(false);
+        });
+    });
+});
diff --git a/tests/unit/components/ConfirmModal/ConfirmModalIntegrationTest.tsx b/tests/unit/components/ConfirmModal/ConfirmModalIntegrationTest.tsx
new file mode 100644
index 000000000000..7f669e597401
--- /dev/null
+++ b/tests/unit/components/ConfirmModal/ConfirmModalIntegrationTest.tsx
@@ -0,0 +1,198 @@
+import {render} from '@testing-library/react-native';
+import React from 'react';
+import ConfirmModal from '@components/ConfirmModal';
+import CONST from '@src/CONST';
+
+type CapturedModalProps = {
+    initialFocus?: () => HTMLElement | false;
+    onModalHide?: () => void;
+    children?: React.ReactNode;
+};
+
+let mockLatestModalProps: CapturedModalProps | undefined;
+
+const mockGetPlatform = jest.fn<string, []>();
+const mockWasRecentKeyboardInteraction = jest.fn<boolean, []>();
+const mockClearKeyboardInteractionFlag = jest.fn<void, []>();
+const mockGetCapturedAnchorElement = jest.fn<HTMLElement | null, []>();
+const mockGetInitialFocusTarget = jest.fn<HTMLElement | false, [{isOpenedViaKeyboard: boolean; containerElementRef: unknown}]>();
+const mockRestoreCapturedAnchorFocus = jest.fn<void, [HTMLElement | null]>();
+const mockShouldTryKeyboardInitialFocus = jest.fn<boolean, [boolean]>((isOpenedViaKeyboard) => isOpenedViaKeyboard);
+const mockIsWebPlatform = jest.fn<boolean, [string]>((platform) => platform === CONST.PLATFORM.WEB);
+
+jest.mock('@components/Modal', () => {
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const ReactModule = jest.requireActual<typeof import('react')>('react');
+
+    return {
+        // eslint-disable-next-line @typescript-eslint/naming-convention
+        __esModule: true,
+        default: (props: CapturedModalProps) => {
+            mockLatestModalProps = props;
+            return ReactModule.createElement('mock-modal', props, props.children);
+        },
+    };
+});
+
+jest.mock('@components/ConfirmContent', () => {
+    // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+    const ReactModule = jest.requireActual<typeof import('react')>('react');
+
+    return {
+        // eslint-disable-next-line @typescript-eslint/naming-convention
+        __esModule: true,
+        default: () => ReactModule.createElement('mock-confirm-content', null, null),
+    };
+});
+
+jest.mock('@hooks/useResponsiveLayout', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: () => ({isSmallScreenWidth: false}),
+}));
+
+jest.mock('@hooks/useThemeStyles', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: () => ({pv0: {}}),
+}));
+
+jest.mock('@libs/getPlatform', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: () => mockGetPlatform(),
+}));
+
+jest.mock('@libs/NavigationFocusManager', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: {
+        wasRecentKeyboardInteraction: () => mockWasRecentKeyboardInteraction(),
+        clearKeyboardInteractionFlag: () => mockClearKeyboardInteractionFlag(),
+        getCapturedAnchorElement: () => mockGetCapturedAnchorElement(),
+    },
+}));
+
+jest.mock('@components/ConfirmModal/focusRestore', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    getInitialFocusTarget: (params: {isOpenedViaKeyboard: boolean; containerElementRef: unknown}) => mockGetInitialFocusTarget(params),
+    restoreCapturedAnchorFocus: (element: HTMLElement | null) => mockRestoreCapturedAnchorFocus(element),
+    shouldTryKeyboardInitialFocus: (isOpenedViaKeyboard: boolean) => mockShouldTryKeyboardInitialFocus(isOpenedViaKeyboard),
+    isWebPlatform: (platform: string) => mockIsWebPlatform(platform),
+}));
+
+function renderConfirmModal(isVisible = true, onModalHide = jest.fn()) {
+    return render(
+        <ConfirmModal
+            isVisible={isVisible}
+            onConfirm={jest.fn()}
+            onModalHide={onModalHide}
+            title="Test"
+        />,
+    );
+}
+
+describe('ConfirmModal integration focus coverage', () => {
+    beforeEach(() => {
+        mockLatestModalProps = undefined;
+        jest.clearAllMocks();
+        mockGetPlatform.mockReturnValue(CONST.PLATFORM.WEB);
+        mockWasRecentKeyboardInteraction.mockReturnValue(false);
+        mockGetCapturedAnchorElement.mockReturnValue(null);
+        mockGetInitialFocusTarget.mockReturnValue(false);
+    });
+
+    it('returns false from initialFocus for mouse/touch opens', () => {
+        const {rerender} = renderConfirmModal(false);
+
+        rerender(
+            <ConfirmModal
+                isVisible
+                onConfirm={jest.fn()}
+                title="Test"
+            />,
+        );
+
+        const initialFocus = mockLatestModalProps?.initialFocus;
+        expect(typeof initialFocus).toBe('function');
+        expect(initialFocus?.()).toBe(false);
+
+        expect(mockShouldTryKeyboardInitialFocus).toHaveBeenCalledWith(false);
+        expect(mockGetPlatform).toHaveBeenCalledWith();
+        expect(mockIsWebPlatform).not.toHaveBeenCalled();
+        expect(mockGetInitialFocusTarget).not.toHaveBeenCalled();
+    });
+
+    it('captures keyboard/anchor on open, computes initial focus, and resets keyboard capture on close', () => {
+        const anchor = document.createElement('button');
+        document.body.appendChild(anchor);
+        const focusTarget = document.createElement('button');
+
+        mockWasRecentKeyboardInteraction.mockReturnValue(true);
+        mockGetCapturedAnchorElement.mockReturnValue(anchor);
+        mockGetInitialFocusTarget.mockReturnValue(focusTarget);
+
+        const {rerender} = renderConfirmModal(false);
+
+        rerender(
+            <ConfirmModal
+                isVisible
+                onConfirm={jest.fn()}
+                title="Test"
+            />,
+        );
+
+        expect(mockWasRecentKeyboardInteraction).toHaveBeenCalledTimes(1);
+        expect(mockClearKeyboardInteractionFlag).toHaveBeenCalledTimes(1);
+        expect(mockGetCapturedAnchorElement).toHaveBeenCalledTimes(1);
+
+        expect(mockLatestModalProps?.initialFocus?.()).toBe(focusTarget);
+        expect(mockShouldTryKeyboardInitialFocus).toHaveBeenCalledWith(true);
+        expect(mockGetInitialFocusTarget).toHaveBeenCalledTimes(1);
+
+        rerender(
+            <ConfirmModal
+                isVisible={false}
+                onConfirm={jest.fn()}
+                title="Test"
+            />,
+        );
+
+        rerender(
+            <ConfirmModal
+                isVisible
+                onConfirm={jest.fn()}
+                title="Test"
+            />,
+        );
+
+        expect(mockWasRecentKeyboardInteraction).toHaveBeenCalledTimes(2);
+    });
+
+    it('restores captured anchor on modal hide and clears the ref after restore', () => {
+        const onModalHide = jest.fn();
+        const anchor = document.createElement('button');
+        document.body.appendChild(anchor);
+
+        mockGetCapturedAnchorElement.mockReturnValue(anchor);
+
+        const {rerender} = renderConfirmModal(false, onModalHide);
+
+        rerender(
+            <ConfirmModal
+                isVisible
+                onConfirm={jest.fn()}
+                onModalHide={onModalHide}
+                title="Test"
+            />,
+        );
+
+        mockLatestModalProps?.onModalHide?.();
+        expect(mockRestoreCapturedAnchorFocus).toHaveBeenNthCalledWith(1, anchor);
+        expect(onModalHide).toHaveBeenCalledTimes(1);
+
+        mockLatestModalProps?.onModalHide?.();
+        expect(mockRestoreCapturedAnchorFocus).toHaveBeenNthCalledWith(2, null);
+    });
+});
diff --git a/tests/unit/components/ConfirmModal/focusRestoreTest.ts b/tests/unit/components/ConfirmModal/focusRestoreTest.ts
new file mode 100644
index 000000000000..cf0ff5528021
--- /dev/null
+++ b/tests/unit/components/ConfirmModal/focusRestoreTest.ts
@@ -0,0 +1,106 @@
+import {getInitialFocusTarget, isWebPlatform, restoreCapturedAnchorFocus, shouldTryKeyboardInitialFocus} from '@components/ConfirmModal/focusRestore/index.web';
+import CONST from '@src/CONST';
+
+describe('ConfirmModal focusRestore (web)', () => {
+    afterEach(() => {
+        document.body.innerHTML = '';
+        jest.clearAllMocks();
+    });
+
+    it('should skip initial focus for mouse/touch opens', () => {
+        const container = document.createElement('div');
+        document.body.appendChild(container);
+
+        const result = getInitialFocusTarget({
+            isOpenedViaKeyboard: false,
+            containerElementRef: container,
+        });
+
+        expect(result).toBe(false);
+    });
+
+    it('should focus the first button in the scoped container for keyboard opens', () => {
+        const container = document.createElement('div');
+        const button = document.createElement('button');
+        button.textContent = 'Confirm';
+        container.appendChild(button);
+        document.body.appendChild(container);
+
+        const result = getInitialFocusTarget({
+            isOpenedViaKeyboard: true,
+            containerElementRef: container,
+        });
+
+        expect(result).toBe(button);
+    });
+
+    it('should prefer last confirm-modal container fallback when container ref is unavailable', () => {
+        const confirmModalContainerA = document.createElement('div');
+        confirmModalContainerA.setAttribute('data-testid', 'confirm-modal-container');
+        const containerButtonA = document.createElement('button');
+        containerButtonA.textContent = 'Container A';
+        confirmModalContainerA.appendChild(containerButtonA);
+
+        const confirmModalContainerB = document.createElement('div');
+        confirmModalContainerB.setAttribute('data-testid', 'confirm-modal-container');
+        const containerButtonB = document.createElement('button');
+        containerButtonB.textContent = 'Container B';
+        confirmModalContainerB.appendChild(containerButtonB);
+
+        const dialog = document.createElement('div');
+        dialog.setAttribute('role', 'dialog');
+        const dialogButton = document.createElement('button');
+        dialogButton.textContent = 'Dialog Button';
+        dialog.appendChild(dialogButton);
+
+        document.body.appendChild(confirmModalContainerA);
+        document.body.appendChild(dialog);
+        document.body.appendChild(confirmModalContainerB);
+
+        const result = getInitialFocusTarget({
+            isOpenedViaKeyboard: true,
+            containerElementRef: null,
+        });
+
+        expect(result).toBe(containerButtonB);
+    });
+
+    it('should fall back to the last dialog if no confirm-modal container is available', () => {
+        const dialogA = document.createElement('div');
+        dialogA.setAttribute('role', 'dialog');
+        const buttonA = document.createElement('button');
+        dialogA.appendChild(buttonA);
+
+        const dialogB = document.createElement('div');
+        dialogB.setAttribute('role', 'dialog');
+        const buttonB = document.createElement('button');
+        dialogB.appendChild(buttonB);
+
+        document.body.appendChild(dialogA);
+        document.body.appendChild(dialogB);
+
+        const result = getInitialFocusTarget({
+            isOpenedViaKeyboard: true,
+            containerElementRef: null,
+        });
+
+        expect(result).toBe(buttonB);
+    });
+
+    it('should restore focus to captured anchor when it is still in DOM', () => {
+        const anchor = document.createElement('button');
+        document.body.appendChild(anchor);
+        const focusSpy = jest.spyOn(anchor, 'focus');
+
+        restoreCapturedAnchorFocus(anchor);
+
+        expect(focusSpy).toHaveBeenCalledTimes(1);
+    });
+
+    it('should expose expected platform helpers', () => {
+        expect(shouldTryKeyboardInitialFocus(true)).toBe(true);
+        expect(shouldTryKeyboardInitialFocus(false)).toBe(false);
+        expect(isWebPlatform(CONST.PLATFORM.WEB)).toBe(true);
+        expect(isWebPlatform(CONST.PLATFORM.ANDROID)).toBe(false);
+    });
+});
diff --git a/tests/unit/components/FocusTrap/FocusTrapForScreenTest.tsx b/tests/unit/components/FocusTrap/FocusTrapForScreenTest.tsx
new file mode 100644
index 000000000000..5b1c71a9ab15
--- /dev/null
+++ b/tests/unit/components/FocusTrap/FocusTrapForScreenTest.tsx
@@ -0,0 +1,724 @@
+/**
+ * P0 Unit Tests for FocusTrapForScreen - Issue #76921
+ *
+ * STATUS: IMPLEMENTED AND PASSING (2026-01-14)
+ *
+ * These tests verify the focus restoration fix for Issue #76921
+ * while ensuring no regression of Issue #46109 (blue frame on new tab).
+ *
+ * Implementation Details (Phase 2 Architecture):
+ * - `initialFocus` callback handles navigation-based focus restoration (returning to a screen)
+ * - `setReturnFocus` handles non-navigation deactivation (click outside) - returns trigger if focusable
+ * - NavigationFocusManager captures elements on pointerdown/keydown (capture phase)
+ * - FocusTrapForScreen captures focus when screen loses focus, restores when it regains focus
+ * - `wasNavigatedTo` ref prevents focus restoration on initial page load (#46109)
+ *
+ * The fix has been applied to:
+ * - `src/libs/NavigationFocusManager/index.web.ts` (web implementation)
+ * - `src/components/FocusTrap/FocusTrapForScreen/index.web.tsx`
+ * - `src/App.tsx` (initialize NavigationFocusManager)
+ *
+ * Test Categories:
+ * P0-1: Initial page load - no focus restoration (guards #46109)
+ * P0-2: Navigation back - focus restored to trigger element
+ * P0-3: Input field focus preserved during navigation
+ * P0-4: Previously focused element removed from DOM - fallback used
+ * P0-5: Element focus checks
+ */
+/* eslint-disable @typescript-eslint/naming-convention */
+import {render, screen} from '@testing-library/react-native';
+import type {ReactNode} from 'react';
+import React from 'react';
+import {View} from 'react-native';
+// ============================================================================
+// Imports (must come after mocks)
+// ============================================================================
+
+// eslint-disable-next-line import/first
+import FocusTrapForScreen from '@components/FocusTrap/FocusTrapForScreen/index.web';
+import type FocusUtilsModule from '@libs/focusUtils/types';
+import {NAVIGATION_FOCUS_ROUTE_DATASET_KEY} from '@libs/NavigationFocusManager/constants';
+import type NavigationFocusManagerModule from '@libs/NavigationFocusManager/types';
+
+// ============================================================================
+// Test-specific configurable mocks (kept inline as they need per-test values)
+// ============================================================================
+
+// Mock variables to control test behavior
+let mockIsFocused = true;
+let mockRouteName = 'TestScreen';
+let mockRouteKey: string | undefined = 'test-route';
+
+// Track focus trap callbacks for testing
+type FocusTrapCallbacks = {
+    onActivate?: () => void;
+    setReturnFocus?: ((element: HTMLElement) => HTMLElement | false) | boolean;
+    initialFocus?: (() => HTMLElement | false) | boolean;
+};
+
+let capturedFocusTrapOptions: FocusTrapCallbacks = {};
+
+// Mock @react-navigation/native - overrides global mock for configurable test values
+jest.mock('@react-navigation/native', () => ({
+    useIsFocused: () => mockIsFocused,
+    useRoute: () => ({name: mockRouteName, key: mockRouteKey}),
+    // useNavigation needed for beforeRemove listener in FocusTrapForScreen
+    useNavigation: () => ({
+        addListener: jest.fn(() => jest.fn()),
+    }),
+}));
+
+// Mock useResponsiveLayout - uses the existing mock in __mocks__ but we specify the return value
+jest.mock('@hooks/useResponsiveLayout', () => ({
+    __esModule: true,
+    default: () => ({shouldUseNarrowLayout: true}),
+}));
+
+// Mock isSidebarScreenName - simple function mock
+jest.mock('@libs/Navigation/helpers/isNavigatorName', () => ({
+    isSidebarScreenName: (name: string) => name === 'SidebarScreen',
+}));
+
+// This suite exercises web-only focus behavior.
+jest.mock('@libs/NavigationFocusManager', () => {
+    const webNavigationFocusManager = jest.requireActual<{default: NavigationFocusManagerModule}>('@libs/NavigationFocusManager/index.web');
+    return webNavigationFocusManager;
+});
+
+jest.mock('@libs/focusUtils', () => {
+    const webFocusUtils = jest.requireActual<{default: FocusUtilsModule}>('../../../../src/libs/focusUtils/index.web.ts');
+    return webFocusUtils;
+});
+
+// Mock Log to break the import chain that causes CONST-related issues
+// (NavigationFocusManager -> Log -> Console -> CONFIG -> CONST causes issues with partial mocks)
+jest.mock('@libs/Log');
+
+// Mock CONST - only the values actually used by FocusTrapForScreen
+jest.mock('@src/CONST', () => ({
+    __esModule: true,
+    default: {
+        ELEMENT_NAME: {
+            INPUT: 'INPUT',
+            TEXTAREA: 'TEXTAREA',
+        },
+        ANIMATED_TRANSITION: 300,
+    },
+}));
+
+// Mock focus-trap-react - kept inline because it needs to capture callbacks
+// for testing. The captured options are stored in `capturedFocusTrapOptions`.
+jest.mock('focus-trap-react', () => ({
+    FocusTrap: ({children, focusTrapOptions, active}: {children: ReactNode; focusTrapOptions?: FocusTrapCallbacks; active?: boolean}) => {
+        // Capture the options for testing
+        capturedFocusTrapOptions = focusTrapOptions ?? {};
+
+        return (
+            <div
+                data-testid="focus-trap-container"
+                data-active={active}
+            >
+                {children}
+            </div>
+        );
+    },
+}));
+
+// ============================================================================
+// Mocks using __mocks__ directories (Jest auto-loads these)
+// ============================================================================
+
+// Uses: src/components/FocusTrap/__mocks__/sharedTrapStack.ts
+jest.mock('@components/FocusTrap/sharedTrapStack');
+
+// Uses: src/components/FocusTrap/__mocks__/TOP_TAB_SCREENS.ts
+jest.mock('@components/FocusTrap/TOP_TAB_SCREENS');
+
+// Uses: src/components/FocusTrap/__mocks__/WIDE_LAYOUT_INACTIVE_SCREENS.ts
+jest.mock('@components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS');
+
+// ============================================================================
+// Test Helpers
+// ============================================================================
+
+/**
+ * Creates a mock DOM element with JSDOM-compatible getBoundingClientRect.
+ * Given: JSDOM doesn't layout elements, so we need to mock dimensions
+ */
+function createMockElement(tagName: string, id: string, options?: {hidden?: boolean}): HTMLElement {
+    const element = document.createElement(tagName);
+    element.id = id;
+    document.body.appendChild(element);
+
+    // Mock getBoundingClientRect since JSDOM doesn't layout elements
+    // By default, return non-zero dimensions (element is visible)
+    element.getBoundingClientRect = jest.fn(() => ({
+        width: options?.hidden ? 0 : 100,
+        height: options?.hidden ? 0 : 50,
+        top: 0,
+        left: 0,
+        bottom: options?.hidden ? 0 : 50,
+        right: options?.hidden ? 0 : 100,
+        x: 0,
+        y: 0,
+        toJSON: () => ({}),
+    }));
+
+    return element;
+}
+
+/**
+ * Check if setReturnFocus is a function (new implementation).
+ * When: The fix is applied, setReturnFocus is a function
+ * Then: Returns true
+ */
+function isSetReturnFocusFunction(): boolean {
+    return typeof capturedFocusTrapOptions.setReturnFocus === 'function';
+}
+
+/**
+ * Call setReturnFocus safely.
+ * When: setReturnFocus is a function, call it with the element
+ * Then: Return the result
+ */
+function callSetReturnFocus(element: HTMLElement): HTMLElement | false | undefined {
+    if (typeof capturedFocusTrapOptions.setReturnFocus === 'function') {
+        return capturedFocusTrapOptions.setReturnFocus(element);
+    }
+    // Current implementation returns boolean
+    return capturedFocusTrapOptions.setReturnFocus === true ? element : false;
+}
+
+/**
+ * Reset all mocks between tests.
+ * Given: Each test should start with a clean state
+ */
+function resetMocks() {
+    mockIsFocused = true;
+    mockRouteName = 'TestScreen';
+    mockRouteKey = 'test-route';
+    capturedFocusTrapOptions = {};
+
+    // Clean up DOM
+    document.body.innerHTML = '';
+
+    // Reset document.activeElement to body
+    if (document.activeElement && document.activeElement !== document.body) {
+        (document.activeElement as HTMLElement).blur();
+    }
+}
+
+function getDataSet(nodeProps: unknown): Record<string, string> | undefined {
+    if (!nodeProps || typeof nodeProps !== 'object' || !('dataSet' in nodeProps)) {
+        return undefined;
+    }
+
+    const {dataSet} = nodeProps as {dataSet?: unknown};
+    if (!dataSet || typeof dataSet !== 'object') {
+        return undefined;
+    }
+
+    return dataSet as Record<string, string>;
+}
+
+function countRouteBoundaryNodes(tree: unknown, routeKey: string): number {
+    if (!tree) {
+        return 0;
+    }
+
+    if (Array.isArray(tree)) {
+        let total = 0;
+
+        for (const child of tree) {
+            total += countRouteBoundaryNodes(child, routeKey);
+        }
+
+        return total;
+    }
+
+    if (typeof tree !== 'object') {
+        return 0;
+    }
+
+    const node = tree as {props?: unknown; children?: unknown};
+    const childNodes: unknown[] = Array.isArray(node.children) ? node.children : [];
+    const isRouteBoundary = getDataSet(node.props)?.[NAVIGATION_FOCUS_ROUTE_DATASET_KEY] === routeKey ? 1 : 0;
+    let childRouteBoundaryCount = 0;
+
+    for (const child of childNodes) {
+        childRouteBoundaryCount += countRouteBoundaryNodes(child, routeKey);
+    }
+
+    return isRouteBoundary + childRouteBoundaryCount;
+}
+
+// ============================================================================
+// Tests
+// ============================================================================
+
+describe('FocusTrapForScreen', () => {
+    beforeEach(() => {
+        // Given: A clean test environment
+        resetMocks();
+    });
+
+    afterEach(() => {
+        jest.clearAllMocks();
+    });
+
+    describe('Route boundary markers', () => {
+        it('should render a single route-boundary wrapper for the current screen', () => {
+            const {toJSON} = render(
+                <FocusTrapForScreen>
+                    <View testID="route-boundary" />
+                </FocusTrapForScreen>,
+            );
+
+            expect(countRouteBoundaryNodes(toJSON(), 'test-route')).toBe(1);
+            expect(screen.getByTestId('route-boundary').props.dataSet).toBeUndefined();
+        });
+
+        it('should preserve existing child dataset values when adding the route marker wrapper', () => {
+            const {toJSON} = render(
+                <FocusTrapForScreen>
+                    <View
+                        testID="route-boundary"
+                        dataSet={{existingValue: 'keep-me'}}
+                    />
+                </FocusTrapForScreen>,
+            );
+
+            expect(countRouteBoundaryNodes(toJSON(), 'test-route')).toBe(1);
+            expect(screen.getByTestId('route-boundary').props.dataSet).toEqual({
+                existingValue: 'keep-me',
+            });
+        });
+    });
+
+    describe('P0-1: Initial page load - no focus restoration (guards #46109)', () => {
+        it('should NOT restore focus via initialFocus on initial page load', () => {
+            // Given: Initial page load (no prior navigation, wasNavigatedTo is false)
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            // Then: initialFocus should be a function (Phase 2 implementation)
+            expect(typeof capturedFocusTrapOptions.initialFocus).toBe('function');
+
+            // When: initialFocus is called (trap activation on initial load)
+            const initialFocusFn = capturedFocusTrapOptions.initialFocus as () => HTMLElement | false;
+            const result = initialFocusFn();
+
+            // Then: Should return false (no focus restoration on initial load)
+            // because wasNavigatedTo.current is false
+            expect(result).toBe(false);
+        });
+
+        it('should return trigger element from setReturnFocus for click-outside deactivation', () => {
+            // Given: Component is rendered
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            // Then: setReturnFocus should be a function
+            expect(typeof capturedFocusTrapOptions.setReturnFocus).toBe('function');
+
+            // When: setReturnFocus is called with a focusable trigger element
+            // (this happens on click-outside deactivation)
+            const mockTriggerElement = createMockElement('button', 'trigger-button');
+            const result = callSetReturnFocus(mockTriggerElement);
+
+            // Then: Should return the trigger element (for click-outside scenarios)
+            expect(result).toBe(mockTriggerElement);
+        });
+
+        it('should allow aria-disabled trigger elements to remain restorable', () => {
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            expect(typeof capturedFocusTrapOptions.setReturnFocus).toBe('function');
+
+            const ariaDisabledTrigger = createMockElement('button', 'aria-disabled-trigger');
+            ariaDisabledTrigger.setAttribute('aria-disabled', 'true');
+
+            const result = callSetReturnFocus(ariaDisabledTrigger);
+
+            expect(result).toBe(ariaDisabledTrigger);
+        });
+    });
+
+    describe('P0-2: Navigation back - focus restored to trigger element', () => {
+        it('should restore focus to previously focused element when trap was activated via navigation', () => {
+            // Given: A button that was focused before navigation (simulates user clicking a menu item)
+            const triggerButton = createMockElement('button', 'trigger-button');
+            triggerButton.focus();
+
+            // When: Component renders (trap activates)
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            // Skip if new implementation not applied
+            if (!isSetReturnFocusFunction()) {
+                // Then: Current behavior - no focus restoration
+                expect(capturedFocusTrapOptions.setReturnFocus).toBe(false);
+                return;
+            }
+
+            // When: Trap activates while button is focused (captures it as previously focused)
+            capturedFocusTrapOptions.onActivate?.();
+
+            // And: setReturnFocus is called (trap deactivating, e.g., user clicked back)
+            const result = callSetReturnFocus(triggerButton);
+
+            // Then: Should return the previously focused element
+            expect(result).toBe(triggerButton);
+        });
+
+        it('should use triggerElement as fallback when previouslyFocusedElement is removed from DOM', () => {
+            // Given: A button that was focused and then will be removed
+            const removableButton = createMockElement('button', 'removable-button');
+            removableButton.focus();
+
+            // When: Component renders
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            // Skip if new implementation not applied
+            if (!isSetReturnFocusFunction()) {
+                expect(capturedFocusTrapOptions.setReturnFocus).toBe(false);
+                return;
+            }
+
+            // When: Trap activates while button is focused
+            capturedFocusTrapOptions.onActivate?.();
+
+            // And: The button is removed from DOM
+            removableButton.remove();
+
+            // And: setReturnFocus is called with a fallback element
+            const fallbackElement = createMockElement('button', 'fallback-button');
+            const result = callSetReturnFocus(fallbackElement);
+
+            // Then: Should return the fallback element since original is gone
+            expect(result).toBe(fallbackElement);
+        });
+    });
+
+    describe('P0-3: Input field focus preserved during navigation', () => {
+        it('should NOT blur INPUT elements on trap activation', () => {
+            // Given: An input field that is currently focused
+            const inputElement = createMockElement('input', 'test-input') as HTMLInputElement;
+            inputElement.focus();
+
+            expect(document.activeElement).toBe(inputElement);
+
+            // When: Component renders
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            const blurSpy = jest.spyOn(inputElement, 'blur');
+
+            // When: onActivate is called
+            capturedFocusTrapOptions.onActivate?.();
+
+            // Then: Input should NOT be blurred (this works in current implementation too)
+            expect(blurSpy).not.toHaveBeenCalled();
+        });
+
+        it('should NOT blur TEXTAREA elements on trap activation', () => {
+            // Given: A textarea that is currently focused
+            const textareaElement = createMockElement('textarea', 'test-textarea') as HTMLTextAreaElement;
+            textareaElement.focus();
+
+            // When: Component renders
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            const blurSpy = jest.spyOn(textareaElement, 'blur');
+
+            // When: onActivate is called
+            capturedFocusTrapOptions.onActivate?.();
+
+            // Then: Textarea should NOT be blurred
+            expect(blurSpy).not.toHaveBeenCalled();
+        });
+
+        it('should blur non-input elements on trap activation', () => {
+            // Given: A button that is currently focused
+            const buttonElement = createMockElement('button', 'test-button');
+            buttonElement.focus();
+
+            // When: Component renders
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            const blurSpy = jest.spyOn(buttonElement, 'blur');
+
+            // When: onActivate is called
+            capturedFocusTrapOptions.onActivate?.();
+
+            // Then: Button SHOULD be blurred (this works in current implementation too)
+            expect(blurSpy).toHaveBeenCalled();
+        });
+    });
+
+    describe('Edge Cases', () => {
+        it('should no-op safely if route key is missing in malformed mocks', () => {
+            mockRouteKey = undefined;
+
+            expect(() =>
+                render(
+                    <FocusTrapForScreen>
+                        <div data-testid="content">Test Content</div>
+                    </FocusTrapForScreen>,
+                ),
+            ).not.toThrow();
+
+            expect(typeof capturedFocusTrapOptions.initialFocus).toBe('function');
+            const initialFocusFn = capturedFocusTrapOptions.initialFocus as () => HTMLElement | false;
+            expect(initialFocusFn()).toBe(false);
+        });
+    });
+
+    describe('P0-5: Element focus checks', () => {
+        it('should reject document.documentElement as a return focus target', () => {
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            if (!isSetReturnFocusFunction()) {
+                expect(capturedFocusTrapOptions.setReturnFocus).toBe(false);
+                return;
+            }
+
+            const result = callSetReturnFocus(document.documentElement);
+
+            expect(result).toBe(false);
+        });
+
+        it('should use fallback when previously focused element becomes hidden (display: none)', () => {
+            // Given: A button was focused before navigation
+            const hiddenButton = createMockElement('button', 'hidden-button');
+            hiddenButton.focus();
+
+            // When: Component renders
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            // Skip if new implementation not applied
+            if (!isSetReturnFocusFunction()) {
+                expect(capturedFocusTrapOptions.setReturnFocus).toBe(false);
+                return;
+            }
+
+            // When: Trap activates while button is focused
+            capturedFocusTrapOptions.onActivate?.();
+
+            // And: The button becomes hidden (update mock to return zero dimensions)
+            hiddenButton.style.display = 'none';
+            hiddenButton.getBoundingClientRect = jest.fn(() => ({
+                width: 0,
+                height: 0,
+                top: 0,
+                left: 0,
+                bottom: 0,
+                right: 0,
+                x: 0,
+                y: 0,
+                toJSON: () => ({}),
+            }));
+
+            // And: setReturnFocus is called with a fallback
+            const fallbackElement = createMockElement('button', 'fallback-button');
+            const result = callSetReturnFocus(fallbackElement);
+
+            // Then: Should return fallback since hidden element is not focusable
+            expect(result).toBe(fallbackElement);
+        });
+
+        it('should use fallback when previously focused element becomes disabled', () => {
+            // Given: A button was focused before navigation
+            const disabledButton = createMockElement('button', 'disabled-button');
+            disabledButton.focus();
+
+            // When: Component renders
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            // Skip if new implementation not applied
+            if (!isSetReturnFocusFunction()) {
+                expect(capturedFocusTrapOptions.setReturnFocus).toBe(false);
+                return;
+            }
+
+            // When: Trap activates while button is focused
+            capturedFocusTrapOptions.onActivate?.();
+
+            // And: The button becomes disabled
+            disabledButton.setAttribute('disabled', 'disabled');
+
+            // And: setReturnFocus is called with a fallback
+            const fallbackElement = createMockElement('button', 'fallback-button');
+            const result = callSetReturnFocus(fallbackElement);
+
+            // Then: Should return fallback since disabled element is not focusable
+            expect(result).toBe(fallbackElement);
+        });
+
+        it('should return an element when only width is zero', () => {
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            if (!isSetReturnFocusFunction()) {
+                expect(capturedFocusTrapOptions.setReturnFocus).toBe(false);
+                return;
+            }
+
+            const zeroWidthButton = createMockElement('button', 'zero-width-button');
+            zeroWidthButton.getBoundingClientRect = jest.fn(() => ({
+                width: 0,
+                height: 50,
+                top: 0,
+                left: 0,
+                bottom: 50,
+                right: 0,
+                x: 0,
+                y: 0,
+                toJSON: () => ({}),
+            }));
+
+            const result = callSetReturnFocus(zeroWidthButton);
+
+            expect(result).toBe(zeroWidthButton);
+        });
+
+        it('should return an element when only height is zero', () => {
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            if (!isSetReturnFocusFunction()) {
+                expect(capturedFocusTrapOptions.setReturnFocus).toBe(false);
+                return;
+            }
+
+            const zeroHeightButton = createMockElement('button', 'zero-height-button');
+            zeroHeightButton.getBoundingClientRect = jest.fn(() => ({
+                width: 100,
+                height: 0,
+                top: 0,
+                left: 0,
+                bottom: 0,
+                right: 100,
+                x: 0,
+                y: 0,
+                toJSON: () => ({}),
+            }));
+
+            const result = callSetReturnFocus(zeroHeightButton);
+
+            expect(result).toBe(zeroHeightButton);
+        });
+
+        it('should reject an element that is itself inert', () => {
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            if (!isSetReturnFocusFunction()) {
+                expect(capturedFocusTrapOptions.setReturnFocus).toBe(false);
+                return;
+            }
+
+            const inertButton = createMockElement('button', 'self-inert-button');
+            inertButton.setAttribute('inert', '');
+
+            const result = callSetReturnFocus(inertButton);
+
+            expect(result).toBe(false);
+        });
+
+        it('should use fallback when previously focused element is inside an inert container', () => {
+            // Given: A container with inert attribute
+            const inertContainer = createMockElement('div', 'inert-container');
+            inertContainer.setAttribute('inert', '');
+
+            // And: A button inside it was focused before navigation (with getBoundingClientRect mock)
+            const buttonInInert = document.createElement('button');
+            buttonInInert.id = 'button-in-inert';
+            buttonInInert.getBoundingClientRect = jest.fn(() => ({
+                width: 100,
+                height: 50,
+                top: 0,
+                left: 0,
+                bottom: 50,
+                right: 100,
+                x: 0,
+                y: 0,
+                toJSON: () => ({}),
+            }));
+            inertContainer.appendChild(buttonInInert);
+            buttonInInert.focus();
+
+            // When: Component renders
+            render(
+                <FocusTrapForScreen>
+                    <div data-testid="content">Test Content</div>
+                </FocusTrapForScreen>,
+            );
+
+            // Skip if new implementation not applied
+            if (!isSetReturnFocusFunction()) {
+                expect(capturedFocusTrapOptions.setReturnFocus).toBe(false);
+                return;
+            }
+
+            // When: Trap activates while button is focused
+            capturedFocusTrapOptions.onActivate?.();
+
+            // And: setReturnFocus is called with a fallback
+            const fallbackElement = createMockElement('button', 'fallback-button');
+            const result = callSetReturnFocus(fallbackElement);
+
+            // Then: Should return fallback since button in inert container is not focusable
+            expect(result).toBe(fallbackElement);
+        });
+    });
+});
diff --git a/tests/unit/components/Modal/ModalNavigationBackTest.tsx b/tests/unit/components/Modal/ModalNavigationBackTest.tsx
new file mode 100644
index 000000000000..d75f285269f6
--- /dev/null
+++ b/tests/unit/components/Modal/ModalNavigationBackTest.tsx
@@ -0,0 +1,183 @@
+import {act, render} from '@testing-library/react-native';
+import React from 'react';
+
+type CapturedBaseModalProps = {
+    children?: React.ReactNode;
+    onModalHide?: () => void;
+    onModalShow?: () => void;
+};
+
+type ModalHarnessProps = {
+    children?: React.ReactNode;
+    isVisible: boolean;
+    onClose?: () => void;
+    onModalHide?: () => void;
+    shouldHandleNavigationBack?: boolean;
+};
+
+// eslint-disable-next-line @typescript-eslint/no-require-imports, import/extensions
+const modalModule = require('../../../../src/components/Modal/index.tsx') as {
+    default: (props: ModalHarnessProps) => React.ReactElement<CapturedBaseModalProps>;
+};
+
+const Modal = modalModule.default;
+
+let latestBaseModalProps: CapturedBaseModalProps | undefined;
+
+const mockSetBackgroundColor = jest.fn<void, [string]>();
+const mockGetBackgroundColor = jest.fn<string | undefined, []>(() => '#ffffff');
+
+jest.mock('@hooks/useStyleUtils', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: () => ({
+        getThemeBackgroundColor: () => '#000000',
+    }),
+}));
+
+jest.mock('@hooks/useTheme', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: () => ({
+        appBG: '#ffffff',
+    }),
+}));
+
+jest.mock('@libs/StatusBar', () => ({
+    // eslint-disable-next-line @typescript-eslint/naming-convention
+    __esModule: true,
+    default: {
+        getBackgroundColor: () => mockGetBackgroundColor(),
+        setBackgroundColor: (color: string) => mockSetBackgroundColor(color),
+    },
+}));
+
+function ModalHarness({children, isVisible, onClose, onModalHide, shouldHandleNavigationBack}: ModalHarnessProps) {
+    const baseModalElement = Modal({children, isVisible, onClose, onModalHide, shouldHandleNavigationBack});
+    latestBaseModalProps = baseModalElement.props;
+    return null;
+}
+
+describe('Modal shouldHandleNavigationBack', () => {
+    beforeEach(() => {
+        latestBaseModalProps = undefined;
+        jest.clearAllMocks();
+        jest.useFakeTimers();
+        window.history.replaceState({existing: 'state'}, '', window.location.href);
+    });
+
+    afterEach(() => {
+        jest.runOnlyPendingTimers();
+        jest.useRealTimers();
+        window.history.replaceState({}, '', window.location.href);
+    });
+
+    it('pushes a guard history entry and closes on popstate when enabled', () => {
+        const onClose = jest.fn();
+
+        render(
+            <ModalHarness
+                isVisible
+                onClose={onClose}
+                shouldHandleNavigationBack
+            >
+                {null}
+            </ModalHarness>,
+        );
+
+        // Given a modal configured to handle browser back navigation
+        expect(typeof latestBaseModalProps?.onModalShow).toBe('function');
+
+        // When the modal show callback runs and the browser navigates back
+        act(() => {
+            latestBaseModalProps?.onModalShow?.();
+        });
+
+        expect(window.history.state).toMatchObject({existing: 'state', shouldGoBack: true});
+
+        act(() => {
+            window.dispatchEvent(new PopStateEvent('popstate'));
+        });
+
+        // Then the modal should close through its onClose callback
+        expect(onClose).toHaveBeenCalledTimes(1);
+    });
+
+    it('runs onModalHide immediately and schedules history.back when enabled', () => {
+        const onModalHide = jest.fn();
+        const historyBackSpy = jest.spyOn(window.history, 'back').mockImplementation(() => {});
+
+        render(
+            <ModalHarness
+                isVisible
+                onClose={jest.fn()}
+                onModalHide={onModalHide}
+                shouldHandleNavigationBack
+            >
+                {null}
+            </ModalHarness>,
+        );
+
+        act(() => {
+            latestBaseModalProps?.onModalShow?.();
+        });
+
+        // Given a shown modal with the guard history entry
+        expect(window.history.state).toMatchObject({shouldGoBack: true});
+
+        // When the modal hide callback runs
+        act(() => {
+            latestBaseModalProps?.onModalHide?.();
+        });
+
+        // Then it should notify the caller immediately and schedule a browser back
+        expect(onModalHide).toHaveBeenCalledTimes(1);
+        expect(historyBackSpy).not.toHaveBeenCalled();
+
+        act(() => {
+            jest.runAllTimers();
+        });
+
+        expect(historyBackSpy).toHaveBeenCalledTimes(1);
+
+        historyBackSpy.mockRestore();
+    });
+
+    it('does not register browser back handling when disabled', () => {
+        const onClose = jest.fn();
+        const onModalHide = jest.fn();
+        const historyBackSpy = jest.spyOn(window.history, 'back').mockImplementation(() => {});
+
+        render(
+            <ModalHarness
+                isVisible
+                onClose={onClose}
+                onModalHide={onModalHide}
+            >
+                {null}
+            </ModalHarness>,
+        );
+
+        // When modal show and hide callbacks run without the navigation-back flag
+        act(() => {
+            latestBaseModalProps?.onModalShow?.();
+        });
+
+        act(() => {
+            window.dispatchEvent(new PopStateEvent('popstate'));
+        });
+
+        act(() => {
+            latestBaseModalProps?.onModalHide?.();
+            jest.runAllTimers();
+        });
+
+        // Then it should not wire browser navigation behavior
+        expect(window.history.state).toMatchObject({existing: 'state'});
+        expect(onClose).not.toHaveBeenCalled();
+        expect(onModalHide).toHaveBeenCalledTimes(1);
+        expect(historyBackSpy).not.toHaveBeenCalled();
+
+        historyBackSpy.mockRestore();
+    });
+});
diff --git a/tests/unit/libs/Accessibility/BlurActiveInputElementTest.ts b/tests/unit/libs/Accessibility/BlurActiveInputElementTest.ts
new file mode 100644
index 000000000000..fbb6cf5fbe6d
--- /dev/null
+++ b/tests/unit/libs/Accessibility/BlurActiveInputElementTest.ts
@@ -0,0 +1,59 @@
+import CONST from '@src/CONST';
+
+/**
+ * Web implementation of blurActiveInputElement, tested directly here because
+ * jest-expo resolves platform imports to .native.ts (no-op) by default.
+ * This mirrors src/libs/Accessibility/blurActiveInputElement/index.ts.
+ */
+function blurActiveInputElement(): void {
+    const activeElement = document.activeElement;
+
+    if (!(activeElement instanceof HTMLElement)) {
+        return;
+    }
+
+    if (activeElement.tagName !== CONST.ELEMENT_NAME.INPUT && activeElement.tagName !== CONST.ELEMENT_NAME.TEXTAREA) {
+        return;
+    }
+
+    activeElement.blur();
+}
+
+describe('blurActiveInputElement (web)', () => {
+    afterEach(() => {
+        document.body.innerHTML = '';
+    });
+
+    it('blurs the active element when it is an input', () => {
+        const input = document.createElement('input');
+        document.body.appendChild(input);
+        input.focus();
+        expect(document.activeElement).toBe(input);
+
+        blurActiveInputElement();
+
+        expect(document.activeElement).not.toBe(input);
+    });
+
+    it('blurs the active element when it is a textarea', () => {
+        const textarea = document.createElement('textarea');
+        document.body.appendChild(textarea);
+        textarea.focus();
+        expect(document.activeElement).toBe(textarea);
+
+        blurActiveInputElement();
+
+        expect(document.activeElement).not.toBe(textarea);
+    });
+
+    it('does nothing when the active element is not an input or textarea', () => {
+        const button = document.createElement('button');
+        document.body.appendChild(button);
+        button.focus();
+        expect(document.activeElement).toBe(button);
+
+        blurActiveInputElement();
+
+        expect(document.activeElement).toBe(button);
+    });
+});
diff --git a/tests/unit/libs/FocusUtilsTest.ts b/tests/unit/libs/FocusUtilsTest.ts
new file mode 100644
index 000000000000..ce339aa8f77d
--- /dev/null
+++ b/tests/unit/libs/FocusUtilsTest.ts
@@ -0,0 +1,222 @@
+import type FocusUtilsModule from '@libs/focusUtils/types';
+
+const FocusUtils = jest.requireActual<{default: FocusUtilsModule}>('../../../src/libs/focusUtils/index.web.ts').default;
+const FocusUtilsFallback = jest.requireActual<{default: FocusUtilsModule}>('../../../src/libs/focusUtils/index.ts').default;
+
+function createMockElement(tagName: string, id: string, options?: {appendToBody?: boolean; width?: number; height?: number}) {
+    const element = document.createElement(tagName);
+    element.id = id;
+
+    if (options?.appendToBody !== false) {
+        document.body.appendChild(element);
+    }
+
+    element.getBoundingClientRect = jest.fn(() => ({
+        width: options?.width ?? 100,
+        height: options?.height ?? 50,
+        top: 0,
+        left: 0,
+        bottom: options?.height ?? 50,
+        right: options?.width ?? 100,
+        x: 0,
+        y: 0,
+        toJSON: () => ({}),
+    }));
+
+    return element;
+}
+
+describe('FocusUtils web implementation', () => {
+    afterEach(() => {
+        document.body.innerHTML = '';
+    });
+
+    describe('isElementFocusRestorable', () => {
+        it('returns false for null', () => {
+            expect(FocusUtils.isElementFocusRestorable(null)).toBe(false);
+        });
+
+        it('returns false for document.body', () => {
+            expect(FocusUtils.isElementFocusRestorable(document.body)).toBe(false);
+        });
+
+        it('returns false for document.documentElement', () => {
+            expect(FocusUtils.isElementFocusRestorable(document.documentElement)).toBe(false);
+        });
+
+        it('returns false for detached elements', () => {
+            const detachedButton = createMockElement('button', 'detached-button', {appendToBody: false});
+
+            expect(FocusUtils.isElementFocusRestorable(detachedButton)).toBe(false);
+        });
+
+        it('returns false for display none elements', () => {
+            const hiddenButton = createMockElement('button', 'display-none-button');
+            hiddenButton.style.display = 'none';
+
+            expect(FocusUtils.isElementFocusRestorable(hiddenButton)).toBe(false);
+        });
+
+        it('returns false for visibility hidden elements', () => {
+            const hiddenButton = createMockElement('button', 'visibility-hidden-button');
+            hiddenButton.style.visibility = 'hidden';
+
+            expect(FocusUtils.isElementFocusRestorable(hiddenButton)).toBe(false);
+        });
+
+        it('returns false for disabled elements', () => {
+            const disabledButton = createMockElement('button', 'disabled-button');
+            disabledButton.setAttribute('disabled', '');
+
+            expect(FocusUtils.isElementFocusRestorable(disabledButton)).toBe(false);
+        });
+
+        it('returns false for elements that are themselves inert', () => {
+            const inertButton = createMockElement('button', 'self-inert-button');
+            inertButton.setAttribute('inert', '');
+
+            expect(FocusUtils.isElementFocusRestorable(inertButton)).toBe(false);
+        });
+
+        it('returns false for descendants of inert containers', () => {
+            const inertContainer = createMockElement('div', 'inert-container');
+            inertContainer.setAttribute('inert', '');
+            const button = document.createElement('button');
+            button.id = 'button-in-inert';
+            button.getBoundingClientRect = jest.fn(() => ({
+                width: 100,
+                height: 50,
+                top: 0,
+                left: 0,
+                bottom: 50,
+                right: 100,
+                x: 0,
+                y: 0,
+                toJSON: () => ({}),
+            }));
+            inertContainer.appendChild(button);
+
+            expect(FocusUtils.isElementFocusRestorable(button)).toBe(false);
+        });
+
+        it('returns false when both width and height are zero', () => {
+            const zeroSizeButton = createMockElement('button', 'zero-size-button', {width: 0, height: 0});
+
+            expect(FocusUtils.isElementFocusRestorable(zeroSizeButton)).toBe(false);
+        });
+
+        it('returns true when only width is zero', () => {
+            const zeroWidthButton = createMockElement('button', 'zero-width-button', {width: 0, height: 50});
+
+            expect(FocusUtils.isElementFocusRestorable(zeroWidthButton)).toBe(true);
+        });
+
+        it('returns true when only height is zero', () => {
+            const zeroHeightButton = createMockElement('button', 'zero-height-button', {width: 100, height: 0});
+
+            expect(FocusUtils.isElementFocusRestorable(zeroHeightButton)).toBe(true);
+        });
+
+        it('returns true for aria-disabled elements when otherwise valid', () => {
+            const ariaDisabledButton = createMockElement('button', 'aria-disabled-button');
+            ariaDisabledButton.setAttribute('aria-disabled', 'true');
+
+            expect(FocusUtils.isElementFocusRestorable(ariaDisabledButton)).toBe(true);
+        });
+    });
+
+    describe('isFocusableActionableElement', () => {
+        it('returns true for role button with tabIndex 0', () => {
+            const button = createMockElement('div', 'role-button');
+            button.setAttribute('role', 'button');
+            button.tabIndex = 0;
+
+            expect(FocusUtils.isFocusableActionableElement(button)).toBe(true);
+        });
+
+        it('returns true for role menuitem with tabIndex 0', () => {
+            const menuitem = createMockElement('div', 'role-menuitem');
+            menuitem.setAttribute('role', 'menuitem');
+            menuitem.tabIndex = 0;
+
+            expect(FocusUtils.isFocusableActionableElement(menuitem)).toBe(true);
+        });
+
+        it('returns false for wrong role even when tabbable', () => {
+            const wrongRole = createMockElement('div', 'wrong-role');
+            wrongRole.setAttribute('role', 'link');
+            wrongRole.tabIndex = 0;
+
+            expect(FocusUtils.isFocusableActionableElement(wrongRole)).toBe(false);
+        });
+
+        it('returns false for tabIndex -1', () => {
+            const nonTabbableButton = createMockElement('div', 'non-tabbable-button');
+            nonTabbableButton.setAttribute('role', 'button');
+            nonTabbableButton.tabIndex = -1;
+
+            expect(FocusUtils.isFocusableActionableElement(nonTabbableButton)).toBe(false);
+        });
+
+        it('returns false for disabled elements', () => {
+            const disabledButton = createMockElement('div', 'disabled-actionable');
+            disabledButton.setAttribute('role', 'button');
+            disabledButton.tabIndex = 0;
+            disabledButton.setAttribute('disabled', '');
+
+            expect(FocusUtils.isFocusableActionableElement(disabledButton)).toBe(false);
+        });
+
+        it('returns false for aria-disabled elements', () => {
+            const ariaDisabledButton = createMockElement('div', 'aria-disabled-actionable');
+            ariaDisabledButton.setAttribute('role', 'button');
+            ariaDisabledButton.tabIndex = 0;
+            ariaDisabledButton.setAttribute('aria-disabled', 'true');
+
+            expect(FocusUtils.isFocusableActionableElement(ariaDisabledButton)).toBe(false);
+        });
+
+        it('returns false for elements that are themselves inert', () => {
+            const inertButton = createMockElement('div', 'self-inert-actionable');
+            inertButton.setAttribute('role', 'button');
+            inertButton.tabIndex = 0;
+            inertButton.setAttribute('inert', '');
+
+            expect(FocusUtils.isFocusableActionableElement(inertButton)).toBe(false);
+        });
+
+        it('returns false for descendants of inert containers', () => {
+            const inertContainer = createMockElement('div', 'inert-actionable-container');
+            inertContainer.setAttribute('inert', '');
+            const button = document.createElement('div');
+            button.id = 'inert-descendant-button';
+            button.setAttribute('role', 'button');
+            button.tabIndex = 0;
+            button.getBoundingClientRect = jest.fn(() => ({
+                width: 100,
+                height: 50,
+                top: 0,
+                left: 0,
+                bottom: 50,
+                right: 100,
+                x: 0,
+                y: 0,
+                toJSON: () => ({}),
+            }));
+            inertContainer.appendChild(button);
+
+            expect(FocusUtils.isFocusableActionableElement(button)).toBe(false);
+        });
+    });
+});
+
+describe('FocusUtils default fallback', () => {
+    it('returns false for both helpers', () => {
+        const button = document.createElement('button');
+        button.setAttribute('role', 'button');
+        button.tabIndex = 0;
+
+        expect(FocusUtilsFallback.isElementFocusRestorable(button)).toBe(false);
+        expect(FocusUtilsFallback.isFocusableActionableElement(button)).toBe(false);
+    });
+});
diff --git a/tests/unit/libs/KeyboardIntentArbitrationIntegrationTest.tsx b/tests/unit/libs/KeyboardIntentArbitrationIntegrationTest.tsx
new file mode 100644
index 000000000000..3fb73313b6ba
--- /dev/null
+++ b/tests/unit/libs/KeyboardIntentArbitrationIntegrationTest.tsx
@@ -0,0 +1,248 @@
+import {render, waitFor} from '@testing-library/react-native';
+import React, {useEffect, useLayoutEffect, useRef} from 'react';
+import NavigationFocusManager from '@libs/NavigationFocusManager/index.web';
+
+type NavigationFocusManagerType = typeof NavigationFocusManager;
+
+type ConsumerEvent = {
+    consumer: 'confirm' | 'composer';
+    value: boolean;
+};
+
+type ConsumerProbeProps = {
+    manager: NavigationFocusManagerType;
+    onSeen: (event: ConsumerEvent) => void;
+};
+
+type ConfirmModalProbeProps = ConsumerProbeProps & {
+    isVisible: boolean;
+};
+
+type ComposerProbeProps = ConsumerProbeProps & {
+    shouldRun: boolean;
+};
+
+type ConfirmModalStrictGuardProbeProps = {
+    isVisible: boolean;
+    manager: NavigationFocusManagerType;
+    onSnapshot: (value: boolean | undefined) => void;
+};
+
+function dispatchEnterKeydown() {
+    const keyEvent = new KeyboardEvent('keydown', {key: 'Enter', bubbles: true});
+    document.dispatchEvent(keyEvent);
+}
+
+function ConfirmModalProbe({isVisible, manager, onSeen}: ConfirmModalProbeProps) {
+    const prevVisibleRef = useRef(isVisible);
+
+    useLayoutEffect(() => {
+        const wasVisible = prevVisibleRef.current;
+        if (isVisible && !wasVisible) {
+            const wasKeyboard = manager.wasRecentKeyboardInteraction();
+            onSeen({consumer: 'confirm', value: wasKeyboard});
+            if (wasKeyboard) {
+                manager.clearKeyboardInteractionFlag();
+            }
+        }
+
+        prevVisibleRef.current = isVisible;
+    }, [isVisible, manager, onSeen]);
+
+    return null;
+}
+
+function ComposerProbe({shouldRun, manager, onSeen}: ComposerProbeProps) {
+    useEffect(() => {
+        if (!shouldRun) {
+            return;
+        }
+
+        const wasKeyboard = manager.wasRecentKeyboardInteraction();
+        onSeen({consumer: 'composer', value: wasKeyboard});
+        if (wasKeyboard) {
+            manager.clearKeyboardInteractionFlag();
+        }
+    }, [shouldRun, manager, onSeen]);
+
+    return null;
+}
+
+function ConfirmModalStrictGuardProbe({isVisible, manager, onSnapshot}: ConfirmModalStrictGuardProbeProps) {
+    const prevVisibleRef = useRef(isVisible);
+    const wasOpenedViaKeyboardRef = useRef<boolean | undefined>(undefined);
+
+    useLayoutEffect(() => {
+        const wasVisible = prevVisibleRef.current;
+        if (isVisible && !wasVisible) {
+            // Mirrors ConfirmModal's StrictMode guard behavior.
+            if (wasOpenedViaKeyboardRef.current === undefined) {
+                const wasKeyboard = manager.wasRecentKeyboardInteraction();
+                wasOpenedViaKeyboardRef.current = wasKeyboard;
+                if (wasKeyboard) {
+                    manager.clearKeyboardInteractionFlag();
+                }
+            }
+            onSnapshot(wasOpenedViaKeyboardRef.current);
+        } else if (!isVisible && wasVisible) {
+            wasOpenedViaKeyboardRef.current = undefined;
+        }
+
+        prevVisibleRef.current = isVisible;
+    }, [isVisible, manager, onSnapshot]);
+
+    return null;
+}
+
+function ArbitrationHarness({
+    isConfirmVisible,
+    shouldRunComposer,
+    manager,
+    onSeen,
+}: {
+    isConfirmVisible: boolean;
+    shouldRunComposer: boolean;
+    manager: NavigationFocusManagerType;
+    onSeen: (event: ConsumerEvent) => void;
+}) {
+    return (
+        <>
+            <ConfirmModalProbe
+                isVisible={isConfirmVisible}
+                manager={manager}
+                onSeen={onSeen}
+            />
+            <ComposerProbe
+                shouldRun={shouldRunComposer}
+                manager={manager}
+                onSeen={onSeen}
+            />
+        </>
+    );
+}
+
+describe('Keyboard Intent Arbitration Integration', () => {
+    beforeEach(() => {
+        NavigationFocusManager.destroy();
+        NavigationFocusManager.initialize();
+        document.body.innerHTML = '';
+    });
+
+    afterEach(() => {
+        NavigationFocusManager.destroy();
+        document.body.innerHTML = '';
+        jest.clearAllMocks();
+    });
+
+    it('should run ConfirmModal layout effect before Composer effect and consume intent first', async () => {
+        const events: ConsumerEvent[] = [];
+        const onSeen = (event: ConsumerEvent) => events.push(event);
+
+        const {rerender} = render(
+            <ArbitrationHarness
+                isConfirmVisible={false}
+                shouldRunComposer={false}
+                manager={NavigationFocusManager}
+                onSeen={onSeen}
+            />,
+        );
+
+        dispatchEnterKeydown();
+
+        rerender(
+            <ArbitrationHarness
+                isConfirmVisible
+                shouldRunComposer
+                manager={NavigationFocusManager}
+                onSeen={onSeen}
+            />,
+        );
+
+        await waitFor(() => {
+            expect(events).toHaveLength(2);
+        });
+
+        expect(events.at(0)).toEqual({consumer: 'confirm', value: true});
+        expect(events.at(1)).toEqual({consumer: 'composer', value: false});
+    });
+
+    it('should let Composer consume first when it runs in an earlier transition', async () => {
+        const events: ConsumerEvent[] = [];
+        const onSeen = (event: ConsumerEvent) => events.push(event);
+
+        const {rerender} = render(
+            <ArbitrationHarness
+                isConfirmVisible={false}
+                shouldRunComposer={false}
+                manager={NavigationFocusManager}
+                onSeen={onSeen}
+            />,
+        );
+
+        dispatchEnterKeydown();
+
+        // First transition: only composer runs and consumes.
+        rerender(
+            <ArbitrationHarness
+                isConfirmVisible={false}
+                shouldRunComposer
+                manager={NavigationFocusManager}
+                onSeen={onSeen}
+            />,
+        );
+
+        await waitFor(() => {
+            expect(events).toHaveLength(1);
+        });
+        expect(events.at(0)).toEqual({consumer: 'composer', value: true});
+
+        // Second transition: confirm opens after composer already consumed.
+        rerender(
+            <ArbitrationHarness
+                isConfirmVisible
+                shouldRunComposer={false}
+                manager={NavigationFocusManager}
+                onSeen={onSeen}
+            />,
+        );
+
+        await waitFor(() => {
+            expect(events).toHaveLength(2);
+        });
+        expect(events.at(1)).toEqual({consumer: 'confirm', value: false});
+    });
+
+    it('should preserve ConfirmModal guarded value in StrictMode and never overwrite with false', async () => {
+        const snapshots: Array<boolean | undefined> = [];
+        const onSnapshot = (value: boolean | undefined) => snapshots.push(value);
+
+        const {rerender} = render(
+            <React.StrictMode>
+                <ConfirmModalStrictGuardProbe
+                    isVisible={false}
+                    manager={NavigationFocusManager}
+                    onSnapshot={onSnapshot}
+                />
+            </React.StrictMode>,
+        );
+
+        dispatchEnterKeydown();
+
+        rerender(
+            <React.StrictMode>
+                <ConfirmModalStrictGuardProbe
+                    isVisible
+                    manager={NavigationFocusManager}
+                    onSnapshot={onSnapshot}
+                />
+            </React.StrictMode>,
+        );
+
+        await waitFor(() => {
+            expect(snapshots.length).toBeGreaterThan(0);
+        });
+
+        expect(snapshots.at(-1)).toBe(true);
+        expect(snapshots).not.toContain(false);
+    });
+});
diff --git a/tests/unit/libs/NavigationFocusManagerTest.tsx b/tests/unit/libs/NavigationFocusManagerTest.tsx
new file mode 100644
index 000000000000..fd2972229e68
--- /dev/null
+++ b/tests/unit/libs/NavigationFocusManagerTest.tsx
@@ -0,0 +1,2238 @@
+import {NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE} from '@libs/NavigationFocusManager/constants';
+
+/**
+ * Unit Tests for NavigationFocusManager - Issue #76921
+ *
+ * NavigationFocusManager is a singleton that captures and stores focused elements
+ * on user interactions (pointerdown, Enter/Space keydown) for later restoration
+ * when navigating back to a screen.
+ *
+ * Test Categories:
+ * - Element availability and lifecycle
+ * - Keyboard and pointer interaction capture
+ * - Route-key based storage and retrieval
+ * - Edge cases (body/html exclusion, nested elements)
+ * - Memory management (destroy, clear, hasStoredFocus)
+ */
+
+/* eslint-disable @typescript-eslint/naming-convention */
+
+// ============================================================================
+// PointerEvent Polyfill for JSDOM
+// ============================================================================
+
+// JSDOM doesn't support PointerEvent, so we polyfill it
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
+class PointerEventPolyfill extends MouseEvent {}
+
+// Add to global if not present
+if (typeof global.PointerEvent === 'undefined') {
+    // @ts-expect-error -- Polyfill for JSDOM
+    global.PointerEvent = PointerEventPolyfill;
+}
+
+jest.mock('@libs/Log');
+
+// ============================================================================
+// NavigationFocusManager Unit Tests
+// ============================================================================
+
+// eslint-disable-next-line @typescript-eslint/consistent-type-imports
+type NavigationFocusManagerType = typeof import('@libs/NavigationFocusManager/index.web').default;
+
+describe('NavigationFocusManager Gap Tests', () => {
+    // Module-level state for testing
+    let NavigationFocusManager: NavigationFocusManagerType;
+
+    beforeEach(() => {
+        // Reset module state between tests
+        jest.resetModules();
+
+        // Fresh import for each test
+        // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
+        NavigationFocusManager = require('@libs/NavigationFocusManager/index.web').default;
+
+        // Initialize the manager
+        NavigationFocusManager.initialize();
+    });
+
+    afterEach(() => {
+        NavigationFocusManager.destroy();
+        document.body.innerHTML = '';
+        jest.clearAllMocks();
+    });
+
+    describe('Gap 1: Delayed Element Availability', () => {
+        it('should return null when element is not in DOM at retrieval time (no identifier match)', () => {
+            // Given: A button that was captured but has no identifying attributes
+            const button = document.createElement('button');
+            button.id = 'virtualized-button';
+            // Note: No aria-label, role, or textContent that would enable identifier matching
+            document.body.appendChild(button);
+
+            // Simulate pointerdown capture
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: button});
+            document.dispatchEvent(pointerEvent);
+
+            // Store the capture for a route
+            NavigationFocusManager.captureForRoute('test-route-1');
+
+            // When: The element is removed from DOM before retrieval
+            button.remove();
+
+            // Then: Retrieval should return null because:
+            // 1. Element reference is no longer in DOM (Strategy 1 fails)
+            // 2. No matching element found via identifier (Strategy 2 fails - no aria-label/role/textContent)
+            const retrieved = NavigationFocusManager.retrieveForRoute('test-route-1');
+            expect(retrieved).toBeNull();
+        });
+
+        it('should find matching element via identifier when original element is removed and re-created', () => {
+            // Given: A button with identifying attributes
+            const originalButton = document.createElement('button');
+            originalButton.id = 'workspace-more-button';
+            originalButton.setAttribute('aria-label', 'More actions for Workspace A');
+            originalButton.setAttribute('role', 'button');
+            originalButton.textContent = 'Workspace A Settings';
+            document.body.appendChild(originalButton);
+
+            // Register the route BEFORE interaction (required for identifier extraction)
+            NavigationFocusManager.registerFocusedRoute('identifier-match-route');
+
+            // Capture the button via pointerdown (this triggers identifier extraction)
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: originalButton});
+            document.dispatchEvent(pointerEvent);
+
+            // Unregister the route (simulating screen losing focus)
+            NavigationFocusManager.unregisterFocusedRoute('identifier-match-route');
+
+            // Remove the original button (simulating screen unmount)
+            originalButton.remove();
+
+            // Create a new button with matching attributes (simulating screen remount)
+            const newButton = document.createElement('button');
+            newButton.id = 'workspace-more-button-new';
+            newButton.setAttribute('aria-label', 'More actions for Workspace A');
+            newButton.setAttribute('role', 'button');
+            newButton.textContent = 'Workspace A Settings';
+            document.body.appendChild(newButton);
+
+            // When: Retrieval is attempted
+            const retrieved = NavigationFocusManager.retrieveForRoute('identifier-match-route');
+
+            // Then: Should find the new button via identifier matching
+            expect(retrieved).toBe(newButton);
+            expect(retrieved?.getAttribute('aria-label')).toBe('More actions for Workspace A');
+        });
+
+        it('should handle gracefully when no element was captured', () => {
+            // Given: No interaction occurred
+
+            // When: captureForRoute is called without prior interaction
+            NavigationFocusManager.captureForRoute('test-route-2');
+
+            // Then: retrieveForRoute should return null
+            const retrieved = NavigationFocusManager.retrieveForRoute('test-route-2');
+            expect(retrieved).toBeNull();
+        });
+
+        it('should use activeElement fallback when interaction capture is stale', () => {
+            // Given: A button that was captured long ago (simulated by not triggering event)
+            const activeButton = document.createElement('button');
+            activeButton.id = 'active-button';
+            document.body.appendChild(activeButton);
+            activeButton.focus();
+
+            // When: captureForRoute is called without recent interaction
+            // (no pointerdown event, but activeElement is the button)
+            NavigationFocusManager.captureForRoute('test-route-3');
+
+            // Then: Should capture the activeElement as fallback
+            const retrieved = NavigationFocusManager.retrieveForRoute('test-route-3');
+            expect(retrieved).toBe(activeButton);
+        });
+    });
+
+    describe('Element matching determinism', () => {
+        it('should prefer aria-label match over text-only exact match when scores tie', () => {
+            const originalButton = document.createElement('button');
+            originalButton.setAttribute('aria-label', 'Workspace actions');
+            originalButton.setAttribute('role', 'button');
+            originalButton.textContent = 'Workspace Settings - Alpha';
+            document.body.appendChild(originalButton);
+
+            NavigationFocusManager.registerFocusedRoute('tie-break-route');
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: originalButton});
+            document.dispatchEvent(pointerEvent);
+            NavigationFocusManager.unregisterFocusedRoute('tie-break-route');
+            originalButton.remove();
+
+            const textOnlyCandidate = document.createElement('button');
+            textOnlyCandidate.setAttribute('role', 'button');
+            textOnlyCandidate.textContent = 'Workspace Settings - Alpha';
+            document.body.appendChild(textOnlyCandidate);
+
+            const ariaCandidate = document.createElement('button');
+            ariaCandidate.setAttribute('aria-label', 'Workspace actions');
+            ariaCandidate.setAttribute('role', 'button');
+            ariaCandidate.textContent = 'Workspace Settings - Alpha Copy';
+            document.body.appendChild(ariaCandidate);
+
+            const retrieved = NavigationFocusManager.retrieveForRoute('tie-break-route');
+            expect(retrieved).toBe(ariaCandidate);
+        });
+
+        it('should reject ambiguous prefix-only collisions', () => {
+            const originalButton = document.createElement('button');
+            originalButton.textContent = 'Workspace Settings - Alpha';
+            document.body.appendChild(originalButton);
+
+            NavigationFocusManager.registerFocusedRoute('prefix-ambiguous-route');
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: originalButton});
+            document.dispatchEvent(pointerEvent);
+            NavigationFocusManager.unregisterFocusedRoute('prefix-ambiguous-route');
+            originalButton.remove();
+
+            const candidateA = document.createElement('button');
+            candidateA.textContent = 'Workspace Settings - Beta';
+            document.body.appendChild(candidateA);
+
+            const candidateB = document.createElement('button');
+            candidateB.textContent = 'Workspace Settings - Gamma';
+            document.body.appendChild(candidateB);
+
+            const retrieved = NavigationFocusManager.retrieveForRoute('prefix-ambiguous-route');
+            expect(retrieved).toBeNull();
+        });
+    });
+
+    describe('Escape-key behavior', () => {
+        it('should mark the interaction as keyboard-driven without storing a focus target on Escape alone', () => {
+            const button = document.createElement('button');
+            document.body.appendChild(button);
+            button.focus();
+
+            NavigationFocusManager.registerFocusedRoute('escape-route');
+            const escapeEvent = new KeyboardEvent('keydown', {key: 'Escape', bubbles: true});
+            document.dispatchEvent(escapeEvent);
+
+            expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+            NavigationFocusManager.clearKeyboardInteractionFlag();
+
+            expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+            expect(NavigationFocusManager.retrieveForRoute('escape-route')).toBeNull();
+        });
+
+        it('should clear keyboard interaction state on destroy', () => {
+            const button = document.createElement('button');
+            document.body.appendChild(button);
+            button.focus();
+
+            NavigationFocusManager.registerFocusedRoute('destroy-route');
+            const escapeEvent = new KeyboardEvent('keydown', {key: 'Escape', bubbles: true});
+            document.dispatchEvent(escapeEvent);
+
+            expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+            NavigationFocusManager.destroy();
+            NavigationFocusManager.initialize();
+            expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+        });
+    });
+
+    describe('Gap 2: Non-Pointer/Enter/Space Navigation Triggers', () => {
+        it('should NOT capture element on non-Enter/Space keydown', () => {
+            // Given: A focused element
+            const menuItem = document.createElement('div');
+            menuItem.setAttribute('role', 'menuitem');
+            menuItem.tabIndex = 0;
+            document.body.appendChild(menuItem);
+            menuItem.focus();
+
+            // When: A keyboard shortcut key is pressed (not Enter/Space)
+            const keyEvent = new KeyboardEvent('keydown', {
+                key: 'k',
+                ctrlKey: true,
+                bubbles: true,
+            });
+            document.dispatchEvent(keyEvent);
+
+            // And: captureForRoute is called
+            NavigationFocusManager.captureForRoute('test-route-4');
+
+            // Then: Should fall back to activeElement (not the keydown-captured element)
+            const retrieved = NavigationFocusManager.retrieveForRoute('test-route-4');
+            expect(retrieved).toBe(menuItem); // Falls back to activeElement
+        });
+
+        it('should capture element on Enter keydown', () => {
+            // Given: A focused element
+            const menuItem = document.createElement('div');
+            menuItem.setAttribute('role', 'menuitem');
+            menuItem.tabIndex = 0;
+            document.body.appendChild(menuItem);
+            menuItem.focus();
+
+            // When: Enter key is pressed
+            const keyEvent = new KeyboardEvent('keydown', {
+                key: 'Enter',
+                bubbles: true,
+            });
+            document.dispatchEvent(keyEvent);
+
+            // And: captureForRoute is called
+            NavigationFocusManager.captureForRoute('test-route-5');
+
+            // Then: Should have captured the element via keydown
+            const retrieved = NavigationFocusManager.retrieveForRoute('test-route-5');
+            expect(retrieved).toBe(menuItem);
+        });
+
+        it('should capture element on Space keydown', () => {
+            // Given: A focused element
+            const button = document.createElement('button');
+            button.id = 'space-button';
+            document.body.appendChild(button);
+            button.focus();
+
+            // When: Space key is pressed
+            const keyEvent = new KeyboardEvent('keydown', {
+                key: ' ',
+                bubbles: true,
+            });
+            document.dispatchEvent(keyEvent);
+
+            // And: captureForRoute is called
+            NavigationFocusManager.captureForRoute('test-route-6');
+
+            // Then: Should have captured the element via keydown
+            const retrieved = NavigationFocusManager.retrieveForRoute('test-route-6');
+            expect(retrieved).toBe(button);
+        });
+
+        it('should handle programmatic navigation (no user interaction) gracefully', () => {
+            // Given: Focus is on document.body (no meaningful element focused)
+            document.body.focus();
+
+            // When: captureForRoute is called (simulating programmatic navigation)
+            NavigationFocusManager.captureForRoute('test-route-7');
+
+            // Then: Should return null (body is explicitly excluded)
+            const retrieved = NavigationFocusManager.retrieveForRoute('test-route-7');
+            expect(retrieved).toBeNull();
+        });
+    });
+
+    describe('Gap 3: Route-Key Granularity', () => {
+        it('should store separate elements for different route keys', () => {
+            // Given: Two different elements for two routes
+            const button1 = document.createElement('button');
+            button1.id = 'button-1';
+            document.body.appendChild(button1);
+
+            const button2 = document.createElement('button');
+            button2.id = 'button-2';
+            document.body.appendChild(button2);
+
+            // When: Capturing for route 1
+            button1.focus();
+            NavigationFocusManager.captureForRoute('route-key-A');
+
+            // And: Capturing for route 2
+            button2.focus();
+            NavigationFocusManager.captureForRoute('route-key-B');
+
+            // Then: Each route should return its own element
+            const retrieved1 = NavigationFocusManager.retrieveForRoute('route-key-A');
+            const retrieved2 = NavigationFocusManager.retrieveForRoute('route-key-B');
+
+            expect(retrieved1).toBe(button1);
+            expect(retrieved2).toBe(button2);
+        });
+
+        it('should return null for route keys that were never stored', () => {
+            // Given: Nothing stored for this route
+
+            // When: Retrieving for unknown route
+            const retrieved = NavigationFocusManager.retrieveForRoute('unknown-route-key');
+
+            // Then: Should return null
+            expect(retrieved).toBeNull();
+        });
+
+        it('should clear route storage after retrieval (one-time use)', () => {
+            // Given: An element captured for a route
+            const button = document.createElement('button');
+            button.id = 'one-time-button';
+            document.body.appendChild(button);
+            button.focus();
+            NavigationFocusManager.captureForRoute('one-time-route');
+
+            // When: Retrieving the first time
+            const firstRetrieval = NavigationFocusManager.retrieveForRoute('one-time-route');
+
+            // Then: Should return the element
+            expect(firstRetrieval).toBe(button);
+
+            // When: Retrieving the second time
+            const secondRetrieval = NavigationFocusManager.retrieveForRoute('one-time-route');
+
+            // Then: Should return null (already consumed)
+            expect(secondRetrieval).toBeNull();
+        });
+    });
+
+    describe('Route boundary ownership resolution', () => {
+        it('should prefer the closest route boundary over a registered wrapper route on pointer capture', () => {
+            const wrapperBoundary = document.createElement('div');
+            wrapperBoundary.setAttribute(NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE, 'workspace-split-route');
+
+            const leafBoundary = document.createElement('div');
+            leafBoundary.setAttribute(NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE, 'workspace-categories-route');
+
+            const button = document.createElement('button');
+            button.id = 'add-category-button';
+
+            leafBoundary.appendChild(button);
+            wrapperBoundary.appendChild(leafBoundary);
+            document.body.appendChild(wrapperBoundary);
+
+            NavigationFocusManager.registerFocusedRoute('workspace-split-route');
+
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: button});
+            document.dispatchEvent(pointerEvent);
+
+            NavigationFocusManager.captureForRoute('workspace-categories-route');
+
+            expect(NavigationFocusManager.retrieveForRoute('workspace-categories-route')).toBe(button);
+            expect(NavigationFocusManager.retrieveForRoute('workspace-split-route')).toBeNull();
+        });
+
+        it('should prefer the closest route boundary over a registered wrapper route on keyboard capture', () => {
+            const wrapperBoundary = document.createElement('div');
+            wrapperBoundary.setAttribute(NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE, 'workspace-split-route');
+
+            const leafBoundary = document.createElement('div');
+            leafBoundary.setAttribute(NAVIGATION_FOCUS_ROUTE_DATA_ATTRIBUTE, 'distance-rates-route');
+
+            const button = document.createElement('button');
+            button.id = 'add-rate-button';
+
+            leafBoundary.appendChild(button);
+            wrapperBoundary.appendChild(leafBoundary);
+            document.body.appendChild(wrapperBoundary);
+
+            NavigationFocusManager.registerFocusedRoute('workspace-split-route');
+            button.focus();
+
+            const keyEvent = new KeyboardEvent('keydown', {
+                key: 'Enter',
+                bubbles: true,
+            });
+            document.dispatchEvent(keyEvent);
+
+            NavigationFocusManager.captureForRoute('distance-rates-route');
+
+            expect(NavigationFocusManager.retrieveForRoute('distance-rates-route')).toBe(button);
+            expect(NavigationFocusManager.retrieveForRoute('workspace-split-route')).toBeNull();
+        });
+    });
+
+    describe('Edge Cases: Interaction Capture Validity', () => {
+        it('should not capture body element on pointerdown', () => {
+            // Given: Pointerdown on body
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: document.body});
+            document.dispatchEvent(pointerEvent);
+
+            // When: captureForRoute is called
+            NavigationFocusManager.captureForRoute('body-click-route');
+
+            // Then: Should return null (body is excluded)
+            const retrieved = NavigationFocusManager.retrieveForRoute('body-click-route');
+            expect(retrieved).toBeNull();
+        });
+
+        it('should not capture HTML element on pointerdown', () => {
+            // Given: Pointerdown on HTML element
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: document.documentElement});
+            document.dispatchEvent(pointerEvent);
+
+            // When: captureForRoute is called
+            NavigationFocusManager.captureForRoute('html-click-route');
+
+            // Then: Should return null (HTML is excluded)
+            const retrieved = NavigationFocusManager.retrieveForRoute('html-click-route');
+            expect(retrieved).toBeNull();
+        });
+
+        it('should find closest interactive element from nested click target', () => {
+            // Given: A button containing a span
+            const button = document.createElement('button');
+            button.id = 'parent-button';
+            const span = document.createElement('span');
+            span.textContent = 'Click me';
+            button.appendChild(span);
+            document.body.appendChild(button);
+
+            // Register route BEFORE interaction (required for state-based validation)
+            NavigationFocusManager.registerFocusedRoute('nested-click-route');
+
+            // When: Pointerdown on the span (inside button)
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: span});
+            document.dispatchEvent(pointerEvent);
+
+            NavigationFocusManager.captureForRoute('nested-click-route');
+
+            // Then: Should capture the button (closest interactive element)
+            const retrieved = NavigationFocusManager.retrieveForRoute('nested-click-route');
+            expect(retrieved).toBe(button);
+        });
+    });
+
+    describe('DOM Presence Validation', () => {
+        it('should fall back to activeElement when captured element is removed from DOM', () => {
+            // Given: A menu item that gets clicked
+            const menuItem = document.createElement('div');
+            menuItem.setAttribute('role', 'menuitem');
+            menuItem.id = 'menu-item';
+            document.body.appendChild(menuItem);
+
+            // And: An anchor button that will receive focus after menu closes
+            const anchorButton = document.createElement('button');
+            anchorButton.id = 'anchor-button';
+            document.body.appendChild(anchorButton);
+
+            // When: User clicks menu item (pointerdown captures it)
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: menuItem});
+            document.dispatchEvent(pointerEvent);
+
+            // And: Menu item is removed from DOM (popover closes)
+            menuItem.remove();
+
+            // And: Focus moves to anchor button (simulating restoreFocusType: PRESERVE)
+            anchorButton.focus();
+
+            // And: captureForRoute is called
+            NavigationFocusManager.captureForRoute('dropdown-test-route');
+
+            // Then: Should capture the anchor button (activeElement), not the removed menu item
+            const retrieved = NavigationFocusManager.retrieveForRoute('dropdown-test-route');
+            expect(retrieved).toBe(anchorButton);
+        });
+
+        it('should use captured element when it is still in DOM', () => {
+            // Given: A button that remains in DOM
+            const button = document.createElement('button');
+            button.id = 'persistent-button';
+            document.body.appendChild(button);
+
+            // Register route BEFORE interaction (required for state-based validation)
+            NavigationFocusManager.registerFocusedRoute('persistent-button-route');
+
+            // When: User clicks the button
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: button});
+            document.dispatchEvent(pointerEvent);
+
+            // And: captureForRoute is called (button still in DOM)
+            NavigationFocusManager.captureForRoute('persistent-button-route');
+
+            // Then: Should capture the button directly
+            const retrieved = NavigationFocusManager.retrieveForRoute('persistent-button-route');
+            expect(retrieved).toBe(button);
+        });
+
+        it('should return null when both captured element and activeElement are invalid', () => {
+            // Given: A menu item that gets clicked
+            const menuItem = document.createElement('div');
+            menuItem.id = 'orphan-menu-item';
+            document.body.appendChild(menuItem);
+
+            // When: User clicks menu item
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: menuItem});
+            document.dispatchEvent(pointerEvent);
+
+            // And: Menu item is removed
+            menuItem.remove();
+
+            // And: Focus is on body (no valid activeElement)
+            document.body.focus();
+
+            // And: captureForRoute is called
+            NavigationFocusManager.captureForRoute('no-valid-element-route');
+
+            // Then: Should return null
+            const retrieved = NavigationFocusManager.retrieveForRoute('no-valid-element-route');
+            expect(retrieved).toBeNull();
+        });
+    });
+
+    describe('P7-01 Fix Verification: Nested Interactive Elements', () => {
+        /**
+         * P7-01: ApprovalWorkflowSection had nested interactive elements:
+         * <PressableWithoutFeedback role="button">
+         *     <MenuItem role="menuitem" /> <!-- BUG: Same handler, captured instead of outer -->
+         * </PressableWithoutFeedback>
+         *
+         * Fix: MenuItem with interactive={false} no longer has role="menuitem"
+         * This test verifies NavigationFocusManager captures the outer button.
+         */
+        it('should capture outer button when inner element has NO interactive role (post-fix behavior)', () => {
+            // Given: A button containing a div WITHOUT role (simulates fixed MenuItem with interactive={false})
+            const outerButton = document.createElement('div');
+            outerButton.setAttribute('role', 'button');
+            outerButton.id = 'outer-workflow-card';
+
+            const innerDisplay = document.createElement('div');
+            innerDisplay.id = 'inner-display-menuitem';
+            // NOTE: NO role="menuitem" - this is the fix!
+            innerDisplay.textContent = 'Expenses from';
+
+            outerButton.appendChild(innerDisplay);
+            document.body.appendChild(outerButton);
+
+            // Register route BEFORE interaction (required for state-based validation)
+            NavigationFocusManager.registerFocusedRoute('p7-01-fixed-route');
+
+            // When: Pointerdown on the inner display element (user clicks on text)
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: innerDisplay});
+            document.dispatchEvent(pointerEvent);
+
+            NavigationFocusManager.captureForRoute('p7-01-fixed-route');
+
+            // Then: Should capture the outer button (role="button"), NOT the inner div
+            const retrieved = NavigationFocusManager.retrieveForRoute('p7-01-fixed-route');
+            expect(retrieved).toBe(outerButton);
+            expect(retrieved?.id).toBe('outer-workflow-card');
+        });
+
+        it('should capture deeply nested text click to outer button when no intermediate interactive roles', () => {
+            // Given: A complex nested structure like ApprovalWorkflowSection
+            // <div role="button">
+            //   <div> (no role - MenuItem with interactive={false})
+            //     <span> (icon)
+            //     <span> (text - click target)
+            //   </div>
+            // </div>
+            const outerButton = document.createElement('div');
+            outerButton.setAttribute('role', 'button');
+            outerButton.id = 'workflow-card';
+
+            const displayMenuItem = document.createElement('div');
+            displayMenuItem.id = 'display-only-menuitem';
+            // NO role - simulates interactive={false}
+
+            const iconSpan = document.createElement('span');
+            iconSpan.textContent = '👤';
+
+            const textSpan = document.createElement('span');
+            textSpan.textContent = 'Expenses from Everyone';
+
+            displayMenuItem.appendChild(iconSpan);
+            displayMenuItem.appendChild(textSpan);
+            outerButton.appendChild(displayMenuItem);
+            document.body.appendChild(outerButton);
+
+            // Register route BEFORE interaction (required for state-based validation)
+            NavigationFocusManager.registerFocusedRoute('deep-nested-route');
+
+            // When: Pointerdown on the text span (deepest nested element)
+            const pointerEvent = new PointerEvent('pointerdown', {
+                bubbles: true,
+                cancelable: true,
+            });
+            Object.defineProperty(pointerEvent, 'target', {value: textSpan});
+            document.dispatchEvent(pointerEvent);
+
+            NavigationFocusManager.captureForRoute('deep-nested-route');
+
+            // Then: Should bubble up to the outer button
+            const retrieved = NavigationFocusManager.retrieveForRoute('deep-nested-route');
+            expect(retrieved).toBe(outerButton);
+            expect(retrieved?.id).toBe('workflow-card');
+        });
+    });
+
+    // ============================================================================
+    // A1 Fix Verification: State-Based Menuitem Protection (Issue #76921)
+    // ============================================================================
+    // These tests verify the A1 fix that changed from time-based to state-based
+    // protection for menu items. The fix ensures focus restoration works regardless
+    // of how long the user takes to interact with menu items.
+    //
+    // Key behavior:
+    // - Menu items (role="menuitem") are transient and removed from DOM after navigation
+    // - Anchor elements (e.g., "More" button) should be preserved for focus restoration
+    // - Protection is STATE-based (anchor vs menuitem), NOT TIME-based
+    // ============================================================================
+
+    describe('A1 Fix: State-Based Menuitem Protection', () => {
+        describe('Core Protection Logic', () => {
+            it('should skip menuitem capture when prior capture is a non-menuitem anchor (pointerdown)', () => {
+                // Given: A "More" button anchor (non-menuitem)
+                const moreButton = document.createElement('button');
+                moreButton.id = 'more-button';
+                moreButton.setAttribute('aria-label', 'More');
+                document.body.appendChild(moreButton);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-core-pointerdown-route');
+
+                // Step 1: User clicks "More" button - should be captured
+                const anchorPointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(anchorPointerEvent, 'target', {value: moreButton});
+                document.dispatchEvent(anchorPointerEvent);
+
+                // Step 2: Menu opens, create menuitem (simulating popover)
+                const menuItem = document.createElement('div');
+                menuItem.setAttribute('role', 'menuitem');
+                menuItem.id = 'duplicate-workspace';
+                menuItem.setAttribute('aria-label', 'Duplicate Workspace');
+                document.body.appendChild(menuItem);
+
+                // Step 3: User clicks menuitem - should be SKIPPED
+                const menuitemPointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(menuitemPointerEvent, 'target', {value: menuItem});
+                document.dispatchEvent(menuitemPointerEvent);
+
+                // Step 4: Capture for route (simulating navigation)
+                NavigationFocusManager.captureForRoute('a1-core-pointerdown-route');
+
+                // Then: Should have preserved the anchor, not the menuitem
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-core-pointerdown-route');
+                expect(retrieved).toBe(moreButton);
+                expect(retrieved?.id).toBe('more-button');
+            });
+
+            it('should skip menuitem capture when prior capture is a non-menuitem anchor (keydown)', () => {
+                // Given: A "More" button anchor (non-menuitem)
+                const moreButton = document.createElement('button');
+                moreButton.id = 'more-button-key';
+                moreButton.setAttribute('aria-label', 'More');
+                document.body.appendChild(moreButton);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-core-keydown-route');
+
+                // Step 1: User presses Enter on "More" button - should be captured
+                moreButton.focus();
+                const anchorKeyEvent = new KeyboardEvent('keydown', {
+                    key: 'Enter',
+                    bubbles: true,
+                    cancelable: true,
+                });
+                document.dispatchEvent(anchorKeyEvent);
+
+                // Step 2: Menu opens, create menuitem
+                const menuItem = document.createElement('div');
+                menuItem.setAttribute('role', 'menuitem');
+                menuItem.id = 'delete-workspace';
+                menuItem.tabIndex = 0;
+                document.body.appendChild(menuItem);
+
+                // Step 3: User presses Enter on menuitem - should be SKIPPED
+                menuItem.focus();
+                const menuitemKeyEvent = new KeyboardEvent('keydown', {
+                    key: 'Enter',
+                    bubbles: true,
+                    cancelable: true,
+                });
+                document.dispatchEvent(menuitemKeyEvent);
+
+                // Step 4: Capture for route
+                NavigationFocusManager.captureForRoute('a1-core-keydown-route');
+
+                // Then: Should have preserved the anchor
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-core-keydown-route');
+                expect(retrieved).toBe(moreButton);
+            });
+
+            it('should capture menuitem when no prior capture exists', () => {
+                // Given: Fresh state (no prior interaction)
+                // Clear any prior state by doing a capture/retrieve cycle
+                NavigationFocusManager.captureForRoute('clear-state');
+                NavigationFocusManager.retrieveForRoute('clear-state');
+
+                // Create a menuitem (simulating Settings page scenario)
+                const settingsMenuItem = document.createElement('div');
+                settingsMenuItem.setAttribute('role', 'menuitem');
+                settingsMenuItem.id = 'security-settings';
+                settingsMenuItem.setAttribute('aria-label', 'Security');
+                document.body.appendChild(settingsMenuItem);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-no-prior-route');
+
+                // When: User clicks menuitem as first interaction
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: settingsMenuItem});
+                document.dispatchEvent(pointerEvent);
+
+                NavigationFocusManager.captureForRoute('a1-no-prior-route');
+
+                // Then: Menuitem SHOULD be captured (better than nothing)
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-no-prior-route');
+                expect(retrieved).toBe(settingsMenuItem);
+            });
+
+            it('should capture menuitem when prior capture is also a menuitem', () => {
+                // Given: A menuitem that was previously captured
+                const firstMenuItem = document.createElement('div');
+                firstMenuItem.setAttribute('role', 'menuitem');
+                firstMenuItem.id = 'first-menuitem';
+                document.body.appendChild(firstMenuItem);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-menuitem-to-menuitem-route');
+
+                // Click first menuitem
+                const firstPointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(firstPointerEvent, 'target', {value: firstMenuItem});
+                document.dispatchEvent(firstPointerEvent);
+
+                // When: Second menuitem is clicked
+                const secondMenuItem = document.createElement('div');
+                secondMenuItem.setAttribute('role', 'menuitem');
+                secondMenuItem.id = 'second-menuitem';
+                document.body.appendChild(secondMenuItem);
+
+                const secondPointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(secondPointerEvent, 'target', {value: secondMenuItem});
+                document.dispatchEvent(secondPointerEvent);
+
+                NavigationFocusManager.captureForRoute('a1-menuitem-to-menuitem-route');
+
+                // Then: Second menuitem SHOULD be captured (both are menuitems, so overwrite is allowed)
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-menuitem-to-menuitem-route');
+                expect(retrieved).toBe(secondMenuItem);
+            });
+        });
+
+        describe('Time Independence (Critical A1 Fix Verification)', () => {
+            /**
+             * This is the critical test that verifies the A1 fix.
+             * The old time-based protection would fail after 1000ms.
+             * The new state-based protection works regardless of delay.
+             */
+            it('should preserve anchor even after very long delay (simulating slow user)', () => {
+                // Given: A "More" button anchor
+                const moreButton = document.createElement('button');
+                moreButton.id = 'slow-user-more-button';
+                moreButton.setAttribute('aria-label', 'More');
+                document.body.appendChild(moreButton);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-long-delay-route');
+
+                // Step 1: User clicks "More" button
+                const anchorPointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(anchorPointerEvent, 'target', {value: moreButton});
+                document.dispatchEvent(anchorPointerEvent);
+
+                // Step 2: Simulate 10 second delay (10x the old 1000ms limit)
+                // In real code, we'd use jest.advanceTimersByTime, but since the fix
+                // is state-based (not time-based), the delay doesn't matter.
+                // We just verify the protection still works.
+
+                // Step 3: Menu item clicked after "long delay"
+                const menuItem = document.createElement('div');
+                menuItem.setAttribute('role', 'menuitem');
+                menuItem.id = 'delayed-menuitem';
+                document.body.appendChild(menuItem);
+
+                const menuitemPointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(menuitemPointerEvent, 'target', {value: menuItem});
+                document.dispatchEvent(menuitemPointerEvent);
+
+                NavigationFocusManager.captureForRoute('a1-long-delay-route');
+
+                // Then: Anchor should STILL be preserved (this would fail with old time-based logic)
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-long-delay-route');
+                expect(retrieved).toBe(moreButton);
+                expect(retrieved?.id).toBe('slow-user-more-button');
+            });
+
+            it('should use state-based check, not timestamp-based check', () => {
+                // This test verifies the implementation detail: the protection
+                // should check element semantics, not timestamps.
+
+                const moreButton = document.createElement('button');
+                moreButton.id = 'state-check-more';
+                document.body.appendChild(moreButton);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('state-check-route');
+
+                // Capture anchor
+                const anchorEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(anchorEvent, 'target', {value: moreButton});
+                document.dispatchEvent(anchorEvent);
+
+                // Create menuitem
+                const menuItem = document.createElement('div');
+                menuItem.setAttribute('role', 'menuitem');
+                menuItem.id = 'state-check-menuitem';
+                document.body.appendChild(menuItem);
+
+                // Click menuitem
+                const menuitemEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(menuitemEvent, 'target', {value: menuItem});
+                document.dispatchEvent(menuitemEvent);
+
+                NavigationFocusManager.captureForRoute('state-check-route');
+
+                // Verify: The anchor is preserved because:
+                // - Current target has role="menuitem" (detected via closest)
+                // - Prior capture does NOT have role="menuitem" (detected via closest)
+                // - Therefore: skip current, preserve prior
+                const retrieved = NavigationFocusManager.retrieveForRoute('state-check-route');
+                expect(retrieved).toBe(moreButton);
+            });
+        });
+
+        describe('Multiple Menu Interactions', () => {
+            it('should correctly handle Menu A → close → Menu B sequence', () => {
+                // Given: Two different "More" buttons for different workspaces
+                const moreButtonA = document.createElement('button');
+                moreButtonA.id = 'more-button-workspace-a';
+                moreButtonA.setAttribute('aria-label', 'More');
+                moreButtonA.textContent = 'Workspace A';
+                document.body.appendChild(moreButtonA);
+
+                const moreButtonB = document.createElement('button');
+                moreButtonB.id = 'more-button-workspace-b';
+                moreButtonB.setAttribute('aria-label', 'More');
+                moreButtonB.textContent = 'Workspace B';
+                document.body.appendChild(moreButtonB);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-multi-menu-route');
+
+                // Step 1: Click More button A
+                const eventA = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(eventA, 'target', {value: moreButtonA});
+                document.dispatchEvent(eventA);
+
+                // Step 2: Click More button B (simulating: closed menu A, opened menu B)
+                // This is a NON-menuitem, so it SHOULD overwrite the prior capture
+                const eventB = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(eventB, 'target', {value: moreButtonB});
+                document.dispatchEvent(eventB);
+
+                // Step 3: Click menuitem in menu B
+                const menuItemB = document.createElement('div');
+                menuItemB.setAttribute('role', 'menuitem');
+                menuItemB.id = 'duplicate-workspace-b';
+                document.body.appendChild(menuItemB);
+
+                const menuitemEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(menuitemEvent, 'target', {value: menuItemB});
+                document.dispatchEvent(menuitemEvent);
+
+                NavigationFocusManager.captureForRoute('a1-multi-menu-route');
+
+                // Then: Should have More button B (the most recent non-menuitem)
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-multi-menu-route');
+                expect(retrieved).toBe(moreButtonB);
+                expect(retrieved?.id).toBe('more-button-workspace-b');
+            });
+
+            it('should allow non-menuitem to overwrite prior non-menuitem capture', () => {
+                // Given: Two buttons (neither are menuitems)
+                const button1 = document.createElement('button');
+                button1.id = 'button-1';
+                document.body.appendChild(button1);
+
+                const button2 = document.createElement('button');
+                button2.id = 'button-2';
+                document.body.appendChild(button2);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-overwrite-route');
+
+                // Click button 1
+                const event1 = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(event1, 'target', {value: button1});
+                document.dispatchEvent(event1);
+
+                // Click button 2 - should overwrite
+                const event2 = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(event2, 'target', {value: button2});
+                document.dispatchEvent(event2);
+
+                NavigationFocusManager.captureForRoute('a1-overwrite-route');
+
+                // Then: Should have button 2 (most recent)
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-overwrite-route');
+                expect(retrieved).toBe(button2);
+            });
+        });
+
+        describe('Edge Cases', () => {
+            it('should handle menuitem nested inside button (complex DOM structure)', () => {
+                // Given: A structure like:
+                // <button role="button">
+                //   <div role="menuitem">Click me</div>
+                // </button>
+                // This is an unusual structure but we should handle it.
+
+                const outerButton = document.createElement('button');
+                outerButton.id = 'outer-button';
+                outerButton.setAttribute('role', 'button');
+
+                const innerMenuitem = document.createElement('div');
+                innerMenuitem.setAttribute('role', 'menuitem');
+                innerMenuitem.id = 'inner-menuitem';
+                innerMenuitem.textContent = 'Click me';
+
+                outerButton.appendChild(innerMenuitem);
+                document.body.appendChild(outerButton);
+
+                // First, capture a non-menuitem anchor
+                const anchor = document.createElement('button');
+                anchor.id = 'anchor-for-edge-case';
+                document.body.appendChild(anchor);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-nested-edge-route');
+
+                const anchorEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(anchorEvent, 'target', {value: anchor});
+                document.dispatchEvent(anchorEvent);
+
+                // Now click on the inner menuitem
+                const menuitemEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(menuitemEvent, 'target', {value: innerMenuitem});
+                document.dispatchEvent(menuitemEvent);
+
+                NavigationFocusManager.captureForRoute('a1-nested-edge-route');
+
+                // Then: Should preserve anchor (innerMenuitem has role="menuitem" via closest)
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-nested-edge-route');
+                expect(retrieved).toBe(anchor);
+            });
+
+            it('should handle Space key on menuitem the same as Enter key', () => {
+                // Given: An anchor button
+                const moreButton = document.createElement('button');
+                moreButton.id = 'more-button-space';
+                document.body.appendChild(moreButton);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-space-key-route');
+
+                // Capture anchor via Enter
+                moreButton.focus();
+                const anchorEvent = new KeyboardEvent('keydown', {key: 'Enter', bubbles: true});
+                document.dispatchEvent(anchorEvent);
+
+                // Create and focus menuitem
+                const menuItem = document.createElement('div');
+                menuItem.setAttribute('role', 'menuitem');
+                menuItem.id = 'menuitem-space';
+                menuItem.tabIndex = 0;
+                document.body.appendChild(menuItem);
+                menuItem.focus();
+
+                // Press Space on menuitem
+                const spaceEvent = new KeyboardEvent('keydown', {key: ' ', bubbles: true});
+                document.dispatchEvent(spaceEvent);
+
+                NavigationFocusManager.captureForRoute('a1-space-key-route');
+
+                // Then: Anchor should be preserved
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-space-key-route');
+                expect(retrieved).toBe(moreButton);
+            });
+
+            it('should handle element with aria-haspopup but not role="menuitem"', () => {
+                // Given: A button that opens a popup (not a menuitem itself)
+                const popupTrigger = document.createElement('button');
+                popupTrigger.id = 'popup-trigger';
+                popupTrigger.setAttribute('aria-haspopup', 'true');
+                document.body.appendChild(popupTrigger);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-popup-trigger-route');
+
+                // Click popup trigger
+                const triggerEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(triggerEvent, 'target', {value: popupTrigger});
+                document.dispatchEvent(triggerEvent);
+
+                // Create and click menuitem
+                const menuItem = document.createElement('div');
+                menuItem.setAttribute('role', 'menuitem');
+                menuItem.id = 'popup-menuitem';
+                document.body.appendChild(menuItem);
+
+                const menuitemEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(menuitemEvent, 'target', {value: menuItem});
+                document.dispatchEvent(menuitemEvent);
+
+                NavigationFocusManager.captureForRoute('a1-popup-trigger-route');
+
+                // Then: Popup trigger should be preserved (it's not a menuitem)
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-popup-trigger-route');
+                expect(retrieved).toBe(popupTrigger);
+            });
+        });
+
+        describe('Regression Prevention', () => {
+            it('should NOT break normal button navigation (no menuitem involved)', () => {
+                // Given: A simple button navigation scenario
+                const navButton = document.createElement('button');
+                navButton.id = 'nav-button';
+                navButton.setAttribute('aria-label', 'Navigate');
+                document.body.appendChild(navButton);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-regression-route');
+
+                // When: User clicks button and navigates
+                const pointerEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(pointerEvent, 'target', {value: navButton});
+                document.dispatchEvent(pointerEvent);
+
+                NavigationFocusManager.captureForRoute('a1-regression-route');
+
+                // Then: Button should be captured normally
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-regression-route');
+                expect(retrieved).toBe(navButton);
+            });
+
+            it('should NOT break link navigation (no menuitem involved)', () => {
+                // Given: A link element
+                const link = document.createElement('a');
+                link.id = 'nav-link';
+                link.href = '#test';
+                link.textContent = 'Navigate';
+                document.body.appendChild(link);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-link-route');
+
+                // When: User clicks link
+                const pointerEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(pointerEvent, 'target', {value: link});
+                document.dispatchEvent(pointerEvent);
+
+                NavigationFocusManager.captureForRoute('a1-link-route');
+
+                // Then: Link should be captured normally
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-link-route');
+                expect(retrieved).toBe(link);
+            });
+
+            it('should NOT break role="button" div navigation', () => {
+                // Given: A div with role="button" (common in React Native Web)
+                const divButton = document.createElement('div');
+                divButton.id = 'div-button';
+                divButton.setAttribute('role', 'button');
+                divButton.tabIndex = 0;
+                document.body.appendChild(divButton);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('a1-div-button-route');
+
+                // When: User clicks div button
+                const pointerEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(pointerEvent, 'target', {value: divButton});
+                document.dispatchEvent(pointerEvent);
+
+                NavigationFocusManager.captureForRoute('a1-div-button-route');
+
+                // Then: Div button should be captured normally
+                const retrieved = NavigationFocusManager.retrieveForRoute('a1-div-button-route');
+                expect(retrieved).toBe(divButton);
+            });
+        });
+    });
+
+    // ============================================================================
+    // Approach 6: Keyboard Interaction Check (Issue #76921)
+    // ============================================================================
+    // These tests verify the keyboard interaction tracking used to distinguish
+    // keyboard navigation from mouse navigation, allowing the composer to skip
+    // auto-focus when users navigate back via keyboard.
+    // ============================================================================
+
+    describe('Approach 6: Keyboard Interaction Tracking', () => {
+        describe('wasRecentKeyboardInteraction() Flag', () => {
+            it('should return false initially (no interaction)', () => {
+                // Given: Fresh state
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // Then: Flag should be false
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+            });
+
+            it('should set flag to true on Enter keydown', () => {
+                // Given: Fresh state
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // When: Enter key is pressed
+                const keyEvent = new KeyboardEvent('keydown', {
+                    key: 'Enter',
+                    bubbles: true,
+                });
+                document.dispatchEvent(keyEvent);
+
+                // Then: Flag should be true
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+            });
+
+            it('should set flag to true on Space keydown', () => {
+                // Given: Fresh state
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // When: Space key is pressed
+                const keyEvent = new KeyboardEvent('keydown', {
+                    key: ' ',
+                    bubbles: true,
+                });
+                document.dispatchEvent(keyEvent);
+
+                // Then: Flag should be true
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+            });
+
+            it('should set flag to true on Escape keydown (back navigation)', () => {
+                // Given: Fresh state
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // When: Escape key is pressed
+                const keyEvent = new KeyboardEvent('keydown', {
+                    key: 'Escape',
+                    bubbles: true,
+                });
+                document.dispatchEvent(keyEvent);
+
+                // Then: Flag should be true
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+            });
+
+            it('should NOT set flag on other key presses (e.g., Tab, Arrow keys)', () => {
+                // Given: Fresh state
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // When: Tab key is pressed
+                const tabEvent = new KeyboardEvent('keydown', {
+                    key: 'Tab',
+                    bubbles: true,
+                });
+                document.dispatchEvent(tabEvent);
+
+                // Then: Flag should still be false
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+
+                // When: ArrowDown is pressed
+                const arrowEvent = new KeyboardEvent('keydown', {
+                    key: 'ArrowDown',
+                    bubbles: true,
+                });
+                document.dispatchEvent(arrowEvent);
+
+                // Then: Flag should still be false
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+            });
+        });
+
+        describe('clearKeyboardInteractionFlag()', () => {
+            it('should clear the flag after it was set by keyboard interaction', () => {
+                // Given: Flag set by Enter keydown
+                const keyEvent = new KeyboardEvent('keydown', {
+                    key: 'Enter',
+                    bubbles: true,
+                });
+                document.dispatchEvent(keyEvent);
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+                // When: Flag is cleared
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // Then: Flag should be false
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+            });
+
+            it('should be safe to call multiple times', () => {
+                // Given: Flag is already false
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // When: Called multiple times
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // Then: No errors, flag remains false
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+            });
+        });
+
+        describe('Pointer Interaction Clears Flag', () => {
+            it('should clear keyboard flag on pointerdown (mouse click)', () => {
+                // Given: Flag set by keyboard interaction
+                const keyEvent = new KeyboardEvent('keydown', {
+                    key: 'Enter',
+                    bubbles: true,
+                });
+                document.dispatchEvent(keyEvent);
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+                // When: Mouse click occurs
+                const button = document.createElement('button');
+                document.body.appendChild(button);
+
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                // Then: Flag should be cleared
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+            });
+
+            it('should handle keyboard → mouse → keyboard sequence correctly', () => {
+                // Step 1: Keyboard interaction
+                const keyEvent1 = new KeyboardEvent('keydown', {key: 'Enter', bubbles: true});
+                document.dispatchEvent(keyEvent1);
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+                // Step 2: Mouse interaction (clears flag)
+                const button = document.createElement('button');
+                document.body.appendChild(button);
+                const pointerEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+
+                // Step 3: Keyboard interaction again
+                const keyEvent2 = new KeyboardEvent('keydown', {key: 'Escape', bubbles: true});
+                document.dispatchEvent(keyEvent2);
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+            });
+        });
+
+        describe('Escape Key Behavior (Approach 6 Specific)', () => {
+            it('should set flag but NOT capture element on Escape (back navigation only needs flag)', () => {
+                // Given: A focused button
+                const button = document.createElement('button');
+                button.id = 'escape-test-button';
+                document.body.appendChild(button);
+                button.focus();
+
+                // And: Clear any prior capture
+                NavigationFocusManager.captureForRoute('clear-prior');
+                NavigationFocusManager.retrieveForRoute('clear-prior');
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // When: Escape is pressed
+                const escapeEvent = new KeyboardEvent('keydown', {
+                    key: 'Escape',
+                    bubbles: true,
+                });
+                document.dispatchEvent(escapeEvent);
+
+                // Then: Flag should be set
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+                // But: No element should be captured via interaction capture
+                // (Escape doesn't call the element capture logic, only sets flag)
+                // captureForRoute will use activeElement fallback since lastInteractionCapture is null
+                NavigationFocusManager.captureForRoute('escape-route');
+                const retrieved = NavigationFocusManager.retrieveForRoute('escape-route');
+
+                // The button may be captured via activeElement fallback, which is expected
+                // The key point is the keyboard flag was set
+                expect(retrieved).toBe(button); // via activeElement fallback
+            });
+
+            it('should NOT overwrite prior capture when Escape is pressed (preserves forward nav element)', () => {
+                // Given: An element captured via Enter (forward navigation)
+                const forwardButton = document.createElement('button');
+                forwardButton.id = 'forward-button';
+                forwardButton.setAttribute('aria-label', 'Forward');
+                document.body.appendChild(forwardButton);
+
+                // Register route for immediate capture
+                NavigationFocusManager.registerFocusedRoute('preserve-forward-route');
+
+                // Press Enter on forward button
+                forwardButton.focus();
+                const enterEvent = new KeyboardEvent('keydown', {key: 'Enter', bubbles: true});
+                document.dispatchEvent(enterEvent);
+
+                // Now press Escape (back navigation) - should NOT overwrite
+                const escapeEvent = new KeyboardEvent('keydown', {key: 'Escape', bubbles: true});
+                document.dispatchEvent(escapeEvent);
+
+                // Unregister route
+                NavigationFocusManager.unregisterFocusedRoute('preserve-forward-route');
+
+                // Then: Should retrieve the forward button, not null
+                const retrieved = NavigationFocusManager.retrieveForRoute('preserve-forward-route');
+                expect(retrieved).toBe(forwardButton);
+            });
+
+            it('should differentiate Escape from Enter/Space in element capture', () => {
+                // Given: Fresh state
+                NavigationFocusManager.captureForRoute('clear-state');
+                NavigationFocusManager.retrieveForRoute('clear-state');
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // Create two buttons
+                const button1 = document.createElement('button');
+                button1.id = 'button-1';
+                document.body.appendChild(button1);
+
+                const button2 = document.createElement('button');
+                button2.id = 'button-2';
+                document.body.appendChild(button2);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('differentiate-route');
+
+                // Press Enter on button1 (captures element)
+                button1.focus();
+                const enterEvent = new KeyboardEvent('keydown', {key: 'Enter', bubbles: true});
+                document.dispatchEvent(enterEvent);
+
+                // Press Escape while button2 is focused (should NOT capture button2)
+                button2.focus();
+                const escapeEvent = new KeyboardEvent('keydown', {key: 'Escape', bubbles: true});
+                document.dispatchEvent(escapeEvent);
+
+                // Capture for route
+                NavigationFocusManager.captureForRoute('differentiate-route');
+                const retrieved = NavigationFocusManager.retrieveForRoute('differentiate-route');
+
+                // Should have captured button1 (from Enter), not button2 (from Escape)
+                // because Escape only sets flag, doesn't capture
+                expect(retrieved).toBe(button1);
+            });
+        });
+
+        describe('Integration: Keyboard vs Mouse User Flow', () => {
+            /**
+             * Simulates the keyboard user flow:
+             * 1. User presses Enter on chat header → wasKeyboardInteraction = true
+             * 2. RHP opens
+             * 3. User presses Escape → wasKeyboardInteraction = true
+             * 4. RHP closes
+             * 5. ComposerWithSuggestions checks flag → true → skips auto-focus
+             */
+            it('should maintain keyboard flag through navigation cycle', () => {
+                // Step 1: Enter on element (forward navigation)
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+                const chatHeader = document.createElement('button');
+                chatHeader.id = 'chat-header';
+                document.body.appendChild(chatHeader);
+                chatHeader.focus();
+
+                const enterEvent = new KeyboardEvent('keydown', {key: 'Enter', bubbles: true});
+                document.dispatchEvent(enterEvent);
+
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+                // Step 2: Simulate RHP open (flag still true)
+                // In real app, this would be modal opening
+
+                // Step 3: Escape (back navigation)
+                const escapeEvent = new KeyboardEvent('keydown', {key: 'Escape', bubbles: true});
+                document.dispatchEvent(escapeEvent);
+
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+                // Step 4: This is where ComposerWithSuggestions would check and clear
+                const wasKeyboard = NavigationFocusManager.wasRecentKeyboardInteraction();
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                expect(wasKeyboard).toBe(true);
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+            });
+
+            /**
+             * Simulates the mouse user flow:
+             * 1. User clicks chat header → wasKeyboardInteraction = false
+             * 2. RHP opens
+             * 3. User clicks Back button → wasKeyboardInteraction = false
+             * 4. RHP closes
+             * 5. ComposerWithSuggestions checks flag → false → auto-focuses
+             */
+            it('should maintain mouse flag (false) through navigation cycle', () => {
+                // Step 1: Click on element (forward navigation)
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+                const chatHeader = document.createElement('button');
+                chatHeader.id = 'chat-header-mouse';
+                document.body.appendChild(chatHeader);
+
+                const clickEvent1 = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(clickEvent1, 'target', {value: chatHeader});
+                document.dispatchEvent(clickEvent1);
+
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+
+                // Step 2: Simulate RHP open
+
+                // Step 3: Click Back button
+                const backButton = document.createElement('button');
+                backButton.id = 'back-button';
+                document.body.appendChild(backButton);
+
+                const clickEvent2 = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(clickEvent2, 'target', {value: backButton});
+                document.dispatchEvent(clickEvent2);
+
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+
+                // Step 4: ComposerWithSuggestions would check and find flag=false → auto-focus
+                const wasKeyboard = NavigationFocusManager.wasRecentKeyboardInteraction();
+                expect(wasKeyboard).toBe(false);
+            });
+
+            /**
+             * Mixed input: keyboard navigate forward, mouse navigate back
+             * Expected: Mouse wins (flag=false), composer should auto-focus
+             */
+            it('should correctly handle keyboard forward → mouse back', () => {
+                // Step 1: Enter on element
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+                const element = document.createElement('button');
+                document.body.appendChild(element);
+                element.focus();
+
+                const enterEvent = new KeyboardEvent('keydown', {key: 'Enter', bubbles: true});
+                document.dispatchEvent(enterEvent);
+
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+                // Step 2: Click back button (mouse)
+                const backButton = document.createElement('button');
+                document.body.appendChild(backButton);
+
+                const clickEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(clickEvent, 'target', {value: backButton});
+                document.dispatchEvent(clickEvent);
+
+                // Then: Mouse should have cleared the keyboard flag
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+            });
+
+            /**
+             * Mixed input: mouse navigate forward, keyboard navigate back
+             * Expected: Keyboard wins (flag=true), focus restoration should work
+             */
+            it('should correctly handle mouse forward → keyboard back', () => {
+                // Step 1: Click on element
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+                const element = document.createElement('button');
+                document.body.appendChild(element);
+
+                const clickEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(clickEvent, 'target', {value: element});
+                document.dispatchEvent(clickEvent);
+
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+
+                // Step 2: Press Escape (keyboard back)
+                const escapeEvent = new KeyboardEvent('keydown', {key: 'Escape', bubbles: true});
+                document.dispatchEvent(escapeEvent);
+
+                // Then: Keyboard should have set the flag
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+            });
+        });
+
+        describe('Edge Cases', () => {
+            it('should handle rapid keyboard events', () => {
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+
+                // Rapid keyboard events
+                for (let i = 0; i < 10; i++) {
+                    const event = new KeyboardEvent('keydown', {key: 'Enter', bubbles: true});
+                    document.dispatchEvent(event);
+                }
+
+                // Flag should still be true
+                expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+            });
+
+            it('should handle rapid alternating keyboard/mouse events', () => {
+                NavigationFocusManager.clearKeyboardInteractionFlag();
+                const button = document.createElement('button');
+                document.body.appendChild(button);
+
+                // Alternate between keyboard and mouse
+                for (let i = 0; i < 5; i++) {
+                    // Keyboard
+                    const keyEvent = new KeyboardEvent('keydown', {key: 'Enter', bubbles: true});
+                    document.dispatchEvent(keyEvent);
+                    expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(true);
+
+                    // Mouse
+                    const pointerEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                    Object.defineProperty(pointerEvent, 'target', {value: button});
+                    document.dispatchEvent(pointerEvent);
+                    expect(NavigationFocusManager.wasRecentKeyboardInteraction()).toBe(false);
+                }
+            });
+        });
+    });
+
+    describe('Memory Management', () => {
+        it('should clear all stored focus on destroy', () => {
+            // Given: Multiple routes with stored focus
+            const button1 = document.createElement('button');
+            document.body.appendChild(button1);
+            button1.focus();
+            NavigationFocusManager.captureForRoute('memory-route-1');
+
+            const button2 = document.createElement('button');
+            document.body.appendChild(button2);
+            button2.focus();
+            NavigationFocusManager.captureForRoute('memory-route-2');
+
+            // When: Manager is destroyed
+            NavigationFocusManager.destroy();
+
+            // Re-initialize for retrieval test
+            NavigationFocusManager.initialize();
+
+            // Then: All stored focus should be cleared
+            expect(NavigationFocusManager.retrieveForRoute('memory-route-1')).toBeNull();
+            expect(NavigationFocusManager.retrieveForRoute('memory-route-2')).toBeNull();
+        });
+
+        it('should support clearForRoute to manually clear stored focus', () => {
+            // Given: A route with stored focus
+            const button = document.createElement('button');
+            document.body.appendChild(button);
+            button.focus();
+            NavigationFocusManager.captureForRoute('clear-test-route');
+
+            // When: clearForRoute is called
+            NavigationFocusManager.clearForRoute('clear-test-route');
+
+            // Then: Retrieval should return null
+            expect(NavigationFocusManager.retrieveForRoute('clear-test-route')).toBeNull();
+        });
+
+        it('should support hasStoredFocus to check without consuming', () => {
+            // Given: A route with stored focus
+            const button = document.createElement('button');
+            document.body.appendChild(button);
+            button.focus();
+            NavigationFocusManager.captureForRoute('has-focus-route');
+
+            // When: hasStoredFocus is called
+            const hasFocus = NavigationFocusManager.hasStoredFocus('has-focus-route');
+
+            // Then: Should return true without consuming
+            expect(hasFocus).toBe(true);
+
+            // And: Retrieval should still work
+            const retrieved = NavigationFocusManager.retrieveForRoute('has-focus-route');
+            expect(retrieved).toBe(button);
+        });
+    });
+
+    // ============================================================================
+    // App.tsx Integration Risk Tests (Issue #76921)
+    // ============================================================================
+    // These tests verify the risks identified in the App.tsx regression analysis:
+    // - React StrictMode double-invocation
+    // - Idempotent initialization
+    // - Event listener cleanup
+    // - Capture phase event handling
+    // - Performance characteristics
+    // ============================================================================
+
+    describe('App.tsx Integration Risks', () => {
+        describe('Risk: React StrictMode Double-Invocation', () => {
+            /**
+             * React StrictMode in development mode calls useEffect twice:
+             * mount → unmount → mount
+             * This simulates that pattern to ensure NavigationFocusManager handles it correctly.
+             */
+            it('should handle StrictMode mount/unmount/mount cycle correctly', () => {
+                // Given: Manager is already initialized from beforeEach
+
+                // Simulate StrictMode: First unmount (cleanup)
+                NavigationFocusManager.destroy();
+
+                // Simulate StrictMode: Second mount
+                NavigationFocusManager.initialize();
+
+                // Then: Manager should still work correctly
+                const button = document.createElement('button');
+                button.id = 'strict-mode-button';
+                document.body.appendChild(button);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('strict-mode-route');
+
+                // Pointerdown should still capture
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                NavigationFocusManager.captureForRoute('strict-mode-route');
+                const retrieved = NavigationFocusManager.retrieveForRoute('strict-mode-route');
+
+                expect(retrieved).toBe(button);
+            });
+
+            it('should not duplicate event listeners after StrictMode cycle', () => {
+                // Given: Track how many times the handler is called
+                const originalAddEventListener = document.addEventListener.bind(document);
+                const listenerCalls: string[] = [];
+
+                jest.spyOn(document, 'addEventListener').mockImplementation((type, listener, options) => {
+                    listenerCalls.push(type);
+                    return originalAddEventListener(type, listener, options);
+                });
+
+                // Reset and re-initialize to track calls
+                NavigationFocusManager.destroy();
+                listenerCalls.length = 0;
+
+                // Simulate StrictMode cycle
+                NavigationFocusManager.initialize(); // First mount
+                NavigationFocusManager.destroy(); // First unmount
+                NavigationFocusManager.initialize(); // Second mount
+
+                // Then: Should only have listeners from final initialization
+                // (pointerdown, keydown = 2 listeners - visibilitychange was removed in state-based refactor)
+                const pointerdownCalls = listenerCalls.filter((t) => t === 'pointerdown').length;
+                expect(pointerdownCalls).toBe(2); // Once per initialize call
+
+                jest.restoreAllMocks();
+            });
+
+            it('should preserve no state across StrictMode cycle', () => {
+                // Given: Some state captured before destroy
+                const button = document.createElement('button');
+                document.body.appendChild(button);
+                button.focus();
+                NavigationFocusManager.captureForRoute('pre-destroy-route');
+
+                // When: StrictMode cycle occurs
+                NavigationFocusManager.destroy();
+                NavigationFocusManager.initialize();
+
+                // Then: Old state should be cleared
+                const retrieved = NavigationFocusManager.retrieveForRoute('pre-destroy-route');
+                expect(retrieved).toBeNull();
+            });
+        });
+
+        describe('Risk: Hot Reload Module Replacement', () => {
+            it('should de-duplicate listeners across module replacement and keep new instance active', () => {
+                const oldManager = NavigationFocusManager;
+
+                jest.resetModules();
+                // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
+                const newManager = require('@libs/NavigationFocusManager/index.web').default as NavigationFocusManagerType;
+                newManager.initialize();
+
+                const button = document.createElement('button');
+                button.id = 'hot-reload-button';
+                document.body.appendChild(button);
+
+                oldManager.registerFocusedRoute('hot-reload-old-route');
+                newManager.registerFocusedRoute('hot-reload-new-route');
+
+                const pointerEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                const oldRetrieved = oldManager.retrieveForRoute('hot-reload-old-route');
+                const newRetrieved = newManager.retrieveForRoute('hot-reload-new-route');
+
+                expect(oldRetrieved).toBeNull();
+                expect(newRetrieved).toBe(button);
+
+                oldManager.unregisterFocusedRoute('hot-reload-old-route');
+                newManager.unregisterFocusedRoute('hot-reload-new-route');
+                newManager.destroy();
+            });
+
+            it('should keep new listeners active when stale old instance calls destroy()', () => {
+                const oldManager = NavigationFocusManager;
+
+                jest.resetModules();
+                // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
+                const newManager = require('@libs/NavigationFocusManager/index.web').default as NavigationFocusManagerType;
+                newManager.initialize();
+
+                oldManager.destroy();
+
+                const button = document.createElement('button');
+                button.id = 'stale-destroy-button';
+                document.body.appendChild(button);
+
+                newManager.registerFocusedRoute('stale-destroy-new-route');
+                const pointerEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                const newRetrieved = newManager.retrieveForRoute('stale-destroy-new-route');
+                expect(newRetrieved).toBe(button);
+
+                newManager.unregisterFocusedRoute('stale-destroy-new-route');
+                newManager.destroy();
+            });
+
+            it('should keep new listeners active when stale old instance calls initialize()', () => {
+                const oldManager = NavigationFocusManager;
+
+                jest.resetModules();
+                // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
+                const newManager = require('@libs/NavigationFocusManager/index.web').default as NavigationFocusManagerType;
+                newManager.initialize();
+
+                oldManager.initialize();
+
+                const button = document.createElement('button');
+                button.id = 'stale-initialize-button';
+                document.body.appendChild(button);
+
+                oldManager.registerFocusedRoute('stale-initialize-old-route');
+                newManager.registerFocusedRoute('stale-initialize-new-route');
+
+                const pointerEvent = new PointerEvent('pointerdown', {bubbles: true, cancelable: true});
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                const oldRetrieved = oldManager.retrieveForRoute('stale-initialize-old-route');
+                const newRetrieved = newManager.retrieveForRoute('stale-initialize-new-route');
+
+                expect(oldRetrieved).toBeNull();
+                expect(newRetrieved).toBe(button);
+
+                oldManager.unregisterFocusedRoute('stale-initialize-old-route');
+                newManager.unregisterFocusedRoute('stale-initialize-new-route');
+                newManager.destroy();
+            });
+        });
+
+        describe('Risk: Idempotent Initialization', () => {
+            it('should be safe to call initialize() multiple times', () => {
+                // Given: Manager already initialized
+
+                // When: initialize() called multiple times
+                NavigationFocusManager.initialize();
+                NavigationFocusManager.initialize();
+                NavigationFocusManager.initialize();
+
+                // Then: Should still work correctly (no errors, single set of listeners)
+                const button = document.createElement('button');
+                document.body.appendChild(button);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('idempotent-route');
+
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                NavigationFocusManager.captureForRoute('idempotent-route');
+                const retrieved = NavigationFocusManager.retrieveForRoute('idempotent-route');
+
+                expect(retrieved).toBe(button);
+            });
+        });
+
+        describe('Risk: Event Listener Cleanup', () => {
+            it('should remove all event listeners on destroy', () => {
+                // Given: Track removeEventListener calls
+                const removedListeners: string[] = [];
+                const originalRemoveEventListener = document.removeEventListener.bind(document);
+
+                jest.spyOn(document, 'removeEventListener').mockImplementation((type, listener, options) => {
+                    removedListeners.push(type);
+                    return originalRemoveEventListener(type, listener, options);
+                });
+
+                // When: destroy() is called
+                NavigationFocusManager.destroy();
+
+                // Then: Both listeners should be removed (visibilitychange was removed in state-based refactor)
+                expect(removedListeners).toContain('pointerdown');
+                expect(removedListeners).toContain('keydown');
+
+                jest.restoreAllMocks();
+
+                // Re-initialize for next test
+                NavigationFocusManager.initialize();
+            });
+        });
+
+        describe('Risk: Capture Phase Event Handling', () => {
+            it('should capture element BEFORE bubbling phase handlers run', () => {
+                // Given: A button with a click handler that might change focus
+                const button = document.createElement('button');
+                button.id = 'capture-phase-button';
+                document.body.appendChild(button);
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('capture-phase-route');
+
+                let capturedBeforeHandler = false;
+                let handlerRan = false;
+
+                // Add a bubbling-phase click handler
+                button.addEventListener('click', () => {
+                    handlerRan = true;
+                    // Check if we already captured the element
+                    NavigationFocusManager.captureForRoute('capture-phase-route');
+                    const retrieved = NavigationFocusManager.retrieveForRoute('capture-phase-route');
+                    if (retrieved === button) {
+                        capturedBeforeHandler = true;
+                    }
+                });
+
+                // When: Pointerdown fires (capture phase)
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                // Simulate click
+                button.click();
+
+                // Then: Element should have been captured before handler ran
+                expect(handlerRan).toBe(true);
+                expect(capturedBeforeHandler).toBe(true);
+            });
+
+            it('should not interfere with other capture-phase listeners', () => {
+                // Given: Another capture-phase listener
+                let otherListenerCalled = false;
+                const otherListener = () => {
+                    otherListenerCalled = true;
+                };
+                document.addEventListener('pointerdown', otherListener, {capture: true});
+
+                // Register route BEFORE interaction (required for state-based validation)
+                NavigationFocusManager.registerFocusedRoute('coexist-route');
+
+                // When: Pointerdown fires
+                const button = document.createElement('button');
+                document.body.appendChild(button);
+
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                // Then: Both listeners should have been called
+                expect(otherListenerCalled).toBe(true);
+
+                // And: NavigationFocusManager should have captured
+                NavigationFocusManager.captureForRoute('coexist-route');
+                const retrieved = NavigationFocusManager.retrieveForRoute('coexist-route');
+                expect(retrieved).toBe(button);
+
+                // Cleanup
+                document.removeEventListener('pointerdown', otherListener, {capture: true});
+            });
+
+            it('should not prevent default or stop propagation', () => {
+                // Given: A button with handlers checking event state
+                const button = document.createElement('button');
+                document.body.appendChild(button);
+
+                let eventDefaultPrevented = false;
+
+                button.addEventListener('pointerdown', (e) => {
+                    eventDefaultPrevented = e.defaultPrevented;
+                });
+
+                // When: Pointerdown fires through NavigationFocusManager
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                button.dispatchEvent(pointerEvent);
+
+                // Then: Event should not have been prevented or stopped
+                expect(eventDefaultPrevented).toBe(false);
+            });
+        });
+
+        describe('State-Based Route Validation', () => {
+            it('should reject capture from a different route', () => {
+                // Given: A button on route-A
+                const buttonA = document.createElement('button');
+                buttonA.id = 'route-a-button';
+                document.body.appendChild(buttonA);
+
+                // Register route-A as the current focused route
+                NavigationFocusManager.registerFocusedRoute('route-A');
+
+                // Capture button on route-A
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: buttonA});
+                document.dispatchEvent(pointerEvent);
+
+                // Unregister route-A
+                NavigationFocusManager.unregisterFocusedRoute('route-A');
+
+                // When: Try to capture for a DIFFERENT route (route-B)
+                // The capture belongs to route-A, not route-B
+                NavigationFocusManager.captureForRoute('route-B');
+
+                // Then: Retrieval for route-B should use activeElement fallback, not the route-A capture
+                // This is because the capture's forRoute (route-A) doesn't match the requested route (route-B)
+                const retrieved = NavigationFocusManager.retrieveForRoute('route-B');
+                // The button should NOT be retrieved since it was captured for a different route
+                // (it will fall back to activeElement which is body in JSDOM)
+                expect(retrieved).not.toBe(buttonA);
+            });
+
+            it('should accept capture from the same route', () => {
+                // Given: A button on route-A
+                const button = document.createElement('button');
+                button.id = 'same-route-button';
+                document.body.appendChild(button);
+
+                // Register route-A as the current focused route
+                NavigationFocusManager.registerFocusedRoute('route-A');
+
+                // Capture button
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                // Unregister route-A
+                NavigationFocusManager.unregisterFocusedRoute('route-A');
+
+                // When: Capture for route-A (matching the capture's forRoute)
+                NavigationFocusManager.captureForRoute('route-A');
+
+                // Then: Retrieval should return the button
+                const retrieved = NavigationFocusManager.retrieveForRoute('route-A');
+                expect(retrieved).toBe(button);
+            });
+
+            it('should reject capture with null forRoute for safety', () => {
+                // Given: A button captured BEFORE any route is registered
+                const button = document.createElement('button');
+                button.id = 'null-route-button';
+                document.body.appendChild(button);
+
+                // Don't register any route - forRoute will be null
+
+                // Capture button (forRoute will be null)
+                const pointerEvent = new PointerEvent('pointerdown', {
+                    bubbles: true,
+                    cancelable: true,
+                });
+                Object.defineProperty(pointerEvent, 'target', {value: button});
+                document.dispatchEvent(pointerEvent);
+
+                // When: Try to capture for any route
+                NavigationFocusManager.captureForRoute('some-route');
+
+                // Then: Should fall back to activeElement since forRoute was null
+                const retrieved = NavigationFocusManager.retrieveForRoute('some-route');
+                // The null-forRoute capture is rejected, falls back to activeElement
+                expect(retrieved).not.toBe(button);
+            });
+        });
+
+        describe('cleanupRemovedRoutes', () => {
+            it('should clean up focus data for routes not in navigation state', () => {
+                // Given: Focus captured for multiple routes
+                const buttonA = document.createElement('button');
+                buttonA.id = 'button-a';
+                document.body.appendChild(buttonA);
+                buttonA.focus();
+                NavigationFocusManager.captureForRoute('route-A-key');
+
+                const buttonB = document.createElement('button');
+                buttonB.id = 'button-b';
+                document.body.appendChild(buttonB);
+                buttonB.focus();
+                NavigationFocusManager.captureForRoute('route-B-key');
+
+                // Verify both have stored focus
+                // Note: hasStoredFocus doesn't consume the entry
+                // We need to re-capture since captureForRoute clears lastInteractionCapture
+                buttonA.focus();
+                NavigationFocusManager.captureForRoute('route-A-key');
+                buttonB.focus();
+                NavigationFocusManager.captureForRoute('route-B-key');
+
+                expect(NavigationFocusManager.hasStoredFocus('route-A-key')).toBe(true);
+                expect(NavigationFocusManager.hasStoredFocus('route-B-key')).toBe(true);
+
+                // When: cleanupRemovedRoutes is called with state containing only route-A
+                const mockNavigationState = {
+                    routes: [{key: 'route-A-key', name: 'ScreenA'}],
+                    index: 0,
+                    stale: false,
+                    type: 'stack',
+                    key: 'root',
+                    routeNames: ['ScreenA'],
+                };
+                NavigationFocusManager.cleanupRemovedRoutes(mockNavigationState);
+
+                // Then: route-A should still have focus data, route-B should be cleaned up
+                expect(NavigationFocusManager.hasStoredFocus('route-A-key')).toBe(true);
+                expect(NavigationFocusManager.hasStoredFocus('route-B-key')).toBe(false);
+            });
+
+            it('should preserve focus data for routes still in navigation state', () => {
+                // Given: Focus captured for a route
+                const button = document.createElement('button');
+                button.id = 'preserved-button';
+                document.body.appendChild(button);
+                button.focus();
+                NavigationFocusManager.captureForRoute('preserved-route-key');
+
+                expect(NavigationFocusManager.hasStoredFocus('preserved-route-key')).toBe(true);
+
+                // When: cleanupRemovedRoutes is called with state containing the route
+                const mockNavigationState = {
+                    routes: [{key: 'preserved-route-key', name: 'PreservedScreen'}],
+                    index: 0,
+                    stale: false,
+                    type: 'stack',
+                    key: 'root',
+                    routeNames: ['PreservedScreen'],
+                };
+                NavigationFocusManager.cleanupRemovedRoutes(mockNavigationState);
+
+                // Then: Focus data should still be available
+                expect(NavigationFocusManager.hasStoredFocus('preserved-route-key')).toBe(true);
+
+                // And retrieval should work
+                const retrieved = NavigationFocusManager.retrieveForRoute('preserved-route-key');
+                expect(retrieved).toBe(button);
+            });
+
+            it('should handle nested routes in navigation state', () => {
+                // Given: Focus captured for a nested route
+                const button = document.createElement('button');
+                button.id = 'nested-route-button';
+                document.body.appendChild(button);
+                button.focus();
+                NavigationFocusManager.captureForRoute('nested-screen-key');
+
+                expect(NavigationFocusManager.hasStoredFocus('nested-screen-key')).toBe(true);
+
+                // When: cleanupRemovedRoutes is called with nested state structure
+                const mockNavigationState = {
+                    routes: [
+                        {
+                            key: 'navigator-key',
+                            name: 'Navigator',
+                            state: {
+                                routes: [{key: 'nested-screen-key', name: 'NestedScreen'}],
+                                index: 0,
+                            },
+                        },
+                    ],
+                    index: 0,
+                    stale: false,
+                    type: 'stack',
+                    key: 'root',
+                    routeNames: ['Navigator'],
+                };
+                NavigationFocusManager.cleanupRemovedRoutes(mockNavigationState);
+
+                // Then: Nested route's focus data should be preserved
+                expect(NavigationFocusManager.hasStoredFocus('nested-screen-key')).toBe(true);
+            });
+        });
+    });
+});
diff --git a/tests/unit/useAutoFocusInputTest.ts b/tests/unit/useAutoFocusInputTest.ts
new file mode 100644
index 000000000000..6fc9a53edb19
--- /dev/null
+++ b/tests/unit/useAutoFocusInputTest.ts
@@ -0,0 +1,301 @@
+/* eslint-disable @typescript-eslint/naming-convention */
+import {act, renderHook} from '@testing-library/react-native';
+import type {TextInput} from 'react-native';
+import {InteractionManager} from 'react-native';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import ComposerFocusManager from '@libs/ComposerFocusManager';
+import isWindowReadyToFocus from '@libs/isWindowReadyToFocus';
+import CONST from '@src/CONST';
+
+type TransitionEndListener = (event?: {data?: {closing?: boolean}}) => void;
+
+let capturedFocusEffect: (() => void | (() => void)) | undefined;
+let capturedTransitionEndListener: TransitionEndListener | undefined;
+
+const mockAddListener = jest.fn();
+const mockSidePanelState = {isSidePanelTransitionEnded: false, shouldHideSidePanel: false};
+
+jest.mock('@react-navigation/native', () => ({
+    useFocusEffect: (callback: () => void | (() => void)) => {
+        capturedFocusEffect = callback;
+    },
+    useNavigation: () => ({
+        addListener: mockAddListener,
+    }),
+}));
+
+jest.mock('@hooks/useOnyx', () => ({
+    __esModule: true,
+    default: () => [null],
+}));
+
+jest.mock('@src/SplashScreenStateContext', () => ({
+    useSplashScreenState: () => ({
+        // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
+        splashScreenState: require('@src/CONST').default.BOOT_SPLASH_STATE.HIDDEN,
+    }),
+}));
+
+jest.mock('@hooks/useSidePanelState', () => ({
+    __esModule: true,
+    default: () => mockSidePanelState,
+}));
+
+jest.mock('@libs/ComposerFocusManager', () => ({
+    __esModule: true,
+    default: {
+        isReadyToFocus: jest.fn(() => Promise.resolve(true)),
+    },
+}));
+
+jest.mock('@libs/isWindowReadyToFocus', () => ({
+    __esModule: true,
+    default: jest.fn(() => Promise.resolve()),
+}));
+
+const originalDocumentDescriptor = Object.getOwnPropertyDescriptor(globalThis, 'document');
+let originalActiveElementDescriptor: PropertyDescriptor | undefined;
+let activeElement: unknown;
+
+function createDeferredPromise() {
+    let resolvePromise: (() => void) | undefined;
+    const promise = new Promise<void>((resolve) => {
+        resolvePromise = resolve;
+    });
+
+    return {
+        promise,
+        resolve: () => resolvePromise?.(),
+    };
+}
+
+function createInput() {
+    const focusOwner = document.createElement('input');
+    const focus = jest.fn();
+    const isFocused = jest.fn(() => activeElement === focusOwner);
+    const input = {} as TextInput;
+    input.focus = focus;
+    input.isFocused = isFocused;
+
+    return {
+        focus,
+        input,
+    };
+}
+
+async function flushPromises() {
+    await act(async () => {
+        await Promise.resolve();
+        await Promise.resolve();
+    });
+}
+
+describe('useAutoFocusInput', () => {
+    beforeAll(() => {
+        if (!globalThis.document) {
+            Object.defineProperty(globalThis, 'document', {
+                value: {body: {}, documentElement: {}} as Document,
+                configurable: true,
+            });
+        }
+
+        originalActiveElementDescriptor = Object.getOwnPropertyDescriptor(document, 'activeElement');
+        Object.defineProperty(document, 'activeElement', {
+            configurable: true,
+            get: () => activeElement as Element | null,
+        });
+    });
+
+    beforeEach(() => {
+        capturedFocusEffect = undefined;
+        capturedTransitionEndListener = undefined;
+        activeElement = document.body;
+        mockSidePanelState.isSidePanelTransitionEnded = false;
+        mockSidePanelState.shouldHideSidePanel = false;
+
+        jest.clearAllMocks();
+        jest.useFakeTimers();
+
+        mockAddListener.mockImplementation((eventName: string, callback: TransitionEndListener) => {
+            if (eventName === 'transitionEnd') {
+                capturedTransitionEndListener = callback;
+            }
+            return jest.fn();
+        });
+
+        jest.spyOn(InteractionManager, 'runAfterInteractions').mockImplementation((task?: (() => void) | {gen?: () => void}) => {
+            if (typeof task === 'function') {
+                task();
+            } else {
+                task?.gen?.();
+            }
+
+            return {
+                then: jest.fn(() => Promise.resolve()),
+                done: jest.fn(),
+                cancel: jest.fn(),
+            } as never;
+        });
+    });
+
+    afterEach(() => {
+        act(() => {
+            jest.runOnlyPendingTimers();
+        });
+        jest.restoreAllMocks();
+        jest.useRealTimers();
+    });
+
+    afterAll(() => {
+        if (originalActiveElementDescriptor) {
+            Object.defineProperty(document, 'activeElement', originalActiveElementDescriptor);
+        }
+
+        if (originalDocumentDescriptor) {
+            Object.defineProperty(globalThis, 'document', originalDocumentDescriptor);
+            return;
+        }
+
+        Reflect.deleteProperty(globalThis as typeof globalThis & {document?: Document}, 'document');
+    });
+
+    it('autofocuses after transitionEnd when no other element owns focus', async () => {
+        const {focus, input} = createInput();
+        const {result} = renderHook(() => useAutoFocusInput());
+
+        act(() => {
+            result.current.inputCallbackRef(input);
+            capturedFocusEffect?.();
+        });
+
+        expect(mockAddListener).toHaveBeenCalledWith('transitionEnd', expect.any(Function));
+
+        await act(async () => {
+            capturedTransitionEndListener?.({data: {closing: false}});
+        });
+        await flushPromises();
+
+        expect(focus).toHaveBeenCalledTimes(1);
+    });
+
+    it('autofocuses via timeout fallback when transitionEnd does not fire', async () => {
+        const {focus, input} = createInput();
+        const {result} = renderHook(() => useAutoFocusInput());
+
+        act(() => {
+            result.current.inputCallbackRef(input);
+            capturedFocusEffect?.();
+            jest.advanceTimersByTime(CONST.SCREEN_TRANSITION_END_TIMEOUT);
+        });
+        await flushPromises();
+
+        expect(focus).toHaveBeenCalledTimes(1);
+    });
+
+    it('re-arms autofocus on a later screen focus', async () => {
+        const {focus, input} = createInput();
+        const {result} = renderHook(() => useAutoFocusInput());
+
+        act(() => {
+            result.current.inputCallbackRef(input);
+        });
+
+        let cleanup: void | (() => void) | undefined;
+        act(() => {
+            cleanup = capturedFocusEffect?.();
+        });
+
+        await act(async () => {
+            capturedTransitionEndListener?.({data: {closing: false}});
+        });
+        await flushPromises();
+
+        act(() => {
+            cleanup?.();
+            cleanup = capturedFocusEffect?.();
+        });
+
+        await act(async () => {
+            capturedTransitionEndListener?.({data: {closing: false}});
+        });
+        await flushPromises();
+
+        expect(focus).toHaveBeenCalledTimes(2);
+    });
+
+    it('does not steal focus if another element becomes active before focus executes', async () => {
+        const deferred = createDeferredPromise();
+        jest.mocked(isWindowReadyToFocus).mockReturnValueOnce(deferred.promise);
+
+        const {focus, input} = createInput();
+        const otherFocusedElement = {} as HTMLElement;
+        const {result} = renderHook(() => useAutoFocusInput());
+
+        act(() => {
+            result.current.inputCallbackRef(input);
+            capturedFocusEffect?.();
+        });
+
+        await act(async () => {
+            capturedTransitionEndListener?.({data: {closing: false}});
+        });
+
+        activeElement = otherFocusedElement;
+
+        await act(async () => {
+            deferred.resolve();
+            await deferred.promise;
+        });
+
+        expect(focus).not.toHaveBeenCalled();
+    });
+
+    it('recovers after skipping focus while another element is active', async () => {
+        const {focus, input} = createInput();
+        const otherFocusedElement = {} as HTMLElement;
+        const {result} = renderHook(() => useAutoFocusInput());
+
+        act(() => {
+            result.current.inputCallbackRef(input);
+            capturedFocusEffect?.();
+        });
+
+        activeElement = otherFocusedElement;
+
+        await act(async () => {
+            capturedTransitionEndListener?.({data: {closing: false}});
+        });
+        await flushPromises();
+
+        expect(focus).not.toHaveBeenCalled();
+
+        activeElement = document.body;
+
+        await act(async () => {
+            capturedTransitionEndListener?.({data: {closing: false}});
+        });
+        await flushPromises();
+
+        expect(focus).toHaveBeenCalledTimes(1);
+    });
+
+    it('still autofocuses when the side panel finishes closing', async () => {
+        const {focus, input} = createInput();
+        const {result, rerender} = renderHook(() => useAutoFocusInput());
+
+        act(() => {
+            result.current.inputCallbackRef(input);
+        });
+
+        mockSidePanelState.shouldHideSidePanel = true;
+        rerender(undefined);
+
+        mockSidePanelState.isSidePanelTransitionEnded = true;
+        rerender(undefined);
+        await flushPromises();
+
+        expect(jest.mocked(ComposerFocusManager.isReadyToFocus)).toHaveBeenCalled();
+        expect(jest.mocked(isWindowReadyToFocus)).toHaveBeenCalled();
+        expect(focus).toHaveBeenCalledTimes(1);
+    });
+});
diff --git a/tests/unit/useSyncFocusTest.ts b/tests/unit/useSyncFocusTest.ts
index f4a1c7f66fe0..1354195b0897 100644
--- a/tests/unit/useSyncFocusTest.ts
+++ b/tests/unit/useSyncFocusTest.ts
@@ -36,4 +36,16 @@ describe('useSyncFocus', () => {
         // Then the ref focus will be called.
         expect(refMock.current.focus).toHaveBeenCalled();
     });
+
+    it("doesn't steal focus from another already-focused element", () => {
+        const refMock = {current: {focus: jest.fn()}};
+        const activeButton = document.createElement('button');
+        document.body.appendChild(activeButton);
+        activeButton.focus();
+
+        renderHook(() => useSyncFocus(refMock as unknown as RefObject<View>, true, true));
+
+        expect(document.activeElement).toBe(activeButton);
+        expect(refMock.current.focus).not.toHaveBeenCalled();
+    });
 });
