diff --git a/assets/audio/sfx/launch-done.mp3 b/assets/audio/sfx/launch-done.mp3
new file mode 100644
index 0000000..1f456f7
Binary files /dev/null and b/assets/audio/sfx/launch-done.mp3 differ
diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json
index 271a347..bb83128 100644
--- a/assets/translations/en-US.json
+++ b/assets/translations/en-US.json
@@ -939,5 +939,7 @@
   "settingsSoundEffects": "Sound Effects",
   "settingsSoundEffectsDescription": "Enable the sound effects around the app.",
   "settingsResetMemorizedWindowSize": "Reset Window Size",
-  "settingsResetMemorizedWindowSizeDescription": "Reset the memorized window size, and set it to the default size."
+  "settingsResetMemorizedWindowSizeDescription": "Reset the memorized window size, and set it to the default size.",
+  "chatDirect": "Direct Messages",
+  "back": "返回"
 }
diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json
index c33c6a2..c0fc6fc 100644
--- a/assets/translations/zh-CN.json
+++ b/assets/translations/zh-CN.json
@@ -936,5 +936,7 @@
   "settingsSoundEffects": "声音效果",
   "settingsSoundEffectsDescription": "在一些场合下启用声音特效。",
   "settingsResetMemorizedWindowSize": "重置窗口大小",
-  "settingsResetMemorizedWindowSizeDescription": "重置记忆的窗口大小,以重新设置为默认大小。"
+  "settingsResetMemorizedWindowSizeDescription": "重置记忆的窗口大小,以重新设置为默认大小。",
+  "chatDirect": "私信",
+  "back": "返回"
 }
diff --git a/lib/main.dart b/lib/main.dart
index cde9f03..c92383b 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -347,7 +347,7 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
         if (!mounted) return;
         _setPhaseText('keyPair');
         final kp = context.read<KeyPairProvider>();
