diff --git a/packages/desktop-client/src/components/FinancesApp.js b/packages/desktop-client/src/components/FinancesApp.tsx
similarity index 87%
rename from packages/desktop-client/src/components/FinancesApp.js
rename to packages/desktop-client/src/components/FinancesApp.tsx
index bc098f9fcae5e7f7feea6bf48832e86fec70c31d..b8804da5dff2da58edd39c51fa4aaf0695a9707d 100644
--- a/packages/desktop-client/src/components/FinancesApp.js
+++ b/packages/desktop-client/src/components/FinancesApp.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useMemo } from 'react';
+import React, { type ReactElement, useEffect, useMemo } from 'react';
 import { DndProvider } from 'react-dnd';
 import { HTML5Backend as Backend } from 'react-dnd-html5-backend';
 import { connect } from 'react-redux';
@@ -30,31 +30,28 @@ import { colors, styles } from '../style';
 import { ExposeNavigate, StackedRoutes } from '../util/router-tools';
 import { getIsOutdated, getLatestVersion } from '../util/versions';
 
-import Account from './accounts/Account';
-import MobileAccount from './accounts/MobileAccount';
-import MobileAccounts from './accounts/MobileAccounts';
 import BankSyncStatus from './BankSyncStatus';
-import Budget from './budget';
 import { BudgetMonthCountProvider } from './budget/BudgetMonthCountContext';
-import MobileBudget from './budget/MobileBudget';
 import { View } from './common';
 import FloatableSidebar, { SidebarProvider } from './FloatableSidebar';
 import GlobalKeys from './GlobalKeys';
-import GoCardlessLink from './gocardless/GoCardlessLink';
 import { ManageRulesPage } from './ManageRulesPage';
 import Modals from './Modals';
 import Notifications from './Notifications';
 import { ManagePayeesPage } from './payees/ManagePayeesPage';
 import Reports from './reports';
-import Schedules from './schedules';
-import DiscoverSchedules from './schedules/DiscoverSchedules';
-import EditSchedule from './schedules/EditSchedule';
-import LinkSchedule from './schedules/LinkSchedule';
+import { NarrowAlternate, WideComponent } from './responsive';
 import PostsOfflineNotification from './schedules/PostsOfflineNotification';
 import Settings from './settings';
 import Titlebar, { TitlebarProvider } from './Titlebar';
 