-        await kp.reloadActive();
+        kp.reloadActive();
         kp.listen();
       } catch (_) {}
       if (ua.isAuthorized) {
@@ -396,8 +396,8 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
     final cfg = context.read<ConfigProvider>();
     if (!cfg.soundEffects) return;
 
-    final player = AudioPlayer(playerId: 'launch-intro-player');
-    await player.play(AssetSource('audio/sfx/launch-intro.mp3'), volume: 0.5);
+    final player = AudioPlayer(playerId: 'launch-done-player');
+    await player.play(AssetSource('audio/sfx/launch-done.mp3'), volume: 0.8);
     player.onPlayerComplete.listen((_) {
       player.dispose();
     });
diff --git a/lib/providers/config.dart b/lib/providers/config.dart
index 12113f3..166a298 100644
--- a/lib/providers/config.dart
+++ b/lib/providers/config.dart
@@ -13,7 +13,6 @@ const kNetworkServerStoreKey = 'app_server_url';
 const kAppbarTransparentStoreKey = 'app_bar_transparent';
 const kAppBackgroundStoreKey = 'app_has_background';
 const kAppColorSchemeStoreKey = 'app_color_scheme';
-const kAppDrawerPreferCollapse = 'app_drawer_prefer_collapse';
 const kAppNotifyWithHaptic = 'app_notify_with_haptic';
 const kAppExpandPostLink = 'app_expand_post_link';
 const kAppExpandChatLink = 'app_expand_chat_link';
@@ -47,27 +46,17 @@ class ConfigProvider extends ChangeNotifier {
   }
 
   bool drawerIsCollapsed = false;
-  bool drawerIsExpanded = false;
 
   void calcDrawerSize(BuildContext context, {bool withMediaQuery = false}) {
     bool newDrawerIsCollapsed = false;
-    bool newDrawerIsExpanded = false;
     if (withMediaQuery) {
       newDrawerIsCollapsed = MediaQuery.of(context).size.width < 600;
-      newDrawerIsExpanded = MediaQuery.of(context).size.width >= 601;
     } else {
       final rpb = ResponsiveBreakpoints.of(context);
       newDrawerIsCollapsed = rpb.smallerOrEqualTo(MOBILE);
-      newDrawerIsExpanded = rpb.largerThan(TABLET)
-          ? (prefs.getBool(kAppDrawerPreferCollapse) ?? false)
-              ? false
-              : true
-          : false;
     }
 
-    if (newDrawerIsExpanded != drawerIsExpanded ||
-        newDrawerIsCollapsed != drawerIsCollapsed) {
-      drawerIsExpanded = newDrawerIsExpanded;
+    if (newDrawerIsCollapsed != drawerIsCollapsed) {
       drawerIsCollapsed = newDrawerIsCollapsed;
       notifyListeners();
     }
diff --git a/lib/providers/navigation.dart b/lib/providers/navigation.dart
index ec8e037..faacbec 100644
--- a/lib/providers/navigation.dart
+++ b/lib/providers/navigation.dart
@@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
 import 'package:go_router/go_router.dart';
 import 'package:material_symbols_icons/symbols.dart';
 import 'package:shared_preferences/shared_preferences.dart';
-import 'package:surface/types/realm.dart';
 
 class AppNavListItem {
   final String title;
@@ -60,11 +59,6 @@ class NavigationProvider extends ChangeNotifier {
       screen: 'chat',
       label: 'screenChat',
     ),
-    AppNavDestination(
-      icon: Icon(Symbols.account_circle, weight: 400, opticalSize: 20),
-      screen: 'account',
-      label: 'screenAccount',
-    ),
     AppNavDestination(
       icon: Icon(Symbols.group, weight: 400, opticalSize: 20),
       screen: 'realm',
@@ -75,6 +69,11 @@ class NavigationProvider extends ChangeNotifier {
       screen: 'news',
       label: 'screenNews',
     ),
+    AppNavDestination(
+      icon: Icon(Symbols.settings, weight: 400, opticalSize: 20),
+      screen: 'settings',
+      label: 'screenSettings',
+    ),
   ];
   static const List<String> kDefaultPinnedDestination = [
     'home',
@@ -135,11 +134,4 @@ class NavigationProvider extends ChangeNotifier {
     _currentIndex = idx;
     notifyListeners();
   }
-
-  SnRealm? focusedRealm;
-
-  void setFocusedRealm(SnRealm? realm) {
-    focusedRealm = realm;
-    notifyListeners();
-  }
 }
diff --git a/lib/providers/notification.dart b/lib/providers/notification.dart
index b592a27..bbb503d 100644
--- a/lib/providers/notification.dart
+++ b/lib/providers/notification.dart
@@ -105,6 +105,7 @@ class NotificationProvider extends ChangeNotifier {
           if (now.day == 1 && now.month == 4) {
             _notifySoundPlayer.play(
               AssetSource('audio/notify/metal-pipe.mp3'),
+              volume: 0.6,
             );
           }
         }
diff --git a/lib/router.dart b/lib/router.dart
index e8a8926..fe092a0 100644
--- a/lib/router.dart
+++ b/lib/router.dart
@@ -72,8 +72,8 @@ final _appRoutes = [
   ),
   GoRoute(
     path: '/posts',
-    name: 'explore',
-    builder: (context, state) => const ExploreScreen(),
+    name: 'posts',
+    builder: (_, __) => const SizedBox.shrink(),
     routes: [
       GoRoute(
         path: '/draft',
@@ -111,156 +111,194 @@ final _appRoutes = [
               state.uri.queryParameters['categories']?.split(','),
         ),
       ),
+    ],
+  ),
+  ShellRoute(
+    builder: (context, state, child) => ResponsiveScaffold(
+      asideFlex: 2,
+      contentFlex: 3,
+      aside: const ExploreScreen(),
+      child: child,
+    ),
+    routes: [
+      GoRoute(
+        path: '/explore',
+        name: 'explore',
+        builder: (context, state) => const ResponsiveScaffoldLanding(
+          child: ExploreScreen(),
+        ),
+      ),
+      GoRoute(
+        path: '/posts/:slug',
+        name: 'postDetail',
+        builder: (context, state) => PostDetailScreen(
+          key: ValueKey(state.pathParameters['slug']!),
+          slug: state.pathParameters['slug']!,
+          preload: state.extra as SnPost?,
+        ),
+      ),
       GoRoute(
         path: '/publishers/:name',
         name: 'postPublisher',
         builder: (context, state) =>
             PostPublisherScreen(name: state.pathParameters['name']!),
       ),
-      GoRoute(
-        path: '/:slug',
-        name: 'postDetail',
-        builder: (context, state) => PostDetailScreen(
-          slug: state.pathParameters['slug']!,
-          preload: state.extra as SnPost?,
-        ),
-      ),
     ],
   ),
-  GoRoute(
-    path: '/account',
-    name: 'account',
-    builder: (context, state) => const AccountScreen(),
+  ShellRoute(
+    builder: (context, state, child) => ResponsiveScaffold(
+      aside: const AccountScreen(),
+      child: child,
+    ),
     routes: [
       GoRoute(
-        path: '/punishments',
-        name: 'accountPunishments',
-        builder: (context, state) => const PunishmentsScreen(),
-      ),
-      GoRoute(
-        path: '/programs',
-        name: 'accountProgram',
-        builder: (context, state) => const AccountProgramScreen(),
-      ),
-      GoRoute(
-        path: '/contacts',
-        name: 'accountContactMethods',
-        builder: (context, state) => const AccountContactMethod(),
-      ),
-      GoRoute(
-        path: '/events',
-        name: 'accountActionEvents',
-        builder: (context, state) => const ActionEventScreen(),
-      ),
-      GoRoute(
-        path: '/tickets',
-        name: 'accountAuthTickets',
-        builder: (context, state) => const AccountAuthTicket(),
-      ),
-      GoRoute(
-        path: '/badges',
-        name: 'accountBadges',
-        builder: (context, state) => const AccountBadgesScreen(),
-      ),
-      GoRoute(
-        path: '/wallet',
-        name: 'accountWallet',
-        builder: (context, state) => const WalletScreen(),
-      ),
-      GoRoute(
-        path: '/keypairs',
-        name: 'accountKeyPairs',
-        builder: (context, state) => const KeyPairScreen(),
-      ),
-      GoRoute(
-        path: '/settings',
-        name: 'accountSettings',
-        builder: (context, state) => AccountSettingsScreen(),
+        path: '/account',
+        name: 'account',
+        builder: (context, state) =>
+            const ResponsiveScaffoldLanding(child: AccountScreen()),
         routes: [
           GoRoute(
-            path: '/notify',
-            name: 'accountSettingsNotify',
-            builder: (context, state) => const AccountNotifyPrefsScreen(),
+            path: '/punishments',
+            name: 'accountPunishments',
+            builder: (context, state) => const PunishmentsScreen(),
           ),
           GoRoute(
-            path: '/auth',
-            name: 'accountSettingsSecurity',
-            builder: (context, state) => const AccountSecurityPrefsScreen(),
+            path: '/programs',
+            name: 'accountProgram',
+            builder: (context, state) => const AccountProgramScreen(),
+          ),
+          GoRoute(
+            path: '/contacts',
+            name: 'accountContactMethods',
+            builder: (context, state) => const AccountContactMethod(),
+          ),
+          GoRoute(
+            path: '/events',
+            name: 'accountActionEvents',
+            builder: (context, state) => const ActionEventScreen(),
+          ),
+          GoRoute(
+            path: '/tickets',
+            name: 'accountAuthTickets',
+            builder: (context, state) => const AccountAuthTicket(),
+          ),
+          GoRoute(
+            path: '/badges',
+            name: 'accountBadges',
+            builder: (context, state) => const AccountBadgesScreen(),
+          ),
+          GoRoute(
+            path: '/wallet',
+            name: 'accountWallet',
+            builder: (context, state) => const WalletScreen(),
+          ),
+          GoRoute(
+            path: '/keypairs',
+            name: 'accountKeyPairs',
+            builder: (context, state) => const KeyPairScreen(),
+          ),
+          GoRoute(
+            path: '/settings',
+            name: 'accountSettings',
+            builder: (context, state) => AccountSettingsScreen(),
+            routes: [
+              GoRoute(
+                path: '/notify',
+                name: 'accountSettingsNotify',
+                builder: (context, state) => const AccountNotifyPrefsScreen(),
+              ),
+              GoRoute(
+                path: '/auth',
+                name: 'accountSettingsSecurity',
+                builder: (context, state) => const AccountSecurityPrefsScreen(),
+              ),
+            ],
+          ),
+          GoRoute(
+            path: '/settings/factors',
+            name: 'factorSettings',
+            builder: (context, state) => FactorSettingsScreen(),
+          ),
+          GoRoute(
+            path: '/profile/edit',
+            name: 'accountProfileEdit',
+            builder: (context, state) => ProfileEditScreen(),
+          ),
+          GoRoute(
+            path: '/publishers',
+            name: 'accountPublishers',
+            builder: (context, state) => PublisherScreen(),
+          ),
+          GoRoute(
+            path: '/publishers/new',
+            name: 'accountPublisherNew',
+            builder: (context, state) => AccountPublisherNewScreen(),
+          ),
+          GoRoute(
+            path: '/publishers/edit/:name',
+            name: 'accountPublisherEdit',
+            builder: (context, state) => AccountPublisherEditScreen(
+              name: state.pathParameters['name']!,
+            ),
           ),
         ],
       ),
-      GoRoute(
-        path: '/settings/factors',
-        name: 'factorSettings',
-        builder: (context, state) => FactorSettingsScreen(),
-      ),
-      GoRoute(
-        path: '/profile/edit',
-        name: 'accountProfileEdit',
-        builder: (context, state) => ProfileEditScreen(),
-      ),
-      GoRoute(
-        path: '/publishers',
-        name: 'accountPublishers',
-        builder: (context, state) => PublisherScreen(),
-      ),
-      GoRoute(
-        path: '/publishers/new',
-        name: 'accountPublisherNew',
-        builder: (context, state) => AccountPublisherNewScreen(),
-      ),
-      GoRoute(
-        path: '/publishers/edit/:name',
-        name: 'accountPublisherEdit',
-        builder: (context, state) => AccountPublisherEditScreen(
-          name: state.pathParameters['name']!,
-        ),
-      ),
-      GoRoute(
-        path: '/profile/:name',
-        name: 'accountProfilePage',
-        pageBuilder: (context, state) => NoTransitionPage(
-          child: UserScreen(name: state.pathParameters['name']!),
-        ),
-      ),
     ],
   ),
   GoRoute(
-    path: '/chat',
-    name: 'chat',
-    builder: (context, state) => const ChatScreen(),
+    path: '/accounts/:name',
+    name: 'accountProfilePage',
+    pageBuilder: (context, state) => NoTransitionPage(
+      child: UserScreen(name: state.pathParameters['name']!),
+    ),
+  ),
+  ShellRoute(
+    builder: (context, state, child) =>
+        ResponsiveScaffold(aside: const ChatScreen(), child: child),
     routes: [
       GoRoute(
-        path: '/:scope/:alias',
-        name: 'chatRoom',
-        builder: (context, state) => ChatRoomScreen(
-          scope: state.pathParameters['scope']!,
-          alias: state.pathParameters['alias']!,
-          extra: state.extra as ChatRoomScreenExtra?,
-        ),
-      ),
-      GoRoute(
-        path: '/:scope/:alias/call',
-        name: 'chatCallRoom',
-        builder: (context, state) => CallRoomScreen(
-          scope: state.pathParameters['scope']!,
-          alias: state.pathParameters['alias']!,
-        ),
-      ),
-      GoRoute(
-        path: '/:scope/:alias/detail',
-        name: 'channelDetail',
-        builder: (context, state) => ChannelDetailScreen(
-          scope: state.pathParameters['scope']!,
-          alias: state.pathParameters['alias']!,
-        ),
-      ),
-      GoRoute(
-        path: '/manage',
-        name: 'chatManage',
-        builder: (context, state) => ChatManageScreen(
-          editingChannelAlias: state.uri.queryParameters['editing'],
+        path: '/chat',
+        name: 'chat',
+        builder: (context, state) => const ResponsiveScaffoldLanding(
+          child: ChatScreen(),
         ),
+        routes: [
+          GoRoute(
+            path: '/:scope/:alias',
+            name: 'chatRoom',
+            builder: (context, state) => ChatRoomScreen(
+              key: ValueKey(
+                '${state.pathParameters['scope']!}:${state.pathParameters['alias']!}',
+              ),
+              scope: state.pathParameters['scope']!,
+              alias: state.pathParameters['alias']!,
+              extra: state.extra as ChatRoomScreenExtra?,
+            ),
+          ),
+          GoRoute(
+            path: '/:scope/:alias/call',
+            name: 'chatCallRoom',
+            builder: (context, state) => CallRoomScreen(
+              scope: state.pathParameters['scope']!,
+              alias: state.pathParameters['alias']!,
+            ),
+          ),
+          GoRoute(
+            path: '/:scope/:alias/detail',
+            name: 'channelDetail',
+            builder: (context, state) => ChannelDetailScreen(
+              scope: state.pathParameters['scope']!,
+              alias: state.pathParameters['alias']!,
+            ),
+          ),
+          GoRoute(
+            path: '/manage',
+            name: 'chatManage',
+            builder: (context, state) => ChatManageScreen(
+              editingChannelAlias: state.uri.queryParameters['editing'],
+            ),
+          ),
+        ],
       ),
     ],
   ),
diff --git a/lib/screens/account.dart b/lib/screens/account.dart
index 8fa83e1..e5d3feb 100644
--- a/lib/screens/account.dart
+++ b/lib/screens/account.dart
@@ -110,6 +110,7 @@ class AccountScreen extends StatelessWidget {
     final sn = context.read<SnNetworkProvider>();
 
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: AutoAppBarLeading(),
         title: Text("screenAccount").tr(),
@@ -141,15 +142,6 @@ class AccountScreen extends StatelessWidget {
                 ],
               )
             : null,
-        actions: [
-          IconButton(
-            icon: const Icon(Symbols.settings, fill: 1),
-            onPressed: () {
-              GoRouter.of(context).pushNamed('settings');
-            },
-          ),
-          const Gap(8),
-        ],
       ),
       body: SingleChildScrollView(
         child: ua.isAuthorized
diff --git a/lib/screens/account/action_events.dart b/lib/screens/account/action_events.dart
index d891a62..bc8e466 100644
--- a/lib/screens/account/action_events.dart
+++ b/lib/screens/account/action_events.dart
@@ -59,6 +59,7 @@ class _ActionEventScreenState extends State<ActionEventScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: const PageBackButton(),
         title: Text('accountActionEvent').tr(),
diff --git a/lib/screens/account/auth_tickets.dart b/lib/screens/account/auth_tickets.dart
index eb59662..de13ad7 100644
--- a/lib/screens/account/auth_tickets.dart
+++ b/lib/screens/account/auth_tickets.dart
@@ -91,6 +91,7 @@ class _AccountAuthTicketState extends State<AccountAuthTicket> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: const PageBackButton(),
         title: Text('accountAuthTickets').tr(),
diff --git a/lib/screens/account/badges.dart b/lib/screens/account/badges.dart
index 86fe9c9..660583d 100644
--- a/lib/screens/account/badges.dart
+++ b/lib/screens/account/badges.dart
@@ -70,6 +70,7 @@ class _AccountBadgesScreenState extends State<AccountBadgesScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         title: Text('screenAccountBadges').tr(),
       ),
diff --git a/lib/screens/account/contact_methods.dart b/lib/screens/account/contact_methods.dart
index ae6f8fa..99607ac 100644
--- a/lib/screens/account/contact_methods.dart
+++ b/lib/screens/account/contact_methods.dart
@@ -69,6 +69,7 @@ class _AccountContactMethodState extends State<AccountContactMethod> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: const PageBackButton(),
         title: Text('accountContactMethods').tr(),
diff --git a/lib/screens/account/factor_settings.dart b/lib/screens/account/factor_settings.dart
index 56e63a7..6bb7b66 100644
--- a/lib/screens/account/factor_settings.dart
+++ b/lib/screens/account/factor_settings.dart
@@ -16,7 +16,11 @@ final Map<int, (String, String, IconData)> kFactorTypes = {
   0: ('authFactorPassword', 'authFactorPasswordDescription', Symbols.password),
   1: ('authFactorEmail', 'authFactorEmailDescription', Symbols.email),
   2: ('authFactorTOTP', 'authFactorTOTPDescription', Symbols.timer),
-  3: ('authFactorInAppNotify', 'authFactorInAppNotifyDescription', Symbols.notifications_active),
+  3: (
+    'authFactorInAppNotify',
+    'authFactorInAppNotifyDescription',
+    Symbols.notifications_active
+  ),
 };
 
 class FactorSettingsScreen extends StatefulWidget {
@@ -36,7 +40,10 @@ class _FactorSettingsScreenState extends State<FactorSettingsScreen> {
       final sn = context.read<SnNetworkProvider>();
       final resp = await sn.client.get('/cgi/id/users/me/factors');
       _factors = List<SnAuthFactor>.from(
-        resp.data?.map((e) => SnAuthFactor.fromJson(e as Map<String, dynamic>)).toList() ?? [],
+        resp.data
+                ?.map((e) => SnAuthFactor.fromJson(e as Map<String, dynamic>))
+                .toList() ??
+            [],
       );
     } catch (err) {
       if (!mounted) return;
@@ -55,6 +62,7 @@ class _FactorSettingsScreenState extends State<FactorSettingsScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: PageBackButton(),
         title: Text('screenFactorSettings').tr(),
@@ -96,7 +104,8 @@ class _FactorSettingsScreenState extends State<FactorSettingsScreen> {
                     return ListTile(
                       title: Text(kFactorTypes[ele.type]!.$1).tr(),
                       subtitle: Text(kFactorTypes[ele.type]!.$2).tr(),
-                      contentPadding: const EdgeInsets.only(left: 24, right: 12),
+                      contentPadding:
+                          const EdgeInsets.only(left: 24, right: 12),
                       leading: Icon(kFactorTypes[ele.type]!.$3),
                       trailing: IconButton(
                         icon: const Icon(Symbols.close),
@@ -105,14 +114,17 @@ class _FactorSettingsScreenState extends State<FactorSettingsScreen> {
                                 context
                                     .showConfirmDialog(
                                   'authFactorDelete'.tr(),
-                                  'authFactorDeleteDescription'.tr(args: [kFactorTypes[ele.type]!.$1.tr()]),
+                                  'authFactorDeleteDescription'.tr(
+                                      args: [kFactorTypes[ele.type]!.$1.tr()]),
                                 )
                                     .then((val) async {
                                   if (!val) return;
                                   try {
                                     if (!context.mounted) return;
-                                    final sn = context.read<SnNetworkProvider>();
-                                    await sn.client.delete('/cgi/id/users/me/factors/${ele.id}');
+                                    final sn =
+                                        context.read<SnNetworkProvider>();
+                                    await sn.client.delete(
+                                        '/cgi/id/users/me/factors/${ele.id}');
                                     _fetchFactors();
                                   } catch (err) {
                                     if (!context.mounted) return;
@@ -191,7 +203,9 @@ class _FactorNewDialogState extends State<_FactorNewDialog> {
               value: _factorType,
               items: kFactorTypes.entries.map(
                 (ele) {
-                  final contains = widget.currentlyHave.map((ele) => ele.type).contains(ele.key);
+                  final contains = widget.currentlyHave
+                      .map((ele) => ele.type)
+                      .contains(ele.key);
                   return DropdownMenuItem<int>(
                     enabled: !contains,
                     value: ele.key,
diff --git a/lib/screens/account/keypairs.dart b/lib/screens/account/keypairs.dart
index 8360452..61423a9 100644
--- a/lib/screens/account/keypairs.dart
+++ b/lib/screens/account/keypairs.dart
@@ -37,6 +37,7 @@ class _KeyPairScreenState extends State<KeyPairScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         title: Text('screenKeyPairs').tr(),
       ),
diff --git a/lib/screens/account/prefs/notify.dart b/lib/screens/account/prefs/notify.dart
index b3da351..957c48e 100644
--- a/lib/screens/account/prefs/notify.dart
+++ b/lib/screens/account/prefs/notify.dart
@@ -75,6 +75,7 @@ class _AccountNotifyPrefsScreenState extends State<AccountNotifyPrefsScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: const PageBackButton(),
         title: Text('accountSettingsNotify').tr(),
diff --git a/lib/screens/account/prefs/security.dart b/lib/screens/account/prefs/security.dart
index 9d6c90c..9d2d071 100644
--- a/lib/screens/account/prefs/security.dart
+++ b/lib/screens/account/prefs/security.dart
@@ -70,6 +70,7 @@ class _AccountSecurityPrefsScreenState
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: const PageBackButton(),
         title: Text('accountSettingsSecurity').tr(),
diff --git a/lib/screens/account/profile_edit.dart b/lib/screens/account/profile_edit.dart
index 2e2696f..ba135a2 100644
--- a/lib/screens/account/profile_edit.dart
+++ b/lib/screens/account/profile_edit.dart
@@ -66,37 +66,40 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
     _locationController.text = prof.profile!.location;
     _avatar = prof.avatar;
     _banner = prof.banner;
-    _links = prof.profile!.links.entries.map((ele) => (ele.key, ele.value)).toList();
+    _links =
+        prof.profile!.links.entries.map((ele) => (ele.key, ele.value)).toList();
     _birthday = prof.profile!.birthday?.toLocal();
     if (_birthday != null) {
-      _birthdayController.text = DateFormat(_kDateFormat).format(prof.profile!.birthday!.toLocal());
+      _birthdayController.text =
+          DateFormat(_kDateFormat).format(prof.profile!.birthday!.toLocal());
     }
   }
 
   void _selectBirthday() async {
     await showCupertinoModalPopup<DateTime?>(
       context: context,
-      builder:
-          (BuildContext context) => Container(
-            height: 216,
-            padding: const EdgeInsets.only(top: 6.0),
-            margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
-            color: Theme.of(context).colorScheme.surface,
-            child: SafeArea(
-              top: false,
-              child: CupertinoDatePicker(
-                initialDateTime: _birthday?.toLocal(),
-                mode: CupertinoDatePickerMode.date,
-                use24hFormat: true,
-                onDateTimeChanged: (DateTime newDate) {
-                  setState(() {
-                    _birthday = newDate;
-                    _birthdayController.text = DateFormat(_kDateFormat).format(_birthday!);
-                  });
-                },
-              ),
-            ),
+      builder: (BuildContext context) => Container(
+        height: 216,
+        padding: const EdgeInsets.only(top: 6.0),
+        margin:
+            EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
+        color: Theme.of(context).colorScheme.surface,
+        child: SafeArea(
+          top: false,
+          child: CupertinoDatePicker(
+            initialDateTime: _birthday?.toLocal(),
+            mode: CupertinoDatePickerMode.date,
+            use24hFormat: true,
+            onDateTimeChanged: (DateTime newDate) {
+              setState(() {
+                _birthday = newDate;
+                _birthdayController.text =
+                    DateFormat(_kDateFormat).format(_birthday!);
+              });
+            },
           ),
+        ),
+      ),
     );
   }
 
@@ -109,29 +112,32 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
 
     Uint8List? rawBytes;
     if (!skipCrop) {
-      final ImageProvider imageProvider = kIsWeb ? NetworkImage(image.path) : FileImage(File(image.path));
-      final aspectRatios =
-          place == 'banner' ? [CropAspectRatio(width: 16, height: 7)] : [CropAspectRatio(width: 1, height: 1)];
-      final result =
-          (!kIsWeb && (Platform.isIOS || Platform.isMacOS))
-              ? await showCupertinoImageCropper(
-                // ignore: use_build_context_synchronously
-                context,
-                allowedAspectRatios: aspectRatios,
-                imageProvider: imageProvider,
-              )
-              : await showMaterialImageCropper(
-                // ignore: use_build_context_synchronously
-                context,
-                allowedAspectRatios: aspectRatios,
-                imageProvider: imageProvider,
-              );
+      final ImageProvider imageProvider =
+          kIsWeb ? NetworkImage(image.path) : FileImage(File(image.path));
+      final aspectRatios = place == 'banner'
+          ? [CropAspectRatio(width: 16, height: 7)]
+          : [CropAspectRatio(width: 1, height: 1)];
+      final result = (!kIsWeb && (Platform.isIOS || Platform.isMacOS))
+          ? await showCupertinoImageCropper(
+              // ignore: use_build_context_synchronously
+              context,
+              allowedAspectRatios: aspectRatios,
+              imageProvider: imageProvider,
+            )
+          : await showMaterialImageCropper(
+              // ignore: use_build_context_synchronously
+              context,
+              allowedAspectRatios: aspectRatios,
+              imageProvider: imageProvider,
+            );
 
       if (result == null) return;
 
       if (!mounted) return;
       setState(() => _isBusy = true);
-      rawBytes = (await result.uiImage.toByteData(format: ImageByteFormat.png))!.buffer.asUint8List();
+      rawBytes = (await result.uiImage.toByteData(format: ImageByteFormat.png))!
+          .buffer
+          .asUint8List();
     } else {
       if (!mounted) return;
       setState(() => _isBusy = true);
@@ -152,7 +158,8 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
 
       if (!mounted) return;
       final sn = context.read<SnNetworkProvider>();
-      await sn.client.put('/cgi/id/users/me/$place', data: {'attachment': attachment.rid});
+      await sn.client
+          .put('/cgi/id/users/me/$place', data: {'attachment': attachment.rid});
 
       if (!mounted) return;
       final ua = context.read<UserProvider>();
@@ -188,7 +195,9 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
           'location': _locationController.value.text,
           'birthday': _birthday?.toUtc().toIso8601String(),
           'links': {
-            for (final link in _links!.where((ele) => ele.$1.isNotEmpty && ele.$2.isNotEmpty)) link.$1: link.$2,
+            for (final link in _links!
+                .where((ele) => ele.$1.isNotEmpty && ele.$2.isNotEmpty))
+              link.$1: link.$2,
           },
         },
       );
@@ -235,7 +244,10 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
     final sn = context.read<SnNetworkProvider>();
 
     return AppScaffold(
-      appBar: AppBar(leading: const PageBackButton(), title: Text('screenAccountProfileEdit').tr()),
+      noBackground: true,
+      appBar: AppBar(
+          leading: const PageBackButton(),
+          title: Text('screenAccountProfileEdit').tr()),
       body: SingleChildScrollView(
         child: Column(
           crossAxisAlignment: CrossAxisAlignment.start,
@@ -253,11 +265,14 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                       child: AspectRatio(
                         aspectRatio: 16 / 9,
                         child: Container(
-                          color: Theme.of(context).colorScheme.surfaceContainerHigh,
-                          child:
-                              _banner != null
-                                  ? AutoResizeUniversalImage(sn.getAttachmentUrl(_banner!), fit: BoxFit.cover)
-                                  : const SizedBox.shrink(),
+                          color: Theme.of(context)
+                              .colorScheme
+                              .surfaceContainerHigh,
+                          child: _banner != null
+                              ? AutoResizeUniversalImage(
+                                  sn.getAttachmentUrl(_banner!),
+                                  fit: BoxFit.cover)
+                              : const SizedBox.shrink(),
                         ),
                       ),
                     ),
@@ -294,12 +309,16 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                     labelText: 'fieldUsername'.tr(),
                     helperText: 'fieldUsernameCannotEditHint'.tr(),
                   ),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ),
                 TextField(
                   controller: _nicknameController,
-                  decoration: InputDecoration(border: const UnderlineInputBorder(), labelText: 'fieldNickname'.tr()),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  decoration: InputDecoration(
+                      border: const UnderlineInputBorder(),
+                      labelText: 'fieldNickname'.tr()),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ),
                 Row(
                   children: [
@@ -311,7 +330,8 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                           border: const UnderlineInputBorder(),
                           labelText: 'fieldFirstName'.tr(),
                         ),
-                        onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                        onTapOutside: (_) =>
+                            FocusManager.instance.primaryFocus?.unfocus(),
                       ),
                     ),
                     const Gap(8),
@@ -323,7 +343,8 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                           border: const UnderlineInputBorder(),
                           labelText: 'fieldLastName'.tr(),
                         ),
-                        onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                        onTapOutside: (_) =>
+                            FocusManager.instance.primaryFocus?.unfocus(),
                       ),
                     ),
                   ],
@@ -338,7 +359,8 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                           border: const UnderlineInputBorder(),
                           labelText: 'fieldGender'.tr(),
                         ),
-                        onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                        onTapOutside: (_) =>
+                            FocusManager.instance.primaryFocus?.unfocus(),
                       ),
                     ),
                     const Gap(4),
@@ -350,7 +372,8 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                           border: const UnderlineInputBorder(),
                           labelText: 'fieldPronouns'.tr(),
                         ),
-                        onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                        onTapOutside: (_) =>
+                            FocusManager.instance.primaryFocus?.unfocus(),
                       ),
                     ),
                   ],
@@ -360,8 +383,11 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                   keyboardType: TextInputType.multiline,
                   maxLines: null,
                   minLines: 3,
-                  decoration: InputDecoration(border: const UnderlineInputBorder(), labelText: 'fieldDescription'.tr()),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  decoration: InputDecoration(
+                      border: const UnderlineInputBorder(),
+                      labelText: 'fieldDescription'.tr()),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ),
                 Row(
                   crossAxisAlignment: CrossAxisAlignment.center,
@@ -373,18 +399,21 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                           border: const UnderlineInputBorder(),
                           labelText: 'fieldTimeZone'.tr(),
                         ),
-                        onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                        onTapOutside: (_) =>
+                            FocusManager.instance.primaryFocus?.unfocus(),
                       ),
                     ),
                     const Gap(4),
                     StyledWidget(
                       IconButton(
                         icon: const Icon(Symbols.calendar_month),
-                        visualDensity: VisualDensity(horizontal: -4, vertical: -4),
+                        visualDensity:
+                            VisualDensity(horizontal: -4, vertical: -4),
                         padding: EdgeInsets.zero,
                         constraints: const BoxConstraints(),
                         onPressed: () async {
-                          _timezoneController.text = await FlutterTimezone.getLocalTimezone();
+                          _timezoneController.text =
+                              await FlutterTimezone.getLocalTimezone();
                         },
                       ),
                     ).padding(top: 6),
@@ -392,7 +421,8 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                     StyledWidget(
                       IconButton(
                         icon: const Icon(Symbols.clear),
-                        visualDensity: VisualDensity(horizontal: -4, vertical: -4),
+                        visualDensity:
+                            VisualDensity(horizontal: -4, vertical: -4),
                         padding: EdgeInsets.zero,
                         constraints: const BoxConstraints(),
                         onPressed: () {
@@ -404,13 +434,18 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                 ),
                 TextField(
                   controller: _locationController,
-                  decoration: InputDecoration(border: const UnderlineInputBorder(), labelText: 'fieldLocation'.tr()),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  decoration: InputDecoration(
+                      border: const UnderlineInputBorder(),
+                      labelText: 'fieldLocation'.tr()),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ),
                 TextField(
                   controller: _birthdayController,
                   readOnly: true,
-                  decoration: InputDecoration(border: const UnderlineInputBorder(), labelText: 'fieldBirthday'.tr()),
+                  decoration: InputDecoration(
+                      border: const UnderlineInputBorder(),
+                      labelText: 'fieldBirthday'.tr()),
                   onTap: () => _selectBirthday(),
                 ),
                 if (_links != null)
@@ -418,7 +453,8 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                     margin: const EdgeInsets.only(top: 16, bottom: 4),
                     child: Container(
                       width: double.infinity,
-                      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
+                      padding: const EdgeInsets.symmetric(
+                          horizontal: 16, vertical: 8),
                       child: Column(
                         crossAxisAlignment: CrossAxisAlignment.start,
                         children: [
@@ -427,13 +463,17 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                               Expanded(
                                 child: Text(
                                   'fieldLinks'.tr(),
-                                  style: Theme.of(context).textTheme.titleMedium!.copyWith(fontSize: 17),
+                                  style: Theme.of(context)
+                                      .textTheme
+                                      .titleMedium!
+                                      .copyWith(fontSize: 17),
                                 ),
                               ),
                               IconButton(
                                 padding: EdgeInsets.zero,
                                 constraints: const BoxConstraints(),
-                                visualDensity: VisualDensity(horizontal: -4, vertical: -4),
+                                visualDensity:
+                                    VisualDensity(horizontal: -4, vertical: -4),
                                 icon: const Icon(Symbols.add),
                                 onPressed: () {
                                   setState(() => _links!.add(('', '')));
@@ -457,7 +497,9 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                                     onChanged: (value) {
                                       _links![idx] = (value, _links![idx].$2);
                                     },
-                                    onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                                    onTapOutside: (_) => FocusManager
+                                        .instance.primaryFocus
+                                        ?.unfocus(),
                                   ),
                                 ),
                                 const Gap(8),
@@ -473,7 +515,9 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
                                     onChanged: (value) {
                                       _links![idx] = (_links![idx].$1, value);
                                     },
-                                    onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                                    onTapOutside: (_) => FocusManager
+                                        .instance.primaryFocus
+                                        ?.unfocus(),
                                   ),
                                 ),
                               ],
diff --git a/lib/screens/account/programs.dart b/lib/screens/account/programs.dart
index 74f6c8b..92bb4b7 100644
--- a/lib/screens/account/programs.dart
+++ b/lib/screens/account/programs.dart
@@ -70,6 +70,7 @@ class _AccountProgramScreenState extends State<AccountProgramScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         title: Text('accountProgram').tr(),
       ),
diff --git a/lib/screens/account/publishers/publisher_edit.dart b/lib/screens/account/publishers/publisher_edit.dart
index a388284..804b321 100644
--- a/lib/screens/account/publishers/publisher_edit.dart
+++ b/lib/screens/account/publishers/publisher_edit.dart
@@ -27,10 +27,12 @@ class AccountPublisherEditScreen extends StatefulWidget {
   const AccountPublisherEditScreen({super.key, required this.name});
 
   @override
-  State<AccountPublisherEditScreen> createState() => _AccountPublisherEditScreenState();
+  State<AccountPublisherEditScreen> createState() =>
+      _AccountPublisherEditScreenState();
 }
 
-class _AccountPublisherEditScreenState extends State<AccountPublisherEditScreen> {
+class _AccountPublisherEditScreenState
+    extends State<AccountPublisherEditScreen> {
   bool _isBusy = false;
 
   SnPublisher? _publisher;
@@ -115,29 +117,32 @@ class _AccountPublisherEditScreenState extends State<AccountPublisherEditScreen>
 
     Uint8List? rawBytes;
     if (!skipCrop) {
-      final ImageProvider imageProvider = kIsWeb ? NetworkImage(image.path) : FileImage(File(image.path));
-      final aspectRatios =
-          place == 'banner' ? [CropAspectRatio(width: 16, height: 7)] : [CropAspectRatio(width: 1, height: 1)];
-      final result =
-          (!kIsWeb && (Platform.isIOS || Platform.isMacOS))
-              ? await showCupertinoImageCropper(
-                // ignore: use_build_context_synchronously
-                context,
-                allowedAspectRatios: aspectRatios,
-                imageProvider: imageProvider,
-              )
-              : await showMaterialImageCropper(
-                // ignore: use_build_context_synchronously
-                context,
-                allowedAspectRatios: aspectRatios,
-                imageProvider: imageProvider,
-              );
+      final ImageProvider imageProvider =
+          kIsWeb ? NetworkImage(image.path) : FileImage(File(image.path));
+      final aspectRatios = place == 'banner'
+          ? [CropAspectRatio(width: 16, height: 7)]
+          : [CropAspectRatio(width: 1, height: 1)];
+      final result = (!kIsWeb && (Platform.isIOS || Platform.isMacOS))
+          ? await showCupertinoImageCropper(
+              // ignore: use_build_context_synchronously
+              context,
+              allowedAspectRatios: aspectRatios,
+              imageProvider: imageProvider,
+            )
+          : await showMaterialImageCropper(
+              // ignore: use_build_context_synchronously
+              context,
+              allowedAspectRatios: aspectRatios,
+              imageProvider: imageProvider,
+            );
 
       if (result == null) return;
 
       if (!mounted) return;
       setState(() => _isBusy = true);
-      rawBytes = (await result.uiImage.toByteData(format: ImageByteFormat.png))!.buffer.asUint8List();
+      rawBytes = (await result.uiImage.toByteData(format: ImageByteFormat.png))!
+          .buffer
+          .asUint8List();
     } else {
       if (!mounted) return;
       setState(() => _isBusy = true);
@@ -191,7 +196,10 @@ class _AccountPublisherEditScreenState extends State<AccountPublisherEditScreen>
     final sn = context.read<SnNetworkProvider>();
 
     return AppScaffold(
-      appBar: AppBar(leading: PageBackButton(), title: Text('screenAccountPublisherEdit').tr()),
+      noBackground: true,
+      appBar: AppBar(
+          leading: PageBackButton(),
+          title: Text('screenAccountPublisherEdit').tr()),
       body: SingleChildScrollView(
         child: Column(
           children: [
@@ -208,11 +216,14 @@ class _AccountPublisherEditScreenState extends State<AccountPublisherEditScreen>
                       child: AspectRatio(
                         aspectRatio: 16 / 9,
                         child: Container(
-                          color: Theme.of(context).colorScheme.surfaceContainerHigh,
-                          child:
-                              _banner != null
-                                  ? AutoResizeUniversalImage(sn.getAttachmentUrl(_banner!), fit: BoxFit.cover)
-                                  : const SizedBox.shrink(),
+                          color: Theme.of(context)
+                              .colorScheme
+                              .surfaceContainerHigh,
+                          child: _banner != null
+                              ? AutoResizeUniversalImage(
+                                  sn.getAttachmentUrl(_banner!),
+                                  fit: BoxFit.cover)
+                              : const SizedBox.shrink(),
                         ),
                       ),
                     ),
@@ -245,13 +256,15 @@ class _AccountPublisherEditScreenState extends State<AccountPublisherEditScreen>
                 labelText: 'fieldUsername'.tr(),
                 helperText: 'fieldUsernameCannotEditHint'.tr(),
               ),
-              onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+              onTapOutside: (_) =>
+                  FocusManager.instance.primaryFocus?.unfocus(),
             ),
             const Gap(4),
             TextField(
               controller: _nickController,
               decoration: InputDecoration(labelText: 'fieldNickname'.tr()),
-              onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+              onTapOutside: (_) =>
+                  FocusManager.instance.primaryFocus?.unfocus(),
             ),
             const Gap(4),
             TextField(
@@ -259,7 +272,8 @@ class _AccountPublisherEditScreenState extends State<AccountPublisherEditScreen>
               maxLines: null,
               minLines: 3,
               decoration: InputDecoration(labelText: 'fieldDescription'.tr()),
-              onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+              onTapOutside: (_) =>
+                  FocusManager.instance.primaryFocus?.unfocus(),
             ),
             const Gap(12),
             Row(
diff --git a/lib/screens/account/publishers/publisher_new.dart b/lib/screens/account/publishers/publisher_new.dart
index 9a59eec..d0f6758 100644
--- a/lib/screens/account/publishers/publisher_new.dart
+++ b/lib/screens/account/publishers/publisher_new.dart
@@ -25,7 +25,8 @@ class _AccountPublisherNewScreenState extends State<AccountPublisherNewScreen> {
 
   @override
   Widget build(BuildContext context) {
-    return  AppScaffold(
+    return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: const PageBackButton(),
         title: Text('screenAccountPublisherNew').tr(),
diff --git a/lib/screens/account/publishers/publishers.dart b/lib/screens/account/publishers/publishers.dart
index d9d2c6a..5d5d902 100644
--- a/lib/screens/account/publishers/publishers.dart
+++ b/lib/screens/account/publishers/publishers.dart
@@ -33,7 +33,8 @@ class _PublisherScreenState extends State<PublisherScreen> {
 
     try {
       final resp = await sn.client.get('/cgi/co/publishers/me');
-      final List<SnPublisher> out = List<SnPublisher>.from(resp.data?.map((e) => SnPublisher.fromJson(e)) ?? []);
+      final List<SnPublisher> out = List<SnPublisher>.from(
+          resp.data?.map((e) => SnPublisher.fromJson(e)) ?? []);
 
       if (!mounted) return;
 
@@ -81,6 +82,7 @@ class _PublisherScreenState extends State<PublisherScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: const PageBackButton(),
         title: Text('screenAccountPublishers').tr(),
@@ -93,7 +95,9 @@ class _PublisherScreenState extends State<PublisherScreen> {
             contentPadding: const EdgeInsets.symmetric(horizontal: 24),
             leading: const Icon(Symbols.add_circle),
             onTap: () {
-              GoRouter.of(context).pushNamed('accountPublisherNew').then((value) {
+              GoRouter.of(context)
+                  .pushNamed('accountPublisherNew')
+                  .then((value) {
                 if (value == true) {
                   _publishers.clear();
                   _fetchPublishers();
@@ -119,7 +123,8 @@ class _PublisherScreenState extends State<PublisherScreen> {
                     return ListTile(
                       title: Text(publisher.nick),
                       subtitle: Text('@${publisher.name}'),
-                      contentPadding: const EdgeInsets.symmetric(horizontal: 16),
+                      contentPadding:
+                          const EdgeInsets.symmetric(horizontal: 16),
                       leading: AccountImage(content: publisher.avatar),
                       trailing: PopupMenuButton(
                         itemBuilder: (BuildContext context) => [
diff --git a/lib/screens/account/punishments.dart b/lib/screens/account/punishments.dart
index abd8dce..1b3529a 100644
--- a/lib/screens/account/punishments.dart
+++ b/lib/screens/account/punishments.dart
@@ -55,6 +55,7 @@ class _PunishmentsScreenState extends State<PunishmentsScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         title: Text('accountPunishments').tr(),
         leading: PageBackButton(),
diff --git a/lib/screens/account/settings.dart b/lib/screens/account/settings.dart
index 6e9a842..7727d59 100644
--- a/lib/screens/account/settings.dart
+++ b/lib/screens/account/settings.dart
@@ -37,6 +37,7 @@ class AccountSettingsScreen extends StatelessWidget {
     final ua = context.watch<UserProvider>();
 
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: PageBackButton(),
         title: Text('screenAccountSettings').tr(),
diff --git a/lib/screens/chat.dart b/lib/screens/chat.dart
index 7068de6..62714f8 100644
--- a/lib/screens/chat.dart
+++ b/lib/screens/chat.dart
@@ -1,3 +1,5 @@
+import 'package:animations/animations.dart';
+import 'package:collection/collection.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
@@ -6,21 +8,22 @@ import 'package:go_router/go_router.dart';
 import 'package:google_fonts/google_fonts.dart';
 import 'package:material_symbols_icons/symbols.dart';
 import 'package:provider/provider.dart';
-import 'package:responsive_framework/responsive_framework.dart';
+import 'package:styled_widget/styled_widget.dart';
 import 'package:surface/providers/channel.dart';
 import 'package:surface/providers/sn_network.dart';
+import 'package:surface/providers/sn_realm.dart';
 import 'package:surface/providers/user_directory.dart';
 import 'package:surface/providers/userinfo.dart';
-import 'package:surface/screens/chat/room.dart';
 import 'package:surface/types/chat.dart';
+import 'package:surface/types/realm.dart';
 import 'package:surface/widgets/account/account_image.dart';
 import 'package:surface/widgets/account/account_select.dart';
 import 'package:surface/widgets/app_bar_leading.dart';
 import 'package:surface/widgets/dialog.dart';
 import 'package:surface/widgets/loading_indicator.dart';
-import 'package:surface/widgets/navigation/app_background.dart';
 import 'package:surface/widgets/navigation/app_scaffold.dart';
 import 'package:surface/widgets/unauthorized_hint.dart';
+import 'package:surface/widgets/universal_image.dart';
 import 'package:uuid/uuid.dart';
 
 class ChatScreen extends StatefulWidget {
@@ -38,6 +41,7 @@ class _ChatScreenState extends State<ChatScreen> {
   List<SnChannel>? _channels;
   Map<int, SnChatMessage>? _lastMessages;
   Map<int, int>? _unreadCounts;
+  Map<int, int>? _unreadCountsGrouped;
 
   Future<void> _fetchWhatsNew() async {
     final sn = context.read<SnNetworkProvider>();
@@ -45,19 +49,48 @@ class _ChatScreenState extends State<ChatScreen> {
     if (resp.data == null) return;
     final List<dynamic> out = resp.data;
     setState(() {
-      _unreadCounts = {for (var v in out) v['channel_id']: v['count']};
+      _unreadCounts ??= {};
+      _unreadCountsGrouped ??= {};
+      for (var v in out) {
+        _unreadCounts![v['channel_id']] = v['count'];
+        final channel =
+            _channels?.firstWhereOrNull((ele) => ele.id == v['channel_id']);
+        if (channel != null) {
+          if (channel.realmId != null) {
+            _unreadCountsGrouped![channel.realmId!] ??= 0;
+            _unreadCountsGrouped![channel.realmId!] =
+                (_unreadCountsGrouped![channel.realmId!]! + v['count']).toInt();
+          }
+          if (channel.type == 1) {
+            _unreadCountsGrouped![0] ??= 0;
+            _unreadCountsGrouped![0] =
+                (_unreadCountsGrouped![0]! + v['count']).toInt();
+          }
+        }
+      }
     });
   }
 
-  void _refreshChannels({bool noRemote = false}) {
+  void _refreshChannels({bool withBoost = false, bool noRemote = false}) {
+    final ct = context.read<ChatChannelProvider>();
     final ua = context.read<UserProvider>();
     if (!ua.isAuthorized) {
       setState(() => _isBusy = false);
       return;
     }
 
+    if (!withBoost) {
+      if (!noRemote) {
+        ct.refreshAvailableChannels();
+      }
+    } else {
+      setState(() {
+        _channels = ct.availableChannels;
+      });
+    }
+
     final chan = context.read<ChatChannelProvider>();
-    chan.fetchChannels(noRemote: noRemote).listen((channels) async {
+    chan.fetchChannels(noRemote: true).listen((channels) async {
       final lastMessages = await chan.getLastMessages(channels);
       _lastMessages = {for (final val in lastMessages) val.channelId: val};
       channels.sort((a, b) {
@@ -99,6 +132,7 @@ class _ChatScreenState extends State<ChatScreen> {
       ..onDone(() {
         if (!mounted) return;
         setState(() => _isBusy = false);
+        _fetchWhatsNew();
       });
   }
 
@@ -130,40 +164,51 @@ class _ChatScreenState extends State<ChatScreen> {
     }
   }
 
-  SnChannel? _focusChannel;
-
   @override
   void initState() {
     super.initState();
-    _refreshChannels();
-    _fetchWhatsNew();
+    _refreshChannels(withBoost: true);
   }
 
   void _onTapChannel(SnChannel channel) {
-    final doExpand = ResponsiveBreakpoints.of(context).largerOrEqualTo(DESKTOP);
-
-    if (doExpand) {
-      setState(() => _focusChannel = channel);
-      return;
+    setState(() => _unreadCounts?[channel.id] = 0);
+    if (ResponsiveScaffold.getIsExpand(context)) {
+      GoRouter.of(context).pushReplacementNamed(
+        'chatRoom',
+        pathParameters: {
+          'scope': channel.realm?.alias ?? 'global',
+          'alias': channel.alias,
+        },
+      ).then((value) {
+        if (mounted) {
+          setState(() => _unreadCounts?[channel.id] = 0);
+          _refreshChannels(noRemote: true);
+        }
+      });
+    } else {
+      GoRouter.of(context).pushNamed(
+        'chatRoom',
+        pathParameters: {
+          'scope': channel.realm?.alias ?? 'global',
+          'alias': channel.alias,
+        },
+      ).then((value) {
+        if (mounted) {
+          setState(() => _unreadCounts?[channel.id] = 0);
+          _refreshChannels(noRemote: true);
+        }
+      });
     }
-    GoRouter.of(context).pushNamed(
-      'chatRoom',
-      pathParameters: {
-        'scope': channel.realm?.alias ?? 'global',
-        'alias': channel.alias,
-      },
-    ).then((value) {
-      if (mounted) {
-        _unreadCounts?[channel.id] = 0;
-        setState(() => _unreadCounts?[channel.id] = 0);
-        _refreshChannels(noRemote: true);
-      }
-    });
   }
 
+  SnRealm? _focusedRealm;
+  bool _isDirect = false;
+
   @override
   Widget build(BuildContext context) {
     final ua = context.read<UserProvider>();
+    final sn = context.read<SnNetworkProvider>();
+    final rel = context.read<SnRealmProvider>();
 
     if (!ua.isAuthorized) {
       return AppScaffold(
@@ -177,10 +222,8 @@ class _ChatScreenState extends State<ChatScreen> {
       );
     }
 
-    final doExpand = ResponsiveBreakpoints.of(context).largerOrEqualTo(DESKTOP);
-
-    final chatList = AppScaffold(
-      noBackground: doExpand,
+    return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         leading: AutoAppBarLeading(),
         title: Text('screenChat').tr(),
@@ -248,64 +291,198 @@ class _ChatScreenState extends State<ChatScreen> {
       body: Column(
         children: [
           LoadingIndicator(isActive: _isBusy),
-          Expanded(
-            child: MediaQuery.removePadding(
-              context: context,
-              removeTop: true,
+          if (_channels != null && ResponsiveScaffold.getIsExpand(context))
+            Expanded(
               child: RefreshIndicator(
-                onRefresh: () => Future.wait([
-                  Future.sync(() => _refreshChannels()),
-                  _fetchWhatsNew(),
-                ]),
-                child: ListView.builder(
-                  itemCount: _channels?.length ?? 0,
-                  itemBuilder: (context, idx) {
-                    final channel = _channels![idx];
-                    final lastMessage = _lastMessages?[channel.id];
+                onRefresh: () => Future.sync(() => _refreshChannels()),
+                child: Builder(builder: (context) {
+                  final scopeList = ListView(
+                    key: const Key('realm-list-view'),
+                    padding: EdgeInsets.zero,
+                    children: [
+                      ListTile(
+                        minTileHeight: 48,
+                        leading:
+                            const Icon(Symbols.inbox_text).padding(right: 4),
+                        contentPadding: EdgeInsets.only(left: 24, right: 24),
+                        title: Text('chatDirect').tr(),
+                        trailing: Row(
+                          mainAxisSize: MainAxisSize.min,
+                          crossAxisAlignment: CrossAxisAlignment.center,
+                          children: [
+                            if (_unreadCountsGrouped?[0] != null &&
+                                (_unreadCountsGrouped?[0] ?? 0) > 0)
+                              Badge(
+                                label: Text(
+                                  _unreadCountsGrouped![0].toString(),
+                                ),
+                              ),
+                          ],
+                        ),
+                        onTap: () {
+                          setState(() => _isDirect = true);
+                        },
+                      ),
+                      ...rel.availableRealms.map((ele) {
+                        return ListTile(
+                          minTileHeight: 48,
+                          contentPadding: EdgeInsets.only(left: 20, right: 24),
+                          leading: AccountImage(
+                            content: ele.avatar,
+                            radius: 16,
+                          ),
+                          trailing: Row(
+                            mainAxisSize: MainAxisSize.min,
+                            crossAxisAlignment: CrossAxisAlignment.center,
+                            children: [
+                              if (_unreadCountsGrouped?[ele.id] != null &&
+                                  (_unreadCountsGrouped?[ele.id] ?? 0) > 0)
+                                Badge(
+                                  label: Text(
+                                    _unreadCountsGrouped![ele.id].toString(),
+                                  ),
+                                ),
+                            ],
+                          ),
+                          title: Text(ele.name),
+                          onTap: () {
+                            setState(() => _focusedRealm = ele);
+                          },
+                        );
+                      }),
+                    ],
+                  );
 
-                    return _ChatChannelEntry(
-                      channel: channel,
-                      lastMessage: lastMessage,
-                      unreadCount: _unreadCounts?[channel.id],
-                      onTap: () {
-                        if (doExpand) {
-                          _unreadCounts?[channel.id] = 0;
-                          setState(() => _focusChannel = channel);
-                          return;
-                        }
-                        _onTapChannel(channel);
-                      },
-                    );
-                  },
+                  final directChatList = ListView(
+                    key: Key('direct-chat-list-view'),
+                    padding: EdgeInsets.zero,
+                    children: [
+                      ListTile(
+                        minTileHeight: 48,
+                        leading: const Icon(Symbols.arrow_left_alt),
+                        contentPadding: EdgeInsets.only(left: 24),
+                        title: Text('back').tr(),
+                        onTap: () {
+                          setState(() => _isDirect = false);
+                        },
+                      ),
+                      const Divider(height: 1),
+                      ..._channels!.where((ele) => ele.type == 1).map(
+                        (ele) {
+                          return _ChatChannelEntry(
+                            channel: ele,
+                            unreadCount: _unreadCounts?[ele.id],
+                            lastMessage: _lastMessages?[ele.id],
+                            isCompact: true,
+                            onTap: () => _onTapChannel(ele),
+                          );
+                        },
+                      )
+                    ],
+                  );
+
+                  final realmScopedChatList = _focusedRealm == null
+                      ? const SizedBox.shrink()
+                      : ListView(
+                          key: ValueKey(_focusedRealm),
+                          padding: EdgeInsets.zero,
+                          children: [
+                            if (_focusedRealm!.banner != null)
+                              AspectRatio(
+                                aspectRatio: 16 / 9,
+                                child: AutoResizeUniversalImage(
+                                  sn.getAttachmentUrl(
+                                    _focusedRealm!.banner!,
+                                  ),
+                                  fit: BoxFit.cover,
+                                ),
+                              ),
+                            ListTile(
+                              minTileHeight: 48,
+                              tileColor: Theme.of(context)
+                                  .colorScheme
+                                  .surfaceContainer,
+                              leading: AccountImage(
+                                content: _focusedRealm!.avatar,
+                                radius: 16,
+                              ),
+                              contentPadding: EdgeInsets.only(
+                                left: 20,
+                                right: 16,
+                              ),
+                              trailing: IconButton(
+                                icon: const Icon(Symbols.close),
+                                padding: EdgeInsets.zero,
+                                constraints: const BoxConstraints(),
+                                visualDensity: VisualDensity.compact,
+                                onPressed: () {
+                                  setState(() => _focusedRealm = null);
+                                },
+                              ),
+                              title: Text(_focusedRealm!.name),
+                            ),
+                            ...(_channels!
+                                .where(
+                                    (ele) => ele.realmId == _focusedRealm?.id)
+                                .map(
+                              (ele) {
+                                return _ChatChannelEntry(
+                                  channel: ele,
+                                  unreadCount: _unreadCounts?[ele.id],
+                                  lastMessage: _lastMessages?[ele.id],
+                                  onTap: () => _onTapChannel(ele),
+                                  isCompact: true,
+                                );
+                              },
+                            ))
+                          ],
+                        );
+
+                  return PageTransitionSwitcher(
+                    duration: const Duration(milliseconds: 300),
+                    transitionBuilder: (Widget child,
+                        Animation<double> primaryAnimation,
+                        Animation<double> secondaryAnimation) {
+                      return SharedAxisTransition(
+                        animation: primaryAnimation,
+                        secondaryAnimation: secondaryAnimation,
+                        fillColor: Colors.transparent,
+                        transitionType: SharedAxisTransitionType.horizontal,
+                        child: child,
+                      );
+                    },
+                    child: (_focusedRealm == null && !_isDirect)
+                        ? scopeList
+                        : _isDirect
+                            ? directChatList
+                            : realmScopedChatList,
+                  );
+                }),
+              ),
+            )
+          else if (_channels != null)
+            Expanded(
+              child: RefreshIndicator(
+                onRefresh: () => Future.sync(() => _refreshChannels()),
+                child: ListView(
+                  key: const Key('chat-list-view'),
+                  padding: EdgeInsets.zero,
+                  children: [
+                    ...(_channels!.map((ele) {
+                      return _ChatChannelEntry(
+                        channel: ele,
+                        unreadCount: _unreadCounts?[ele.id],
+                        lastMessage: _lastMessages?[ele.id],
+                        onTap: () => _onTapChannel(ele),
+                      );
+                    }))
+                  ],
                 ),
               ),
             ),
-          ),
         ],
       ),
     );
-
-    if (doExpand) {
-      return AppBackground(
-        isRoot: true,
-        child: Row(
-          children: [
-            SizedBox(width: 340, child: chatList),
-            const VerticalDivider(width: 1),
-            if (_focusChannel != null)
-              Expanded(
-                child: ChatRoomScreen(
-                  key: ValueKey(_focusChannel!.id),
-                  scope: _focusChannel!.realm?.alias ?? 'global',
-                  alias: _focusChannel!.alias,
-                ),
-              ),
-          ],
-        ),
-      );
-    }
-
-    return chatList;
   }
 }
 
@@ -314,11 +491,13 @@ class _ChatChannelEntry extends StatelessWidget {
   final int? unreadCount;
   final SnChatMessage? lastMessage;
   final Function? onTap;
+  final bool isCompact;
   const _ChatChannelEntry({
     required this.channel,
     this.unreadCount,
     this.lastMessage,
     this.onTap,
+    this.isCompact = false,
   });
 
   @override
@@ -337,6 +516,34 @@ class _ChatChannelEntry extends StatelessWidget {
         ? ud.getFromCache(otherMember.accountId)?.nick ?? channel.name
         : channel.name;
 
+    if (isCompact) {
+      return ListTile(
+        minTileHeight: 48,
+        contentPadding:
+            EdgeInsets.only(left: otherMember != null ? 20 : 24, right: 24),
+        leading: otherMember != null
+            ? AccountImage(
+                content: ud.getFromCache(otherMember.accountId)?.avatar,
+                radius: 16,
+              )
+            : const Icon(Symbols.tag),
+        trailing: Row(
+          mainAxisSize: MainAxisSize.min,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            if (unreadCount != null && (unreadCount ?? 0) > 0)
+              Badge(
+                label: Text(unreadCount.toString()),
+              ),
+          ],
+        ),
+        title: Text(title),
+        onTap: () {
+          onTap?.call();
+        },
+      );
+    }
+
     return ListTile(
       title: Row(
         children: [
@@ -399,7 +606,7 @@ class _ChatChannelEntry extends StatelessWidget {
         content: otherMember != null
             ? ud.getFromCache(otherMember.accountId)?.avatar
             : channel.realm?.avatar,
-        fallbackWidget: const Icon(Symbols.chat, size: 20),
+        fallbackWidget: const Icon(Symbols.tag, size: 20),
       ),
       onTap: () => onTap?.call(),
     );
diff --git a/lib/screens/chat/call_room.dart b/lib/screens/chat/call_room.dart
index 5595c87..f774cd9 100644
--- a/lib/screens/chat/call_room.dart
+++ b/lib/screens/chat/call_room.dart
@@ -37,7 +37,8 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
     return Stack(
       children: [
         Container(
-          color: Theme.of(context).colorScheme.surfaceContainer.withOpacity(0.75),
+          color:
+              Theme.of(context).colorScheme.surfaceContainer.withOpacity(0.75),
           child: call.focusTrack != null
               ? InteractiveParticipantWidget(
                   isFixedAvatar: false,
@@ -72,7 +73,8 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
                       color: Theme.of(context).cardColor,
                       participant: track,
                       onTap: () {
-                        if (track.participant.sid != call.focusTrack?.participant.sid) {
+                        if (track.participant.sid !=
+                            call.focusTrack?.participant.sid) {
                           call.setFocusTrack(track);
                         }
                       },
@@ -114,10 +116,14 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
             child: ClipRRect(
               borderRadius: const BorderRadius.all(Radius.circular(8)),
               child: InteractiveParticipantWidget(
-                color: Theme.of(context).colorScheme.surfaceContainerHigh.withOpacity(0.75),
+                color: Theme.of(context)
+                    .colorScheme
+                    .surfaceContainerHigh
+                    .withOpacity(0.75),
                 participant: track,
                 onTap: () {
-                  if (track.participant.sid != call.focusTrack?.participant.sid) {
+                  if (track.participant.sid !=
+                      call.focusTrack?.participant.sid) {
                     call.setFocusTrack(track);
                   }
                 },
@@ -149,6 +155,7 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
         listenable: call,
         builder: (context, _) {
           return AppScaffold(
+            noBackground: true,
             appBar: AppBar(
               title: RichText(
                 textAlign: TextAlign.center,
@@ -183,7 +190,8 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
                         Builder(builder: (context) {
                           final call = context.read<ChatCallProvider>();
                           final connectionQuality =
-                              call.room.localParticipant?.connectionQuality ?? livekit.ConnectionQuality.unknown;
+                              call.room.localParticipant?.connectionQuality ??
+                                  livekit.ConnectionQuality.unknown;
                           return Expanded(
                             child: Column(
                               mainAxisSize: MainAxisSize.min,
@@ -205,24 +213,35 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
                                   children: [
                                     Text(
                                       {
-                                        livekit.ConnectionState.disconnected: 'callStatusDisconnected'.tr(),
-                                        livekit.ConnectionState.connected: 'callStatusConnected'.tr(),
-                                        livekit.ConnectionState.connecting: 'callStatusConnecting'.tr(),
-                                        livekit.ConnectionState.reconnecting: 'callStatusReconnecting'.tr(),
+                                        livekit.ConnectionState.disconnected:
+                                            'callStatusDisconnected'.tr(),
+                                        livekit.ConnectionState.connected:
+                                            'callStatusConnected'.tr(),
+                                        livekit.ConnectionState.connecting:
+                                            'callStatusConnecting'.tr(),
+                                        livekit.ConnectionState.reconnecting:
+                                            'callStatusReconnecting'.tr(),
                                       }[call.room.connectionState]!,
                                     ),
                                     const Gap(6),
-                                    if (connectionQuality != livekit.ConnectionQuality.unknown)
+                                    if (connectionQuality !=
+                                        livekit.ConnectionQuality.unknown)
                                       Icon(
                                         {
-                                          livekit.ConnectionQuality.excellent: Icons.signal_cellular_alt,
-                                          livekit.ConnectionQuality.good: Icons.signal_cellular_alt_2_bar,
-                                          livekit.ConnectionQuality.poor: Icons.signal_cellular_alt_1_bar,
+                                          livekit.ConnectionQuality.excellent:
+                                              Icons.signal_cellular_alt,
+                                          livekit.ConnectionQuality.good:
+                                              Icons.signal_cellular_alt_2_bar,
+                                          livekit.ConnectionQuality.poor:
+                                              Icons.signal_cellular_alt_1_bar,
                                         }[connectionQuality],
                                         color: {
-                                          livekit.ConnectionQuality.excellent: Colors.green,
-                                          livekit.ConnectionQuality.good: Colors.orange,
-                                          livekit.ConnectionQuality.poor: Colors.red,
+                                          livekit.ConnectionQuality.excellent:
+                                              Colors.green,
+                                          livekit.ConnectionQuality.good:
+                                              Colors.orange,
+                                          livekit.ConnectionQuality.poor:
+                                              Colors.red,
                                         }[connectionQuality],
                                         size: 16,
                                       )
@@ -244,7 +263,9 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
                         Row(
                           children: [
                             IconButton(
-                              icon: _layoutMode == 0 ? const Icon(Icons.view_list) : const Icon(Icons.grid_view),
+                              icon: _layoutMode == 0
+                                  ? const Icon(Icons.view_list)
+                                  : const Icon(Icons.grid_view),
                               onPressed: () {
                                 _switchLayout();
                               },
diff --git a/lib/screens/chat/channel_detail.dart b/lib/screens/chat/channel_detail.dart
index 1d86144..f1154c3 100644
--- a/lib/screens/chat/channel_detail.dart
+++ b/lib/screens/chat/channel_detail.dart
@@ -220,6 +220,7 @@ class _ChannelDetailScreenState extends State<ChannelDetailScreen> {
     final isOwned = ua.isAuthorized && _channel?.accountId == ua.user?.id;
 
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         title: _channel != null ? Text(_channel!.name) : Text('loading').tr(),
       ),
diff --git a/lib/screens/chat/manage.dart b/lib/screens/chat/manage.dart
index 2eceac2..67007d2 100644
--- a/lib/screens/chat/manage.dart
+++ b/lib/screens/chat/manage.dart
@@ -49,7 +49,8 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
         resp.data?.map((e) => SnRealm.fromJson(e)) ?? [],
       );
       if (_editingChannel != null) {
-        _belongToRealm = _realms?.firstWhereOrNull((e) => e.id == _editingChannel!.realmId);
+        _belongToRealm =
+            _realms?.firstWhereOrNull((e) => e.id == _editingChannel!.realmId);
       }
     } catch (err) {
       if (mounted) context.showErrorDialog(err);
@@ -97,7 +98,8 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
       'is_community': _isCommunity,
       if (_editingChannel != null && _belongToRealm == null)
         'new_belongs_realm': 'global'
-      else if (_editingChannel != null && _belongToRealm?.id != _editingChannel?.realm?.id)
+      else if (_editingChannel != null &&
+          _belongToRealm?.id != _editingChannel?.realm?.id)
         'new_belongs_realm': _belongToRealm!.alias,
     };
 
@@ -139,8 +141,11 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
-        title: widget.editingChannelAlias != null ? Text('screenChatManage').tr() : Text('screenChatNew').tr(),
+        title: widget.editingChannelAlias != null
+            ? Text('screenChatManage').tr()
+            : Text('screenChatNew').tr(),
       ),
       body: SingleChildScrollView(
         child: Column(
@@ -152,7 +157,8 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
                 leadingPadding: const EdgeInsets.only(left: 10, right: 20),
                 dividerColor: Colors.transparent,
                 content: Text(
-                  'channelEditingNotice'.tr(args: ['#${_editingChannel!.alias}']),
+                  'channelEditingNotice'
+                      .tr(args: ['#${_editingChannel!.alias}']),
                 ),
                 actions: [
                   TextButton(
@@ -192,12 +198,15 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
                                   mainAxisSize: MainAxisSize.min,
                                   crossAxisAlignment: CrossAxisAlignment.start,
                                   children: [
-                                    Text(item.name).textStyle(Theme.of(context).textTheme.bodyMedium!),
+                                    Text(item.name).textStyle(Theme.of(context)
+                                        .textTheme
+                                        .bodyMedium!),
                                     Text(
                                       item.description,
                                       maxLines: 1,
                                       overflow: TextOverflow.ellipsis,
-                                    ).textStyle(Theme.of(context).textTheme.bodySmall!),
+                                    ).textStyle(
+                                        Theme.of(context).textTheme.bodySmall!),
                                   ],
                                 ),
                               ),
@@ -213,7 +222,8 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
                         CircleAvatar(
                           radius: 16,
                           backgroundColor: Colors.transparent,
-                          foregroundColor: Theme.of(context).colorScheme.onSurface,
+                          foregroundColor:
+                              Theme.of(context).colorScheme.onSurface,
                           child: const Icon(Symbols.clear),
                         ),
                         const Gap(12),
@@ -222,7 +232,9 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
                             mainAxisSize: MainAxisSize.min,
                             crossAxisAlignment: CrossAxisAlignment.start,
                             children: [
-                              Text('fieldChatBelongToRealmUnset').tr().textStyle(
+                              Text('fieldChatBelongToRealmUnset')
+                                  .tr()
+                                  .textStyle(
                                     Theme.of(context).textTheme.bodyMedium!,
                                   ),
                             ],
@@ -257,7 +269,8 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
                     helperText: 'fieldChatAliasHint'.tr(),
                     helperMaxLines: 2,
                   ),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ),
                 const Gap(4),
                 TextField(
@@ -266,7 +279,8 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
                     border: const UnderlineInputBorder(),
                     labelText: 'fieldChatName'.tr(),
                   ),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ),
                 const Gap(4),
                 TextField(
@@ -277,7 +291,8 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
                     border: const UnderlineInputBorder(),
                     labelText: 'fieldChatDescription'.tr(),
                   ),
-                  onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
+                  onTapOutside: (_) =>
+                      FocusManager.instance.primaryFocus?.unfocus(),
                 ),
                 const Gap(12),
                 CheckboxListTile(
diff --git a/lib/screens/chat/room.dart b/lib/screens/chat/room.dart
index 22950cb..efd3dab 100644
--- a/lib/screens/chat/room.dart
+++ b/lib/screens/chat/room.dart
@@ -304,6 +304,7 @@ class _ChatRoomScreenState extends State<ChatRoomScreen> {
     final ud = context.read<UserDirectoryProvider>();
 
     return AppScaffold(
+      noBackground: true,
       appBar: AppBar(
         title: Text(
           _channel?.type == 1
diff --git a/lib/screens/explore.dart b/lib/screens/explore.dart
index f08119e..6b7f086 100644
--- a/lib/screens/explore.dart
+++ b/lib/screens/explore.dart
@@ -157,6 +157,7 @@ class _ExploreScreenState extends State<ExploreScreen>
   Widget build(BuildContext context) {
     final cfg = context.watch<ConfigProvider>();
     return AppScaffold(
+      noBackground: true,
       floatingActionButtonLocation: ExpandableFab.location,
       floatingActionButton: ExpandableFab(
         key: _fabKey,
@@ -243,6 +244,8 @@ class _ExploreScreenState extends State<ExploreScreen>
                         GoRouter.of(context).pushNamed('postShuffle');
                       },
                     ),
+                    if (ResponsiveBreakpoints.of(context).largerThan(MOBILE))
+                      const Gap(48),
                     Expanded(
                       child: Center(
                         child: IconButton(
@@ -534,6 +537,7 @@ class _PostListWidgetState extends State<_PostListWidget> {
             switch (ele.type) {
               case 'interactive.post':
                 return OpenablePostItem(
+                  useReplace: true,
                   data: SnPost.fromJson(ele.data),
                   maxWidth: 640,
                   onChanged: (data) {
diff --git a/lib/screens/post/post_detail.dart b/lib/screens/post/post_detail.dart
index fa2d49f..2514058 100644
--- a/lib/screens/post/post_detail.dart
+++ b/lib/screens/post/post_detail.dart
@@ -12,7 +12,6 @@ import 'package:surface/providers/userinfo.dart';
 import 'package:surface/types/post.dart';
 import 'package:surface/widgets/dialog.dart';
 import 'package:surface/widgets/loading_indicator.dart';
-import 'package:surface/widgets/navigation/app_background.dart';
 import 'package:surface/widgets/navigation/app_scaffold.dart';
 import 'package:surface/widgets/post/post_comment_list.dart';
 import 'package:surface/widgets/post/post_item.dart';
@@ -66,115 +65,111 @@ class _PostDetailScreenState extends State<PostDetailScreen> {
 
     final double maxWidth = _data?.type == 'video' ? double.infinity : 640;
 
-    return AppBackground(
-      isRoot: widget.onBack != null,
-      child: AppScaffold(
-        appBar: AppBar(
-          leading: BackButton(
-            onPressed: () {
-              if (widget.onBack != null) {
-                widget.onBack!.call();
-              }
-              if (GoRouter.of(context).canPop()) {
-                GoRouter.of(context).pop(context);
-                return;
-              }
-              GoRouter.of(context).replaceNamed('explore');
-            },
-          ),
-          title: _data?.body['title'] != null
-              ? RichText(
-                  textAlign: TextAlign.center,
-                  text: TextSpan(children: [
-                    TextSpan(
-                      text: _data?.body['title'] ?? 'postNoun'.tr(),
-                      style: Theme.of(context).textTheme.titleLarge!.copyWith(
-                            color:
-                                Theme.of(context).appBarTheme.foregroundColor!,
-                          ),
-                    ),
-                    const TextSpan(text: '\n'),
-                    TextSpan(
-                      text: 'postDetail'.tr(),
-                      style: Theme.of(context).textTheme.bodySmall!.copyWith(
-                            color:
-                                Theme.of(context).appBarTheme.foregroundColor!,
-                          ),
-                    ),
-                  ]),
-                  maxLines: 2,
-                  overflow: TextOverflow.ellipsis,
-                )
-              : Text('postDetail').tr(),
+    return AppScaffold(
+      noBackground: true,
+      appBar: AppBar(
+        leading: BackButton(
+          onPressed: () {
+            if (widget.onBack != null) {
+              widget.onBack!.call();
+            }
+            if (GoRouter.of(context).canPop()) {
+              GoRouter.of(context).pop(context);
+              return;
+            }
+            GoRouter.of(context).replaceNamed('explore');
+          },
         ),
-        body: CustomScrollView(
-          slivers: [
-            SliverToBoxAdapter(
-              child: LoadingIndicator(isActive: _isBusy),
-            ),
-            if (_data != null)
-              SliverToBoxAdapter(
-                child: PostItem(
-                  data: _data!,
-                  maxWidth: maxWidth,
-                  showComments: false,
-                  showFullPost: true,
-                  onChanged: (data) {
-                    setState(() => _data = data);
-                  },
-                  onDeleted: () {
-                    Navigator.pop(context);
-                  },
-                ),
-              ),
-            if (_data != null)
-              SliverToBoxAdapter(
-                child: Divider(height: 1).padding(top: 8),
-              ),
-            if (_data != null)
-              SliverToBoxAdapter(
-                child: Container(
-                  constraints: BoxConstraints(maxWidth: maxWidth),
-                  child: Row(
-                    crossAxisAlignment: CrossAxisAlignment.center,
-                    children: [
-                      const Icon(Symbols.comment, size: 24),
-                      const Gap(16),
-                      Text('postCommentsDetailed')
-                          .plural(_data!.metric.replyCount)
-                          .textStyle(Theme.of(context).textTheme.titleLarge!),
-                    ],
-                  ).padding(horizontal: 20, vertical: 12).center(),
-                ),
-              ),
-            if (_data != null && ua.isAuthorized)
-              SliverToBoxAdapter(
-                child: PostCommentQuickAction(
-                  parentPost: _data!,
-                  maxWidth: maxWidth,
-                  onPosted: () {
-                    setState(() {
-                      _data = _data!.copyWith(
-                        metric: _data!.metric.copyWith(
-                          replyCount: _data!.metric.replyCount + 1,
+        title: _data?.body['title'] != null
+            ? RichText(
+                textAlign: TextAlign.center,
+                text: TextSpan(children: [
+                  TextSpan(
+                    text: _data?.body['title'] ?? 'postNoun'.tr(),
+                    style: Theme.of(context).textTheme.titleLarge!.copyWith(
+                          color: Theme.of(context).appBarTheme.foregroundColor!,
                         ),
-                      );
-                    });
-                    _childListKey.currentState!.refresh();
-                  },
-                ),
+                  ),
+                  const TextSpan(text: '\n'),
+                  TextSpan(
+                    text: 'postDetail'.tr(),
+                    style: Theme.of(context).textTheme.bodySmall!.copyWith(
+                          color: Theme.of(context).appBarTheme.foregroundColor!,
+                        ),
+                  ),
+                ]),
+                maxLines: 2,
+                overflow: TextOverflow.ellipsis,
+              )
+            : Text('postDetail').tr(),
+      ),
+      body: CustomScrollView(
+        slivers: [
+          SliverToBoxAdapter(
+            child: LoadingIndicator(isActive: _isBusy),
+          ),
+          if (_data != null)
+            SliverToBoxAdapter(
+              child: PostItem(
+                data: _data!,
+                maxWidth: maxWidth,
+                showComments: false,
+                showFullPost: true,
+                onChanged: (data) {
+                  setState(() => _data = data);
+                },
+                onDeleted: () {
+                  Navigator.pop(context);
+                },
               ),
-            if (_data != null) SliverGap(8),
-            if (_data != null)
-              PostCommentSliverList(
-                key: _childListKey,
+            ),
+          if (_data != null)
+            SliverToBoxAdapter(
+              child: Divider(height: 1).padding(top: 8),
+            ),
+          if (_data != null)
+            SliverToBoxAdapter(
+              child: Container(
+                constraints: BoxConstraints(maxWidth: maxWidth),
+                child: Row(
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    const Icon(Symbols.comment, size: 24),
+                    const Gap(16),
+                    Text('postCommentsDetailed')
+                        .plural(_data!.metric.replyCount)
+                        .textStyle(Theme.of(context).textTheme.titleLarge!),
+                  ],
+                ).padding(horizontal: 20, vertical: 12).center(),
+              ),
+            ),
+          if (_data != null && ua.isAuthorized)
+            SliverToBoxAdapter(
+              child: PostCommentQuickAction(
                 parentPost: _data!,
                 maxWidth: maxWidth,
+                onPosted: () {
+                  setState(() {
+                    _data = _data!.copyWith(
+                      metric: _data!.metric.copyWith(
+                        replyCount: _data!.metric.replyCount + 1,
+                      ),
+                    );
+                  });
+                  _childListKey.currentState!.refresh();
+                },
               ),
-            if (_data != null)
-              SliverGap(math.max(MediaQuery.of(context).padding.bottom, 16)),
-          ],
-        ),
+            ),
+          if (_data != null) SliverGap(8),
+          if (_data != null)
+            PostCommentSliverList(
+              key: _childListKey,
+              parentPost: _data!,
+              maxWidth: maxWidth,
+            ),
+          if (_data != null)
+            SliverGap(math.max(MediaQuery.of(context).padding.bottom, 16)),
+        ],
       ),
     );
   }
diff --git a/lib/screens/post/publisher_page.dart b/lib/screens/post/publisher_page.dart
index fdea667..0b8cb06 100644
--- a/lib/screens/post/publisher_page.dart
+++ b/lib/screens/post/publisher_page.dart
@@ -286,6 +286,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen>
     final sn = context.read<SnNetworkProvider>();
 
     return AppScaffold(
+      noBackground: true,
       body: NestedScrollView(
         controller: _scrollController,
         headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart
index 0610eb9..5e379a0 100644
--- a/lib/screens/settings.dart
+++ b/lib/screens/settings.dart
@@ -325,20 +325,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
                     setState(() {});
                   },
                 ),
-                CheckboxListTile(
-                  secondary: const Icon(Symbols.left_panel_close),
-                  title: Text('settingsDrawerPreferCollapse').tr(),
-                  subtitle:
-                      Text('settingsDrawerPreferCollapseDescription').tr(),
-                  contentPadding: const EdgeInsets.only(left: 24, right: 17),
-                  value: _prefs.getBool(kAppDrawerPreferCollapse) ?? false,
-                  onChanged: (value) {
-                    _prefs.setBool(kAppDrawerPreferCollapse, value ?? false);
-                    final cfg = context.read<ConfigProvider>();
-                    cfg.calcDrawerSize(context);
-                    setState(() {});
-                  },
-                ),
                 CheckboxListTile(
                   secondary: const Icon(Symbols.hide),
                   title: Text('settingsHideBottomNav').tr(),
diff --git a/lib/screens/wallet.dart b/lib/screens/wallet.dart
index 799d8ee..dd49a3a 100644
--- a/lib/screens/wallet.dart
+++ b/lib/screens/wallet.dart
@@ -45,7 +45,9 @@ class _WalletScreenState extends State<WalletScreen> {
   @override
   Widget build(BuildContext context) {
     return AppScaffold(
-      appBar: AppBar(leading: PageBackButton(), title: Text('screenAccountWallet').tr()),
+      noBackground: true,
+      appBar: AppBar(
+          leading: PageBackButton(), title: Text('screenAccountWallet').tr()),
       body: Column(
         children: [
           LoadingIndicator(isActive: _isBusy),
@@ -66,7 +68,9 @@ class _WalletScreenState extends State<WalletScreen> {
                   SizedBox(width: double.infinity),
                   Text(
                     NumberFormat.compactCurrency(
-                      locale: EasyLocalization.of(context)!.currentLocale.toString(),
+                      locale: EasyLocalization.of(context)!
+                          .currentLocale
+                          .toString(),
                       symbol: '${'walletCurrencyShort'.tr()} ',
                       decimalDigits: 2,
                     ).format(double.parse(_wallet!.balance)),
@@ -76,17 +80,21 @@ class _WalletScreenState extends State<WalletScreen> {
                   const Gap(16),
                   Text(
                     NumberFormat.compactCurrency(
-                      locale: EasyLocalization.of(context)!.currentLocale.toString(),
+                      locale: EasyLocalization.of(context)!
+                          .currentLocale
+                          .toString(),
                       symbol: '${'walletCurrencyGoldenShort'.tr()} ',
                       decimalDigits: 2,
                     ).format(double.parse(_wallet!.goldenBalance)),
                     style: Theme.of(context).textTheme.titleLarge,
                   ),
-                  Text('walletCurrencyGolden'.plural(double.parse(_wallet!.goldenBalance))),
+                  Text('walletCurrencyGolden'
+                      .plural(double.parse(_wallet!.goldenBalance))),
                 ],
               ).padding(horizontal: 20, vertical: 24),
             ).padding(horizontal: 8, top: 16, bottom: 4),
-          if (_wallet != null) Expanded(child: _WalletTransactionList(myself: _wallet!)),
+          if (_wallet != null)
+            Expanded(child: _WalletTransactionList(myself: _wallet!)),
         ],
       ),
     );
@@ -116,7 +124,10 @@ class _WalletTransactionListState extends State<_WalletTransactionList> {
         queryParameters: {'take': 10, 'offset': _transactions.length},
       );
       _totalCount = resp.data['count'];
-      _transactions.addAll(resp.data['data']?.map((e) => SnTransaction.fromJson(e)).cast<SnTransaction>() ?? []);
+      _transactions.addAll(resp.data['data']
+              ?.map((e) => SnTransaction.fromJson(e))
+              .cast<SnTransaction>() ??
+          []);
     } catch (err) {
       if (!mounted) return;
       context.showErrorDialog(err);
@@ -141,7 +152,8 @@ class _WalletTransactionListState extends State<_WalletTransactionList> {
         child: InfiniteList(
           itemCount: _transactions.length,
           isLoading: _isBusy,
-          hasReachedMax: _totalCount != null && _transactions.length >= _totalCount!,
+          hasReachedMax:
+              _totalCount != null && _transactions.length >= _totalCount!,
           onFetchData: () {
             _fetchTransactions();
           },
@@ -149,7 +161,9 @@ class _WalletTransactionListState extends State<_WalletTransactionList> {
             final ele = _transactions[idx];
             final isIncoming = ele.payeeId == widget.myself.id;
             return ListTile(
-              leading: isIncoming ? const Icon(Symbols.call_received) : const Icon(Symbols.call_made),
+              leading: isIncoming
+                  ? const Icon(Symbols.call_received)
+                  : const Icon(Symbols.call_made),
               title: Text(
                 '${isIncoming ? '+' : '-'}${ele.amount} ${'walletCurrencyShort'.tr()}',
                 style: TextStyle(color: isIncoming ? Colors.green : Colors.red),
@@ -162,12 +176,20 @@ class _WalletTransactionListState extends State<_WalletTransactionList> {
                   Row(
                     children: [
                       Text(
-                        'walletTransactionType${ele.currency.capitalize()}'.tr(),
+                        'walletTransactionType${ele.currency.capitalize()}'
+                            .tr(),
                         style: Theme.of(context).textTheme.labelSmall,
                       ),
-                      Text(' · ').textStyle(Theme.of(context).textTheme.labelSmall!).padding(right: 4),
+                      Text(' · ')
+                          .textStyle(Theme.of(context).textTheme.labelSmall!)
+                          .padding(right: 4),
                       Text(
-                        DateFormat(null, EasyLocalization.of(context)!.currentLocale.toString()).format(ele.createdAt),
+                        DateFormat(
+                                null,
+                                EasyLocalization.of(context)!
+                                    .currentLocale
+                                    .toString())
+                            .format(ele.createdAt),
                         style: Theme.of(context).textTheme.labelSmall,
                       ),
                     ],
@@ -199,33 +221,34 @@ class _CreateWalletWidgetState extends State<_CreateWalletWidget> {
     final TextEditingController passwordController = TextEditingController();
     final password = await showDialog<String?>(
       context: context,
-      builder:
-          (ctx) => AlertDialog(
-            title: Text('walletCreate').tr(),
-            content: Column(
-              crossAxisAlignment: CrossAxisAlignment.start,
-              mainAxisSize: MainAxisSize.min,
-              children: [
-                Text('walletCreatePassword').tr(),
-                const Gap(8),
-                TextField(
-                  autofocus: true,
-                  obscureText: true,
-                  controller: passwordController,
-                  decoration: InputDecoration(labelText: 'fieldPassword'.tr()),
-                ),
-              ],
+      builder: (ctx) => AlertDialog(
+        title: Text('walletCreate').tr(),
+        content: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            Text('walletCreatePassword').tr(),
+            const Gap(8),
+            TextField(
+              autofocus: true,
+              obscureText: true,
+              controller: passwordController,
+              decoration: InputDecoration(labelText: 'fieldPassword'.tr()),
             ),
-            actions: [
-              TextButton(onPressed: () => Navigator.of(ctx).pop(), child: Text('cancel').tr()),
-              TextButton(
-                onPressed: () {
-                  Navigator.of(ctx).pop(passwordController.text);
-                },
-                child: Text('next').tr(),
-              ),
-            ],
+          ],
+        ),
+        actions: [
+          TextButton(
+              onPressed: () => Navigator.of(ctx).pop(),
+              child: Text('cancel').tr()),
+          TextButton(
+            onPressed: () {
+              Navigator.of(ctx).pop(passwordController.text);
+            },
+            child: Text('next').tr(),
           ),
+        ],
+      ),
     );
     WidgetsBinding.instance.addPostFrameCallback((_) {
       passwordController.dispose();
@@ -257,12 +280,18 @@ class _CreateWalletWidgetState extends State<_CreateWalletWidget> {
             children: [
               CircleAvatar(radius: 28, child: Icon(Symbols.add, size: 28)),
               const Gap(12),
-              Text('walletCreate', style: Theme.of(context).textTheme.titleLarge).tr(),
-              Text('walletCreateSubtitle', style: Theme.of(context).textTheme.bodyMedium).tr(),
+              Text('walletCreate',
+                      style: Theme.of(context).textTheme.titleLarge)
+                  .tr(),
+              Text('walletCreateSubtitle',
+                      style: Theme.of(context).textTheme.bodyMedium)
+                  .tr(),
               const Gap(8),
               Align(
                 alignment: Alignment.centerRight,
-                child: TextButton(onPressed: _isBusy ? null : () => _createWallet(), child: Text('next').tr()),
+                child: TextButton(
+                    onPressed: _isBusy ? null : () => _createWallet(),
+                    child: Text('next').tr()),
               ),
             ],
           ).padding(horizontal: 20, vertical: 24),
diff --git a/lib/widgets/connection_indicator.dart b/lib/widgets/connection_indicator.dart
index d411636..4f56b4e 100644
--- a/lib/widgets/connection_indicator.dart
+++ b/lib/widgets/connection_indicator.dart
@@ -16,12 +16,7 @@ class ConnectionIndicator extends StatelessWidget {
     final ws = context.watch<WebSocketProvider>();
     final cfg = context.watch<ConfigProvider>();
 
-    final marginLeft =
-        cfg.drawerIsCollapsed
-            ? 0.0
-            : cfg.drawerIsExpanded
-            ? 304.0
-            : 80.0;
+    final marginLeft = cfg.drawerIsCollapsed ? 0.0 : 80.0;
 
     return ListenableBuilder(
       listenable: ws,
@@ -35,41 +30,52 @@ class ConnectionIndicator extends StatelessWidget {
             child: GestureDetector(
               child: Material(
                 elevation: 2,
-                shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))),
+                shape: const RoundedRectangleBorder(
+                    borderRadius: BorderRadius.all(Radius.circular(16))),
                 color: Theme.of(context).colorScheme.secondaryContainer,
-                child:
-                    ua.isAuthorized
-                        ? Row(
-                          mainAxisSize: MainAxisSize.min,
-                          mainAxisAlignment: MainAxisAlignment.center,
-                          crossAxisAlignment: CrossAxisAlignment.center,
-                          children: [
-                            if (ws.isBusy)
-                              Text(
-                                'serverConnecting',
-                              ).tr().textColor(Theme.of(context).colorScheme.onSecondaryContainer)
-                            else if (!ws.isConnected)
-                              Text(
-                                'serverDisconnected',
-                              ).tr().textColor(Theme.of(context).colorScheme.onSecondaryContainer)
-                            else
-                              Text(
-                                'serverConnected',
-                              ).tr().textColor(Theme.of(context).colorScheme.onSecondaryContainer),
-                            const Gap(8),
-                            if (ws.isBusy)
-                              const CircularProgressIndicator(
-                                strokeWidth: 2.5,
-                                padding: EdgeInsets.zero,
-                              ).width(12).height(12).padding(horizontal: 4, right: 4)
-                            else if (!ws.isConnected)
-                              const Icon(Symbols.power_off, size: 18)
-                            else
-                              const Icon(Symbols.power, size: 18),
-                          ],
-                        ).padding(horizontal: 8, vertical: 4)
-                        : const SizedBox.shrink(),
-              ).opacity(show ? 1 : 0, animate: true).animate(const Duration(milliseconds: 300), Curves.easeInOut),
+                child: ua.isAuthorized
+                    ? Row(
+                        mainAxisSize: MainAxisSize.min,
+                        mainAxisAlignment: MainAxisAlignment.center,
+                        crossAxisAlignment: CrossAxisAlignment.center,
+                        children: [
+                          if (ws.isBusy)
+                            Text(
+                              'serverConnecting',
+                            ).tr().textColor(Theme.of(context)
+                                .colorScheme
+                                .onSecondaryContainer)
+                          else if (!ws.isConnected)
+                            Text(
+                              'serverDisconnected',
+                            ).tr().textColor(Theme.of(context)
+                                .colorScheme
+                                .onSecondaryContainer)
+                          else
+                            Text(
+                              'serverConnected',
+                            ).tr().textColor(Theme.of(context)
+                                .colorScheme
+                                .onSecondaryContainer),
+                          const Gap(8),
+                          if (ws.isBusy)
+                            const CircularProgressIndicator(
+                              strokeWidth: 2.5,
+                              padding: EdgeInsets.zero,
+                            )
+                                .width(12)
+                                .height(12)
+                                .padding(horizontal: 4, right: 4)
+                          else if (!ws.isConnected)
+                            const Icon(Symbols.power_off, size: 18)
+                          else
+                            const Icon(Symbols.power, size: 18),
+                        ],
+                      ).padding(horizontal: 8, vertical: 4)
+                    : const SizedBox.shrink(),
+              )
+                  .opacity(show ? 1 : 0, animate: true)
+                  .animate(const Duration(milliseconds: 300), Curves.easeInOut),
               onTap: () {
                 if (!ws.isConnected && !ws.isBusy) {
                   ws.connect();
diff --git a/lib/widgets/context_menu.dart b/lib/widgets/context_menu.dart
index 940f6da..ce77857 100644
--- a/lib/widgets/context_menu.dart
+++ b/lib/widgets/context_menu.dart
@@ -26,9 +26,7 @@ class ContextMenuArea extends StatelessWidget {
         final cfg = context.read<ConfigProvider>();
         if (!cfg.drawerIsCollapsed) {
           // Leave padding for side navigation
-          mousePosition = cfg.drawerIsExpanded
-              ? mousePosition.copyWith(dx: mousePosition.dx - 304 * 2)
-              : mousePosition.copyWith(dx: mousePosition.dx - 80 * 2);
+          mousePosition = mousePosition.copyWith(dx: mousePosition.dx - 80 * 2);
         }
       },
       child: GestureDetector(
@@ -40,7 +38,8 @@ class ContextMenuArea extends StatelessWidget {
   }
 
   void _showMenu(BuildContext context, Offset mousePosition) async {
-    final menu = contextMenu.copyWith(position: contextMenu.position ?? mousePosition);
+    final menu =
+        contextMenu.copyWith(position: contextMenu.position ?? mousePosition);
     final value = await showContextMenu(context, contextMenu: menu);
     onItemSelected?.call(value);
   }
diff --git a/lib/widgets/navigation/app_drawer_navigation.dart b/lib/widgets/navigation/app_drawer_navigation.dart
index a008852..679ca37 100644
--- a/lib/widgets/navigation/app_drawer_navigation.dart
+++ b/lib/widgets/navigation/app_drawer_navigation.dart
@@ -1,6 +1,5 @@
 import 'dart:io';
 
-import 'package:animations/animations.dart';
 import 'package:bitsdojo_window/bitsdojo_window.dart';
 import 'package:collection/collection.dart';
 import 'package:easy_localization/easy_localization.dart';
@@ -11,14 +10,9 @@ import 'package:go_router/go_router.dart';
 import 'package:material_symbols_icons/symbols.dart';
 import 'package:provider/provider.dart';
 import 'package:styled_widget/styled_widget.dart';
-import 'package:surface/providers/channel.dart';
-import 'package:surface/providers/config.dart';
 import 'package:surface/providers/navigation.dart';
-import 'package:surface/providers/sn_network.dart';
-import 'package:surface/providers/sn_realm.dart';
 import 'package:surface/providers/userinfo.dart';
 import 'package:surface/widgets/account/account_image.dart';
-import 'package:surface/widgets/universal_image.dart';
 import 'package:surface/widgets/version_label.dart';
 
 class AppNavigationDrawer extends StatefulWidget {
@@ -45,27 +39,18 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
   Widget build(BuildContext context) {
     final ua = context.read<UserProvider>();
     final nav = context.watch<NavigationProvider>();
-    final cfg = context.watch<ConfigProvider>();
-
-    final backgroundColor = cfg.drawerIsExpanded ? Colors.transparent : null;
 
     return ListenableBuilder(
       listenable: nav,
       builder: (context, _) {
         return Drawer(
           elevation: widget.elevation,
-          backgroundColor: backgroundColor,
-          shape: const RoundedRectangleBorder(
-              borderRadius: BorderRadius.all(Radius.circular(0))),
           child: Column(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.start,
             children: [
               if (!kIsWeb &&
-                  (Platform.isWindows ||
-                      Platform.isLinux ||
-                      Platform.isMacOS) &&
-                  !cfg.drawerIsExpanded)
+                  (Platform.isWindows || Platform.isLinux || Platform.isMacOS))
                 Container(
                   decoration: BoxDecoration(
                     border: Border(
@@ -78,42 +63,36 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
                   child: WindowTitleBarBox(),
                 ),
               Gap(MediaQuery.of(context).padding.top),
-              Expanded(
-                child: _DrawerContentList(),
+              Column(
+                mainAxisSize: MainAxisSize.min,
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Text('Solar Network').bold(),
+                  AppVersionLabel(),
+                ],
+              ).padding(
+                horizontal: 32,
+                vertical: 12,
+              ),
+              Expanded(
+                child: ListView(
+                  padding: EdgeInsets.zero,
+                  children: [
+                    ...nav.destinations.mapIndexed((idx, ele) {
+                      return ListTile(
+                        leading: ele.icon,
+                        title: Text(ele.label).tr(),
+                        contentPadding: EdgeInsets.symmetric(horizontal: 24),
+                        selected: nav.currentIndex == idx,
+                        onTap: () {
+                          GoRouter.of(context).pushNamed(ele.screen);
+                          nav.setIndex(idx);
+                        },
+                      );
+                    })
+                  ],
+                ),
               ),
-              Row(
-                spacing: 8,
-                children:
-                    nav.destinations.where((ele) => ele.isPinned).mapIndexed(
-                  (idx, ele) {
-                    return Expanded(
-                      child: Tooltip(
-                        message: ele.label.tr(),
-                        child: IconButton(
-                          icon: ele.icon,
-                          color: nav.currentIndex == idx
-                              ? Theme.of(context).colorScheme.onPrimaryContainer
-                              : Theme.of(context).colorScheme.onSurface,
-                          style: ButtonStyle(
-                            backgroundColor: WidgetStatePropertyAll(
-                              nav.currentIndex == idx
-                                  ? Theme.of(context)
-                                      .colorScheme
-                                      .primaryContainer
-                                  : Colors.transparent,
-                            ),
-                          ),
-                          onPressed: () {
-                            GoRouter.of(context).goNamed(ele.screen);
-                            Scaffold.of(context).closeDrawer();
-                            nav.setIndex(idx);
-                          },
-                        ),
-                      ),
-                    );
-                  },
-                ).toList(),
-              ).padding(horizontal: 16, bottom: 8),
               Align(
                 alignment: Alignment.bottomCenter,
                 child: ListTile(
@@ -167,163 +146,3 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
     );
   }
 }
-
-class _DrawerContentList extends StatelessWidget {
-  const _DrawerContentList();
-
-  @override
-  Widget build(BuildContext context) {
-    final ct = context.read<ChatChannelProvider>();
-    final sn = context.read<SnNetworkProvider>();
-    final nav = context.watch<NavigationProvider>();
-    final rel = context.watch<SnRealmProvider>();
-
-    return PageTransitionSwitcher(
-      duration: const Duration(milliseconds: 300),
-      transitionBuilder: (Widget child, Animation<double> primaryAnimation,
-          Animation<double> secondaryAnimation) {
-        return SharedAxisTransition(
-          animation: primaryAnimation,
-          secondaryAnimation: secondaryAnimation,
-          fillColor: Colors.transparent,
-          transitionType: SharedAxisTransitionType.horizontal,
-          child: child,
-        );
-      },
-      child: nav.focusedRealm == null
-          ? ListView(
-              key: const Key('realm-list-view'),
-              padding: EdgeInsets.zero,
-              children: [
-                Column(
-                  mainAxisSize: MainAxisSize.min,
-                  crossAxisAlignment: CrossAxisAlignment.start,
-                  children: [
-                    Text('Solar Network').bold(),
-                    AppVersionLabel(),
-                  ],
-                ).padding(
-                  horizontal: 32,
-                  vertical: 12,
-                ),
-                ...rel.availableRealms.map((ele) {
-                  return ListTile(
-                    minTileHeight: 48,
-                    contentPadding: EdgeInsets.symmetric(horizontal: 24),
-                    leading: AccountImage(
-                      content: ele.avatar,
-                      radius: 16,
-                    ),
-                    title: Text(ele.name),
-                    onTap: () {
-                      nav.setFocusedRealm(ele);
-                    },
-                  );
-                }),
-                ListTile(
-                  minTileHeight: 48,
-                  contentPadding: EdgeInsets.only(left: 28, right: 16),
-                  leading: const Icon(Symbols.globe).padding(right: 4),
-                  title: Text('screenRealmDiscovery').tr(),
-                  onTap: () {
-                    GoRouter.of(context).pushNamed('realmDiscovery');
-                    Scaffold.of(context).closeDrawer();
-                  },
-                ),
-              ],
-            )
-          : ListView(
-              key: ValueKey(nav.focusedRealm),
-              padding: EdgeInsets.zero,
-              children: [
-                if (nav.focusedRealm!.banner != null)
-                  AspectRatio(
-                    aspectRatio: 16 / 9,
-                    child: AutoResizeUniversalImage(
-                      sn.getAttachmentUrl(
-                        nav.focusedRealm!.banner!,
-                      ),
-                      fit: BoxFit.cover,
-                    ),
-                  ),
-                ListTile(
-                  minTileHeight: 48,
-                  tileColor: Theme.of(context).colorScheme.surfaceContainer,
-                  contentPadding: EdgeInsets.only(
-                    left: 24,
-                    right: 16,
-                  ),
-                  leading: AccountImage(
-                    content: nav.focusedRealm!.avatar,
-                    radius: 16,
-                  ),
-                  trailing: IconButton(
-                    icon: const Icon(Symbols.close),
-                    padding: EdgeInsets.zero,
-                    constraints: const BoxConstraints(),
-                    visualDensity: VisualDensity.compact,
-                    onPressed: () {
-                      nav.setFocusedRealm(null);
-                    },
-                  ),
-                  title: Text(nav.focusedRealm!.name),
-                  onTap: () {
-                    GoRouter.of(context).goNamed(
-                      'realmDetail',
-                      pathParameters: {
-                        'alias': nav.focusedRealm!.alias,
-                      },
-                    );
-                    Scaffold.of(context).closeDrawer();
-                  },
-                ),
-                ListTile(
-                  minTileHeight: 48,
-                  contentPadding: EdgeInsets.only(
-                    left: 28,
-                    right: 8,
-                  ),
-                  leading: const Icon(Symbols.globe),
-                  title: Text('community').tr(),
-                  onTap: () {
-                    GoRouter.of(context).goNamed(
-                      'realmCommunity',
-                      pathParameters: {
-                        'alias': nav.focusedRealm!.alias,
-                      },
-                    );
-                    Scaffold.of(context).closeDrawer();
-                  },
-                ),
-                if (ct.availableChannels
-                    .where((ele) => ele.realmId == nav.focusedRealm?.id)
-                    .isNotEmpty)
-                  const Divider(height: 1),
-                ...(ct.availableChannels
-                    .where((ele) => ele.realmId == nav.focusedRealm?.id)
-                    .map((ele) {
-                  return ListTile(
-                    minTileHeight: 48,
-                    contentPadding: EdgeInsets.only(
-                      left: 28,
-                      right: 8,
-                    ),
-                    leading: const Icon(Symbols.tag),
-                    title: Text(ele.name),
-                    onTap: () {
-                      GoRouter.of(context).goNamed(
-                        'chatRoom',
-                        pathParameters: {
-                          'scope': ele.realm?.alias ?? 'global',
-                          'alias': ele.alias,
-                        },
-                      );
-                      Scaffold.of(context).closeDrawer();
-                    },
-                  );
-                }))
-              ],
-            ),
-    );
-  }
-}
diff --git a/lib/widgets/navigation/app_rail_navigation.dart b/lib/widgets/navigation/app_rail_navigation.dart
index c3c7a55..e11cf51 100644
--- a/lib/widgets/navigation/app_rail_navigation.dart
+++ b/lib/widgets/navigation/app_rail_navigation.dart
@@ -1,10 +1,12 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:gap/gap.dart';
 import 'package:go_router/go_router.dart';
 import 'package:material_symbols_icons/symbols.dart';
 import 'package:provider/provider.dart';
-import 'package:styled_widget/styled_widget.dart';
 import 'package:surface/providers/navigation.dart';
+import 'package:surface/providers/userinfo.dart';
+import 'package:surface/widgets/account/account_image.dart';
 
 class AppRailNavigation extends StatefulWidget {
   const AppRailNavigation({super.key});
@@ -18,43 +20,59 @@ class _AppRailNavigationState extends State<AppRailNavigation> {
   void initState() {
     super.initState();
     WidgetsBinding.instance.addPostFrameCallback((_) {
-      context.read<NavigationProvider>().autoDetectIndex(GoRouter.maybeOf(context));
+      context
+          .read<NavigationProvider>()
+          .autoDetectIndex(GoRouter.maybeOf(context));
     });
   }
 
   @override
   Widget build(BuildContext context) {
+    final ua = context.watch<UserProvider>();
     final nav = context.watch<NavigationProvider>();
 
     return ListenableBuilder(
       listenable: nav,
       builder: (context, _) {
-        final destinations = nav.destinations.where((ele) => ele.isPinned).toList();
+        final destinations = nav.destinations.toList();
 
         return SizedBox(
           width: 80,
           child: NavigationRail(
-            selectedIndex:
-                nav.currentIndex != null && nav.currentIndex! < nav.pinnedDestinationCount ? nav.currentIndex : null,
+            labelType: NavigationRailLabelType.selected,
+            backgroundColor: Theme.of(context)
+                .colorScheme
+                .surfaceContainerLow
+                .withOpacity(0.5),
+            selectedIndex: nav.currentIndex != null &&
+                    nav.currentIndex! < nav.destinations.length
+                ? nav.currentIndex
+                : null,
             destinations: [
-              ...destinations.where((ele) => ele.isPinned).map((ele) {
+              ...destinations.map((ele) {
                 return NavigationRailDestination(
                   icon: ele.icon,
                   label: Text(ele.label).tr(),
                 );
               }),
             ],
+            leading: const Gap(4),
             trailing: Expanded(
               child: Align(
                 alignment: Alignment.bottomCenter,
-                child: StyledWidget(
-                  IconButton(
-                    icon: const Icon(Symbols.menu),
-                    onPressed: () {
-                      Scaffold.of(context).openDrawer();
+                child: Padding(
+                  padding: EdgeInsets.only(bottom: 24),
+                  child: GestureDetector(
+                    child: AccountImage(
+                      content: ua.user?.avatar,
+                      fallbackWidget:
+                          ua.isAuthorized ? null : const Icon(Symbols.login),
+                    ),
+                    onTap: () {
+                      GoRouter.of(context).goNamed('account');
                     },
                   ),
-                ).padding(bottom: 16),
+                ),
               ),
             ),
             onDestinationSelected: (idx) {
diff --git a/lib/widgets/navigation/app_scaffold.dart b/lib/widgets/navigation/app_scaffold.dart
index 7208f62..4e1a1d3 100644
--- a/lib/widgets/navigation/app_scaffold.dart
+++ b/lib/widgets/navigation/app_scaffold.dart
@@ -66,7 +66,9 @@ class AppScaffold extends StatelessWidget {
     return Scaffold(
       extendBody: true,
       extendBodyBehindAppBar: true,
-      backgroundColor: Theme.of(context).scaffoldBackgroundColor,
+      backgroundColor: noBackground
+          ? Colors.transparent
+          : Theme.of(context).scaffoldBackgroundColor,
       body: SizedBox.expand(
         child: noBackground
             ? content
@@ -111,7 +113,6 @@ class AppRootScaffold extends StatelessWidget {
     final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
 
     final isCollapseDrawer = cfg.drawerIsCollapsed;
-    final isExpandedDrawer = cfg.drawerIsExpanded;
 
     final routeName = GoRouter.of(context)
         .routerDelegate
@@ -132,19 +133,7 @@ class AppRootScaffold extends StatelessWidget {
         ? body
         : Row(
             children: [
-              Container(
-                decoration: BoxDecoration(
-                  border: Border(
-                    right: BorderSide(
-                      color: Theme.of(context).dividerColor,
-                      width: 1 / devicePixelRatio,
-                    ),
-                  ),
-                ),
-                child: isExpandedDrawer
-                    ? AppNavigationDrawer(elevation: 0)
-                    : AppRailNavigation(),
-              ),
+              AppRailNavigation(),
               Expanded(child: body),
             ],
           );
@@ -232,10 +221,72 @@ class AppRootScaffold extends StatelessWidget {
             ),
         ],
       ),
-      drawer: !isExpandedDrawer ? AppNavigationDrawer() : null,
       drawerEdgeDragWidth: isPopable ? 0 : null,
+      drawer: isCollapseDrawer ? const AppNavigationDrawer() : null,
       bottomNavigationBar:
           isShowBottomNavigation ? AppBottomNavigationBar() : null,
     );
   }
 }
+
+class ResponsiveScaffold extends StatelessWidget {
+  final Widget aside;
+  final Widget? child;
+  final int asideFlex;
+  final int contentFlex;
+  const ResponsiveScaffold({
+    super.key,
+    required this.aside,
+    required this.child,
+    this.asideFlex = 1,
+    this.contentFlex = 2,
+  });
+
+  static bool getIsExpand(BuildContext context) {
+    return ResponsiveBreakpoints.of(context).largerOrEqualTo(TABLET);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    if (getIsExpand(context)) {
+      return AppBackground(
+        isRoot: true,
+        child: Row(
+          children: [
+            Flexible(
+              flex: asideFlex,
+              child: aside,
+            ),
+            VerticalDivider(width: 1),
+            if (child != null && child != aside)
+              Flexible(flex: contentFlex, child: child!)
+            else
+              Flexible(
+                flex: contentFlex,
+                child: ResponsiveScaffoldLanding(child: null),
+              ),
+          ],
+        ),
+      );
+    }
+
+    return AppBackground(isRoot: true, child: child ?? aside);
+  }
+}
+
+class ResponsiveScaffoldLanding extends StatelessWidget {
+  final Widget? child;
+  const ResponsiveScaffoldLanding({super.key, required this.child});
+
+  @override
+  Widget build(BuildContext context) {
+    if (ResponsiveScaffold.getIsExpand(context) || child == null) {
+      return AppScaffold(
+        noBackground: true,
+        appBar: AppBar(),
+        body: const SizedBox.shrink(),
+      );
+    }
+    return child!;
+  }
+}
diff --git a/lib/widgets/post/post_comment_list.dart b/lib/widgets/post/post_comment_list.dart
index 4e7e23d..c7a981d 100644
--- a/lib/widgets/post/post_comment_list.dart
+++ b/lib/widgets/post/post_comment_list.dart
@@ -4,7 +4,6 @@ import 'package:gap/gap.dart';
 import 'package:go_router/go_router.dart';
 import 'package:material_symbols_icons/symbols.dart';
 import 'package:provider/provider.dart';
-import 'package:responsive_framework/responsive_framework.dart';
 import 'package:styled_widget/styled_widget.dart';
 import 'package:surface/providers/post.dart';
 import 'package:surface/providers/sn_network.dart';
@@ -30,24 +29,14 @@ class PostCommentQuickAction extends StatelessWidget {
     return Container(
       height: 240,
       constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
-      margin: ResponsiveBreakpoints.of(context).largerThan(MOBILE)
-          ? const EdgeInsets.symmetric(vertical: 8)
-          : EdgeInsets.zero,
       decoration: BoxDecoration(
-        borderRadius: ResponsiveBreakpoints.of(context).largerThan(MOBILE)
-            ? const BorderRadius.all(Radius.circular(8))
-            : BorderRadius.zero,
-        border: ResponsiveBreakpoints.of(context).largerThan(MOBILE)
-            ? Border.all(
-                color: Theme.of(context).dividerColor,
-                width: 1 / devicePixelRatio,
-              )
-            : Border.symmetric(
-                horizontal: BorderSide(
-                  color: Theme.of(context).dividerColor,
-                  width: 1 / devicePixelRatio,
-                ),
-              ),
+        borderRadius: BorderRadius.zero,
+        border: Border.symmetric(
+          horizontal: BorderSide(
+            color: Theme.of(context).dividerColor,
+            width: 1 / devicePixelRatio,
+          ),
+        ),
       ),
       child: PostMiniEditor(
         postReplyId: parentPost.id,
diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart
index 99a5785..cd08ccf 100644
--- a/lib/widgets/post/post_item.dart
+++ b/lib/widgets/post/post_item.dart
@@ -1,7 +1,6 @@
 import 'dart:io';
 import 'dart:math' as math;
 
-import 'package:animations/animations.dart';
 import 'package:dio/dio.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:file_saver/file_saver.dart';
@@ -26,7 +25,6 @@ import 'package:surface/providers/sn_network.dart';
 import 'package:surface/providers/translation.dart';
 import 'package:surface/providers/user_directory.dart';
 import 'package:surface/providers/userinfo.dart';
-import 'package:surface/screens/post/post_detail.dart';
 import 'package:surface/types/attachment.dart';
 import 'package:surface/types/post.dart';
 import 'package:surface/types/reaction.dart';
@@ -53,6 +51,7 @@ class OpenablePostItem extends StatelessWidget {
   final bool showMenu;
   final bool showFullPost;
   final bool showExpandableComments;
+  final bool useReplace;
   final double? maxWidth;
   final Function(SnPost data)? onChanged;
   final Function()? onDeleted;
@@ -66,6 +65,7 @@ class OpenablePostItem extends StatelessWidget {
     this.showMenu = true,
     this.showFullPost = false,
     this.showExpandableComments = false,
+    this.useReplace = false,
     this.maxWidth,
     this.onChanged,
     this.onDeleted,
@@ -74,40 +74,32 @@ class OpenablePostItem extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final cfg = context.read<ConfigProvider>();
-
     return Container(
       constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
       child: Center(
-        child: OpenContainer(
-          closedBuilder: (_, __) => Container(
-            constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
-            child: PostItem(
-              data: data,
-              maxWidth: maxWidth,
-              showComments: showComments,
-              showFullPost: showFullPost,
-              showExpandableComments: showExpandableComments,
-              onChanged: onChanged,
-              onDeleted: onDeleted,
-              onSelectAnswer: onSelectAnswer,
-            ),
-          ),
-          openBuilder: (_, close) => PostDetailScreen(
-            slug: data.id.toString(),
-            preload: data,
-            onBack: close,
-          ),
-          openColor: Colors.transparent,
-          openElevation: 0,
-          transitionType: ContainerTransitionType.fade,
-          closedElevation: 0,
-          closedColor: Theme.of(context).colorScheme.surface.withOpacity(
-                cfg.prefs.getBool(kAppBackgroundStoreKey) == true ? 0 : 1,
-              ),
-          closedShape: const RoundedRectangleBorder(
-            borderRadius: BorderRadius.all(Radius.circular(16)),
+        child: GestureDetector(
+          child: PostItem(
+            data: data,
+            maxWidth: maxWidth,
+            showComments: showComments,
+            showFullPost: showFullPost,
+            showExpandableComments: showExpandableComments,
+            onChanged: onChanged,
+            onDeleted: onDeleted,
+            onSelectAnswer: onSelectAnswer,
           ),
+          onTap: () {
+            if (useReplace) {
+              GoRouter.of(context)
+                  .pushReplacementNamed('postDetail', pathParameters: {
+                'slug': data.id.toString(),
+              });
+            } else {
+              GoRouter.of(context).pushNamed('postDetail', pathParameters: {
+                'slug': data.id.toString(),
+              });
+            }
+          },
         ),
       ),
     );
diff --git a/pubspec.yaml b/pubspec.yaml
index c01dd53..3112c12 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 # In Windows, build-name is used as the major, minor, and patch parts
 # of the product and file versions while build-number is used as the build suffix.
-version: 2.4.2+84
+version: 2.4.2+85
 
 environment:
   sdk: ^3.5.4