-function NarrowNotSupported({ children, redirectTo = '/budget' }) {
+function NarrowNotSupported({
+  redirectTo = '/budget',
+  children,
+}: {
+  redirectTo?: string;
+  children: ReactElement;
+}) {
   const { isNarrowWidth } = useResponsive();
   const navigate = useNavigate();
   useEffect(() => {
@@ -66,7 +63,6 @@ function NarrowNotSupported({ children, redirectTo = '/budget' }) {
 }
 
 function StackedRoutesInner({ location }) {
-  const { isNarrowWidth } = useResponsive();
   return (
     <Routes location={location}>
       <Route path="/" element={<Navigate to="/budget" replace />} />
@@ -75,21 +71,19 @@ function StackedRoutesInner({ location }) {
         path="/reports/*"
         element={
           <NarrowNotSupported>
+            {/* Has its own lazy loading logic */}
             <Reports />
           </NarrowNotSupported>
         }
       />
 
-      <Route
-        path="/budget"
-        element={isNarrowWidth ? <MobileBudget /> : <Budget />}
-      />
+      <Route path="/budget" element={<NarrowAlternate name="Budget" />} />
 
       <Route
         path="/schedules"
         element={
           <NarrowNotSupported>
-            <Schedules />
+            <WideComponent name="Schedules" />
           </NarrowNotSupported>
         }
       />
@@ -98,7 +92,7 @@ function StackedRoutesInner({ location }) {
         path="/schedule/edit"
         element={
           <NarrowNotSupported>
-            <EditSchedule />
+            <WideComponent name="EditSchedule" />
           </NarrowNotSupported>
         }
       />
@@ -106,7 +100,7 @@ function StackedRoutesInner({ location }) {
         path="/schedule/edit/:id"
         element={
           <NarrowNotSupported>
-            <EditSchedule />
+            <WideComponent name="EditSchedule" />
           </NarrowNotSupported>
         }
       />
@@ -114,7 +108,7 @@ function StackedRoutesInner({ location }) {
         path="/schedule/link"
         element={
           <NarrowNotSupported>
-            <LinkSchedule />
+            <WideComponent name="LinkSchedule" />
           </NarrowNotSupported>
         }
       />
@@ -122,7 +116,7 @@ function StackedRoutesInner({ location }) {
         path="/schedule/discover"
         element={
           <NarrowNotSupported>
-            <DiscoverSchedules />
+            <WideComponent name="DiscoverSchedules" />
           </NarrowNotSupported>
         }
       />
@@ -141,7 +135,7 @@ function StackedRoutesInner({ location }) {
         path="/nordigen/link"
         element={
           <NarrowNotSupported>
-            <GoCardlessLink />
+            <WideComponent name="GoCardlessLink" />
           </NarrowNotSupported>
         }
       />
@@ -149,20 +143,17 @@ function StackedRoutesInner({ location }) {
         path="/gocardless/link"
         element={
           <NarrowNotSupported>
-            <GoCardlessLink />
+            <WideComponent name="GoCardlessLink" />
           </NarrowNotSupported>
         }
       />
 
       <Route
         path="/accounts/:id"
-        element={isNarrowWidth ? <MobileAccount /> : <Account />}
+        element={<NarrowAlternate name="Account" />}
       />
 
-      <Route
-        path="/accounts"
-        element={isNarrowWidth ? <MobileAccounts /> : <Account />}
-      />
+      <Route path="/accounts" element={<NarrowAlternate name="Accounts" />} />
     </Routes>
   );
 }
@@ -230,6 +221,8 @@ function RouterBehaviors({ getAccounts }) {
   useEffect(() => {
     undo.setUndoState('url', href);
   }, [href]);
+
+  return null;
 }
 
 function FinancesApp(props) {
diff --git a/packages/desktop-client/src/components/Modals.tsx b/packages/desktop-client/src/components/Modals.tsx
index 1934a56237c61ccfeec7349c7f339caa8fb3b834..ca5b47a990b28fcd738d7e3d7a390c29418173dc 100644
--- a/packages/desktop-client/src/components/Modals.tsx
+++ b/packages/desktop-client/src/components/Modals.tsx
@@ -37,7 +37,7 @@ export default function Modals() {
 
   const syncServerStatus = useSyncServerStatus();
 
-  return modalStack
+  let modals = modalStack
     .map(({ name, options }, idx) => {
       const modalProps = {
         onClose: actions.popModal,
@@ -227,4 +227,8 @@ export default function Modals() {
     .map((modal, idx) => (
       <React.Fragment key={modalStack[idx].name}>{modal}</React.Fragment>
     ));
+
+  // fragment needed per TS types
+  // eslint-disable-next-line react/jsx-no-useless-fragment
+  return <>{modals}</>;
 }
diff --git a/packages/desktop-client/src/components/Notifications.tsx b/packages/desktop-client/src/components/Notifications.tsx
index 67287e2ec1bbf36aa935a704c351f4be60a1017b..69c6450fd2485b532c43d55869a26245ab676ac6 100644
--- a/packages/desktop-client/src/components/Notifications.tsx
+++ b/packages/desktop-client/src/components/Notifications.tsx
@@ -4,13 +4,13 @@ import React, {
   useMemo,
   type SetStateAction,
 } from 'react';
-import { connect, useSelector } from 'react-redux';
+import { useSelector } from 'react-redux';
 
-import { bindActionCreators } from 'redux';
+import { type CSSProperties } from 'glamor';
 
-import * as actions from 'loot-core/src/client/actions';
 import type { NotificationWithId } from 'loot-core/src/client/state-types/notifications';
 
+import { useActions } from '../hooks/useActions';
 import Loading from '../icons/AnimatedLoading';
 import Delete from '../icons/v0/Delete';
 import { styles, colors } from '../style';
@@ -220,7 +220,8 @@ function Notification({
   );
 }
 
-function Notifications({ removeNotification, style }) {
+export default function Notifications({ style }: { style?: CSSProperties }) {
+  let { removeNotification } = useActions();
   let notifications = useSelector(state => state.notifications.notifications);
   return (
     <View
@@ -249,7 +250,3 @@ function Notifications({ removeNotification, style }) {
     </View>
   );
 }
-
-export default connect(null, dispatch => bindActionCreators(actions, dispatch))(
-  Notifications,
-);
diff --git a/packages/desktop-client/src/components/Titlebar.js b/packages/desktop-client/src/components/Titlebar.js
index 50eaa6245bc220a0ea3fcfa22f06c4b5f040385c..8a644b39c48dac87f8028ff2754cf825590c1976 100644
--- a/packages/desktop-client/src/components/Titlebar.js
+++ b/packages/desktop-client/src/components/Titlebar.js
@@ -281,10 +281,7 @@ function Titlebar({
   saveGlobalPrefs,
   savePrefs,
   localPrefs,
-  userData,
   floatingSidebar,
-  syncError,
-  setAppState,
   style,
   sync,
 }) {
diff --git a/packages/desktop-client/src/components/reports/index.tsx b/packages/desktop-client/src/components/reports/index.tsx
index 4d110091bd7c854ebaa36d09de5e9b2a6730fc3e..7d3a886f2d3108942a29aec5dd3c447f93fc775c 100644
--- a/packages/desktop-client/src/components/reports/index.tsx
+++ b/packages/desktop-client/src/components/reports/index.tsx
@@ -1,44 +1,16 @@
-import { useState, useEffect } from 'react';
-
-import AnimatedLoading from '../../icons/AnimatedLoading';
-import { colors, styles } from '../../style';
-import { Block, View } from '../common';
-
-import type { ReportRouter } from './ReportRouter';
+import { View } from '../common';
+import { LoadComponent } from '../util/LoadComponent';
 
 export default function Reports() {
-  let [ReportRouterComponent, setReportRouter] = useState<
-    typeof ReportRouter | null
-  >(null);
-
-  useEffect(() => {
-    import(/* webpackChunkName: 'reports' */ './ReportRouter').then(module => {
-      setReportRouter(() => module.ReportRouter);
-    });
-  }, []);
-
   return (
     <View style={{ flex: 1 }} data-testid="reports-page">
-      {ReportRouterComponent ? (
-        <ReportRouterComponent />
-      ) : (
-        <View
-          style={[
-            {
-              flex: 1,
-              gap: 20,
-              justifyContent: 'center',
-              alignItems: 'center',
-            },
-            styles.delayedFadeIn,
-          ]}
-        >
-          <Block style={{ marginBottom: 20, fontSize: 18 }}>
-            Loading reports…
-          </Block>
-          <AnimatedLoading width={25} color={colors.n1} />
-        </View>
-      )}
+      <LoadComponent
+        name="ReportRouter"
+        message="Loading reports..."
+        importer={() =>
+          import(/* webpackChunkName: 'reports' */ './ReportRouter')
+        }
+      />
     </View>
   );
 }
diff --git a/packages/desktop-client/src/components/responsive/index.tsx b/packages/desktop-client/src/components/responsive/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..570e533aabebe75bf7a18b530b630e87eeaa254a
--- /dev/null
+++ b/packages/desktop-client/src/components/responsive/index.tsx
@@ -0,0 +1,27 @@
+import { useResponsive } from '../../ResponsiveProvider';
+import { LoadComponent } from '../util/LoadComponent';
+
+import type * as NarrowComponents from './narrow';
+import type * as WideComponents from './wide';
+
+let loadNarrow = () =>
+  import(/* webpackChunkName: "narrow-components" */ './narrow');
+let loadWide = () => import(/* webpackChunkName: "wide-components" */ './wide');
+
+export function WideComponent({ name }: { name: keyof typeof WideComponents }) {
+  return <LoadComponent name={name} importer={loadWide} />;
+}
+
+export function NarrowAlternate({
+  name,
+}: {
+  name: keyof typeof WideComponents & keyof typeof NarrowComponents;
+}) {
+  const { isNarrowWidth } = useResponsive();
+  return (
+    <LoadComponent
+      name={name}
+      importer={isNarrowWidth ? loadNarrow : loadWide}
+    />
+  );
+}
diff --git a/packages/desktop-client/src/components/responsive/narrow.ts b/packages/desktop-client/src/components/responsive/narrow.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d3b35e5ef69e2b0d1b8619d15461a01659b2d9dc
--- /dev/null
+++ b/packages/desktop-client/src/components/responsive/narrow.ts
@@ -0,0 +1,4 @@
+export { default as Budget } from '../budget/MobileBudget';
+
+export { default as Accounts } from '../accounts/MobileAccounts';
+export { default as Account } from '../accounts/MobileAccount';
diff --git a/packages/desktop-client/src/components/responsive/wide.ts b/packages/desktop-client/src/components/responsive/wide.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cca8e725e2a2dc3013478c59c16d2433d95923aa
--- /dev/null
+++ b/packages/desktop-client/src/components/responsive/wide.ts
@@ -0,0 +1,11 @@
+export { default as Budget } from '../budget';
+
+export { default as Schedules } from '../schedules';
+export { default as EditSchedule } from '../schedules/EditSchedule';
+export { default as LinkSchedule } from '../schedules/LinkSchedule';
+export { default as DiscoverSchedules } from '../schedules/DiscoverSchedules';
+
+export { default as GoCardlessLink } from '../gocardless/GoCardlessLink';
+
+export { default as Accounts } from '../accounts/Account';
+export { default as Account } from '../accounts/Account';
diff --git a/packages/desktop-client/src/components/transactions/MobileTransaction.js b/packages/desktop-client/src/components/transactions/MobileTransaction.js
index 61c3b533e54cb26b80611c365887b87ef8cbfbdf..032870e190dae27743bc67597a7af13fc3388b9c 100644
--- a/packages/desktop-client/src/components/transactions/MobileTransaction.js
+++ b/packages/desktop-client/src/components/transactions/MobileTransaction.js
@@ -11,6 +11,7 @@ import { useListBox, useListBoxSection, useOption } from '@react-aria/listbox';
 import { mergeProps } from '@react-aria/utils';
 import { Item, Section } from '@react-stately/collections';
 import { useListState } from '@react-stately/list';
+import { css } from 'glamor';
 import memoizeOne from 'memoize-one';
 
 import * as monthUtils from 'loot-core/src/shared/months';
@@ -408,8 +409,7 @@ function ListBoxSection({ section, state }) {
       {section.rendered && (
         <div
           {...headingProps}
-          style={{
-            ...styles.smallText,
+          {...css(styles.smallText, {
             backgroundColor: colors.n10,
             borderBottom: `1px solid ${colors.n9}`,
             borderTop: `1px solid ${colors.n9}`,
@@ -422,7 +422,7 @@ function ListBoxSection({ section, state }) {
             top: '0',
             width: '100%',
             zIndex: zIndices.SECTION_HEADING,
-          }}
+          })}
         >
           {section.rendered}
         </div>
diff --git a/packages/desktop-client/src/components/util/LoadComponent.tsx b/packages/desktop-client/src/components/util/LoadComponent.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..956be6ba7216beda0804518bc944ee39cf6f562f
--- /dev/null
+++ b/packages/desktop-client/src/components/util/LoadComponent.tsx
@@ -0,0 +1,54 @@
+import { type ComponentType, useEffect, useState } from 'react';
+
+import AnimatedLoading from '../../icons/AnimatedLoading';
+import { colors, styles } from '../../style';
+import { Block, View } from '../common';
+
+type ProplessComponent = ComponentType<Record<string, never>>;
+type LoadComponentProps<K extends string> = {
+  name: K;
+  message?: string;
+  importer: () => Promise<{ [key in K]: ProplessComponent }>;
+};
+export function LoadComponent<K extends string>(props: LoadComponentProps<K>) {
+  // need to set `key` so the component is reloaded when the name changes
+  // otherwise the old component will be rendered while the new one is being loaded
+  return <LoadComponentInner key={props.name} {...props} />;
+}
+
+function LoadComponentInner<K extends string>({
+  name,
+  message,
+  importer,
+}: LoadComponentProps<K>) {
+  let [Component, setComponent] = useState<ProplessComponent | null>(null);
+  useEffect(() => {
+    importer().then(module => setComponent(() => module[name]));
+  }, [name, importer]);
+
+  if (!Component) {
+    return (
+      <View
+        style={[
+          {
+            flex: 1,
+            gap: 20,
+            justifyContent: 'center',
+            alignItems: 'center',
+          },
+          styles.delayedFadeIn,
+        ]}
+      >
+        {message && (
+          <Block style={{ marginBottom: 20, fontSize: 18 }}>{message}</Block>
+        )}
+        <AnimatedLoading width={25} color={colors.n1} />
+      </View>
+    );
+  }
+
+  // console.log(
+  //   `rendering <${Component.displayName || Component.name} /> as ${name}`,
+  // );
+  return <Component />;
+}
diff --git a/packages/desktop-client/src/fonts.scss b/packages/desktop-client/src/fonts.scss
index b36437aff056bc0462806428ea7859e7c2740dc5..7e1ee6cc8ba2b97626b3c34a1013219521cca603 100644
--- a/packages/desktop-client/src/fonts.scss
+++ b/packages/desktop-client/src/fonts.scss
@@ -1,2 +1,2 @@
 @use '~inter-ui/variable';
-@include variable.all;
+@include variable.default;
diff --git a/packages/desktop-client/src/style.tsx b/packages/desktop-client/src/style.tsx
index 5e3807eee2f4856e45587110e0e63306fc965969..49a7d05a5d07e4470fa275b5bb6dc987624497f9 100644
--- a/packages/desktop-client/src/style.tsx
+++ b/packages/desktop-client/src/style.tsx
@@ -176,7 +176,7 @@ export const styles = {
       '0%': { opacity: 0 },
       '100%': { opacity: 1 },
     }),
-    animationDuration: '0.2s',
+    animationDuration: '1s',
     animationFillMode: 'both',
     animationDelay: '0.5s',
   },
diff --git a/packages/desktop-client/src/util/withThemeColor.tsx b/packages/desktop-client/src/util/withThemeColor.tsx
index f2615e515c5d86604276d32017e347c09b0666cf..c146b60aae94e69e39a10f4d8409b1ee3ceb6d6b 100644
--- a/packages/desktop-client/src/util/withThemeColor.tsx
+++ b/packages/desktop-client/src/util/withThemeColor.tsx
@@ -2,6 +2,10 @@ import React, { Component } from 'react';
 
 export const withThemeColor = color => WrappedComponent => {
   class WithThemeColor extends Component {
+    static displayName = `withThemeColor(${
+      WrappedComponent.displayName || WrappedComponent.name
+    })`;
+
     componentDidMount() {
       setThemeColor(color);
     }
diff --git a/upcoming-release-notes/1240.md b/upcoming-release-notes/1240.md
new file mode 100644
index 0000000000000000000000000000000000000000..6f76beeb829bf54058d4cc881a31616ec974cebb
--- /dev/null
+++ b/upcoming-release-notes/1240.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [j-f1]
+---
+
+Avoid downloading code for the desktop UI on mobile and vice versa