diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h
index 639ec4d910..e042e1e74c 100644
--- a/core/embed/rust/librust_qstr.h
+++ b/core/embed/rust/librust_qstr.h
@@ -19,7 +19,9 @@ static void _librust_qstrs(void) {
   MP_QSTR___dict__;
   MP_QSTR___name__;
   MP_QSTR_account;
+  MP_QSTR_account_items;
   MP_QSTR_account_label;
+  MP_QSTR_account_path;
   MP_QSTR_accounts;
   MP_QSTR_action;
   MP_QSTR_active;
@@ -175,6 +177,7 @@ static void _librust_qstrs(void) {
   MP_QSTR_confirm_reset_device;
   MP_QSTR_confirm_total;
   MP_QSTR_confirm_total__fee_rate;
+  MP_QSTR_confirm_total__fee_rate_colon;
   MP_QSTR_confirm_total__sending_from_account;
   MP_QSTR_confirm_total__title_fee;
   MP_QSTR_confirm_total__title_sending_from;
@@ -205,6 +208,7 @@ static void _librust_qstrs(void) {
   MP_QSTR_experimental_mode__title;
   MP_QSTR_extra;
   MP_QSTR_fee_amount;
+  MP_QSTR_fee_items;
   MP_QSTR_fee_label;
   MP_QSTR_fee_rate_amount;
   MP_QSTR_fee_title;
@@ -212,9 +216,11 @@ static void _librust_qstrs(void) {
   MP_QSTR_fingerprint;
   MP_QSTR_firmware_update__title;
   MP_QSTR_firmware_update__title_fingerprint;
+  MP_QSTR_flow_confirm_output;
   MP_QSTR_flow_confirm_reset_create;
   MP_QSTR_flow_confirm_reset_recover;
   MP_QSTR_flow_confirm_set_new_pin;
+  MP_QSTR_flow_confirm_summary;
   MP_QSTR_flow_get_address;
   MP_QSTR_flow_prompt_backup;
   MP_QSTR_flow_show_share_words;
@@ -248,6 +254,7 @@ static void _librust_qstrs(void) {
   MP_QSTR_inputs__space;
   MP_QSTR_instructions__continue_in_app;
   MP_QSTR_instructions__hold_to_confirm;
+  MP_QSTR_instructions__hold_to_sign;
   MP_QSTR_instructions__swipe_up;
   MP_QSTR_instructions__tap_to_confirm;
   MP_QSTR_is_type_of;
@@ -521,11 +528,15 @@ static void _librust_qstrs(void) {
   MP_QSTR_select_word;
   MP_QSTR_select_word_count;
   MP_QSTR_send__address_path;
+  MP_QSTR_send__cancel_sign;
   MP_QSTR_send__confirm_sending;
   MP_QSTR_send__from_multiple_accounts;
+  MP_QSTR_send__incl_transaction_fee;
   MP_QSTR_send__including_fee;
   MP_QSTR_send__maximum_fee;
   MP_QSTR_send__receiving_to_multisig;
+  MP_QSTR_send__send_from;
+  MP_QSTR_send__sign_transaction;
   MP_QSTR_send__title_confirm_sending;
   MP_QSTR_send__title_joint_transaction;
   MP_QSTR_send__title_receiving_to;
@@ -534,6 +545,7 @@ static void _librust_qstrs(void) {
   MP_QSTR_send__title_sending_to;
   MP_QSTR_send__to_the_total_amount;
   MP_QSTR_send__total_amount;
+  MP_QSTR_send__total_amount_colon;
   MP_QSTR_send__transaction_id;
   MP_QSTR_send__you_are_contributing;
   MP_QSTR_share_words;
@@ -833,7 +845,6 @@ static void _librust_qstrs(void) {
   MP_QSTR_eos__requirement;
   MP_QSTR_eos__sell_ram;
   MP_QSTR_eos__sender;
-  MP_QSTR_eos__sign_transaction;
   MP_QSTR_eos__threshold;
   MP_QSTR_eos__to;
   MP_QSTR_eos__transfer;
diff --git a/core/embed/rust/src/translations/generated/translated_string.rs b/core/embed/rust/src/translations/generated/translated_string.rs
index a79e554bda..537d2b976b 100644
--- a/core/embed/rust/src/translations/generated/translated_string.rs
+++ b/core/embed/rust/src/translations/generated/translated_string.rs
@@ -351,9 +351,9 @@ pub enum TranslatedString {
     coinjoin__title_do_not_disconnect = 217,  // "Do not disconnect your trezor!"
     coinjoin__title_progress = 218,  // "Coinjoin in progress"
     coinjoin__waiting_for_others = 219,  // "Waiting for others"
-    confirm_total__fee_rate = 220,  // "Fee rate:"
+    confirm_total__fee_rate_colon = 220,  // "Fee rate:"
     confirm_total__sending_from_account = 221,  // "Sending from account:"
-    confirm_total__title_fee = 222,  // "Fee information"
+    confirm_total__title_fee = 222,  // "Fee info"
     confirm_total__title_sending_from = 223,  // "Sending from"
     debug__loading_seed = 224,  // "Loading seed"
     debug__loading_seed_not_recommended = 225,  // "Loading private seed is not recommended."
@@ -420,8 +420,7 @@ pub enum TranslatedString {
     eos__sell_ram = 258,  // "Sell RAM"
     #[cfg(feature = "universal_fw")]
     eos__sender = 259,  // "Sender:"
-    #[cfg(feature = "universal_fw")]
-    eos__sign_transaction = 260,  // "Sign transaction"
+    send__sign_transaction = 260,  // "Sign transaction"
     #[cfg(feature = "universal_fw")]
     eos__threshold = 261,  // "Threshold:"
     #[cfg(feature = "universal_fw")]
@@ -940,7 +939,7 @@ pub enum TranslatedString {
     send__title_sending_amount = 650,  // "Sending amount"
     send__title_sending_to = 651,  // "Sending to"
     send__to_the_total_amount = 652,  // "To the total amount:"
-    send__total_amount = 653,  // "Total amount:"
+    send__total_amount_colon = 653,  // "Total amount:"
     send__transaction_id = 654,  // "Transaction ID:"
     send__you_are_contributing = 655,  // "You are contributing:"
     share_words__words_in_order = 656,  // " words in order."
@@ -1271,6 +1270,12 @@ pub enum TranslatedString {
     pin__cancel_description = 870,  // "Continue without PIN"
     pin__cancel_info = 871,  // "Without a PIN, anyone can access this device."
     pin__cancel_setup = 872,  // "Cancel PIN setup"
+    send__cancel_sign = 873,  // "Cancel sign"
+    send__send_from = 874,  // "Send from"
+    instructions__hold_to_sign = 875,  // "Hold to sign"
+    confirm_total__fee_rate = 876,  // "Fee rate"
+    send__incl_transaction_fee = 877,  // "incl. Transaction fee"
+    send__total_amount = 878,  // "Total amount"
 }
 
 impl TranslatedString {
@@ -1617,9 +1622,9 @@ impl TranslatedString {
             Self::coinjoin__title_do_not_disconnect => "Do not disconnect your trezor!",
             Self::coinjoin__title_progress => "Coinjoin in progress",
             Self::coinjoin__waiting_for_others => "Waiting for others",
-            Self::confirm_total__fee_rate => "Fee rate:",
+            Self::confirm_total__fee_rate_colon => "Fee rate:",
             Self::confirm_total__sending_from_account => "Sending from account:",
-            Self::confirm_total__title_fee => "Fee information",
+            Self::confirm_total__title_fee => "Fee info",
             Self::confirm_total__title_sending_from => "Sending from",
             Self::debug__loading_seed => "Loading seed",
             Self::debug__loading_seed_not_recommended => "Loading private seed is not recommended.",
@@ -1686,8 +1691,7 @@ impl TranslatedString {
             Self::eos__sell_ram => "Sell RAM",
             #[cfg(feature = "universal_fw")]
             Self::eos__sender => "Sender:",
-            #[cfg(feature = "universal_fw")]
-            Self::eos__sign_transaction => "Sign transaction",
+            Self::send__sign_transaction => "Sign transaction",
             #[cfg(feature = "universal_fw")]
             Self::eos__threshold => "Threshold:",
             #[cfg(feature = "universal_fw")]
@@ -2206,7 +2210,7 @@ impl TranslatedString {
             Self::send__title_sending_amount => "Sending amount",
             Self::send__title_sending_to => "Sending to",
             Self::send__to_the_total_amount => "To the total amount:",
-            Self::send__total_amount => "Total amount:",
+            Self::send__total_amount_colon => "Total amount:",
             Self::send__transaction_id => "Transaction ID:",
             Self::send__you_are_contributing => "You are contributing:",
             Self::share_words__words_in_order => " words in order.",
@@ -2537,6 +2541,12 @@ impl TranslatedString {
             Self::pin__cancel_description => "Continue without PIN",
             Self::pin__cancel_info => "Without a PIN, anyone can access this device.",
             Self::pin__cancel_setup => "Cancel PIN setup",
+            Self::send__cancel_sign => "Cancel sign",
+            Self::send__send_from => "Send from",
+            Self::instructions__hold_to_sign => "Hold to sign",
+            Self::confirm_total__fee_rate => "Fee rate",
+            Self::send__incl_transaction_fee => "incl. Transaction fee",
+            Self::send__total_amount => "Total amount",
         }
     }
 
@@ -2884,7 +2894,7 @@ impl TranslatedString {
             Qstr::MP_QSTR_coinjoin__title_do_not_disconnect => Some(Self::coinjoin__title_do_not_disconnect),
             Qstr::MP_QSTR_coinjoin__title_progress => Some(Self::coinjoin__title_progress),
             Qstr::MP_QSTR_coinjoin__waiting_for_others => Some(Self::coinjoin__waiting_for_others),
-            Qstr::MP_QSTR_confirm_total__fee_rate => Some(Self::confirm_total__fee_rate),
+            Qstr::MP_QSTR_confirm_total__fee_rate_colon => Some(Self::confirm_total__fee_rate_colon),
             Qstr::MP_QSTR_confirm_total__sending_from_account => Some(Self::confirm_total__sending_from_account),
             Qstr::MP_QSTR_confirm_total__title_fee => Some(Self::confirm_total__title_fee),
             Qstr::MP_QSTR_confirm_total__title_sending_from => Some(Self::confirm_total__title_sending_from),
@@ -2953,8 +2963,7 @@ impl TranslatedString {
             Qstr::MP_QSTR_eos__sell_ram => Some(Self::eos__sell_ram),
             #[cfg(feature = "universal_fw")]
             Qstr::MP_QSTR_eos__sender => Some(Self::eos__sender),
-            #[cfg(feature = "universal_fw")]
-            Qstr::MP_QSTR_eos__sign_transaction => Some(Self::eos__sign_transaction),
+            Qstr::MP_QSTR_send__sign_transaction => Some(Self::send__sign_transaction),
             #[cfg(feature = "universal_fw")]
             Qstr::MP_QSTR_eos__threshold => Some(Self::eos__threshold),
             #[cfg(feature = "universal_fw")]
@@ -3473,7 +3482,7 @@ impl TranslatedString {
             Qstr::MP_QSTR_send__title_sending_amount => Some(Self::send__title_sending_amount),
             Qstr::MP_QSTR_send__title_sending_to => Some(Self::send__title_sending_to),
             Qstr::MP_QSTR_send__to_the_total_amount => Some(Self::send__to_the_total_amount),
-            Qstr::MP_QSTR_send__total_amount => Some(Self::send__total_amount),
+            Qstr::MP_QSTR_send__total_amount_colon => Some(Self::send__total_amount_colon),
             Qstr::MP_QSTR_send__transaction_id => Some(Self::send__transaction_id),
             Qstr::MP_QSTR_send__you_are_contributing => Some(Self::send__you_are_contributing),
             Qstr::MP_QSTR_share_words__words_in_order => Some(Self::share_words__words_in_order),
@@ -3804,6 +3813,12 @@ impl TranslatedString {
             Qstr::MP_QSTR_pin__cancel_description => Some(Self::pin__cancel_description),
             Qstr::MP_QSTR_pin__cancel_info => Some(Self::pin__cancel_info),
             Qstr::MP_QSTR_pin__cancel_setup => Some(Self::pin__cancel_setup),
+            Qstr::MP_QSTR_send__cancel_sign => Some(Self::send__cancel_sign),
+            Qstr::MP_QSTR_send__send_from => Some(Self::send__send_from),
+            Qstr::MP_QSTR_instructions__hold_to_sign => Some(Self::instructions__hold_to_sign),
+            Qstr::MP_QSTR_confirm_total__fee_rate => Some(Self::confirm_total__fee_rate),
+            Qstr::MP_QSTR_send__incl_transaction_fee => Some(Self::send__incl_transaction_fee),
+            Qstr::MP_QSTR_send__total_amount => Some(Self::send__total_amount),
             _ => None,
         }
     }
diff --git a/core/embed/rust/src/ui/model_mercury/component/frame.rs b/core/embed/rust/src/ui/model_mercury/component/frame.rs
index 26c50e9d56..b2049fab07 100644
--- a/core/embed/rust/src/ui/model_mercury/component/frame.rs
+++ b/core/embed/rust/src/ui/model_mercury/component/frame.rs
@@ -104,6 +104,7 @@ where
 
     pub fn with_warning_button(self) -> Self {
         self.with_button(theme::ICON_WARNING, CancelInfoConfirmMsg::Info, false)
+            .button_styled(theme::button_danger())
     }
 
     pub fn button_styled(mut self, style: ButtonStyleSheet) -> Self {
diff --git a/core/embed/rust/src/ui/model_mercury/flow/confirm_output.rs b/core/embed/rust/src/ui/model_mercury/flow/confirm_output.rs
new file mode 100644
index 0000000000..9e55a15978
--- /dev/null
+++ b/core/embed/rust/src/ui/model_mercury/flow/confirm_output.rs
@@ -0,0 +1,158 @@
+use crate::{
+    error,
+    micropython::qstr::Qstr,
+    strutil::TString,
+    translations::TR,
+    ui::{
+        component::{ComponentExt, SwipeDirection},
+        flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow, SwipePage},
+    },
+};
+
+use super::super::{
+    component::{
+        AddressDetails, Frame, FrameMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg,
+    },
+    theme,
+};
+
+use super::util::ConfirmBlobParams;
+
+#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
+pub enum ConfirmOutput {
+    Address,
+    Amount,
+    // Tap,
+    Menu,
+    AccountInfo,
+    CancelTap,
+}
+
+impl FlowState for ConfirmOutput {
+    fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
+        match (self, direction) {
+            (ConfirmOutput::Address | ConfirmOutput::Amount, SwipeDirection::Left) => {
+                Decision::Goto(ConfirmOutput::Menu, direction)
+            }
+            (ConfirmOutput::Address, SwipeDirection::Up) => {
+                Decision::Goto(ConfirmOutput::Amount, direction)
+            }
+            (ConfirmOutput::Amount, SwipeDirection::Up) => Decision::Return(FlowMsg::Confirmed),
+            (ConfirmOutput::Amount, SwipeDirection::Down) => {
+                Decision::Goto(ConfirmOutput::Address, direction)
+            }
+            (ConfirmOutput::Menu, SwipeDirection::Right) => {
+                Decision::Goto(ConfirmOutput::Address, direction)
+            }
+            (ConfirmOutput::Menu, SwipeDirection::Left) => {
+                Decision::Goto(ConfirmOutput::AccountInfo, direction)
+            }
+            (ConfirmOutput::AccountInfo | ConfirmOutput::CancelTap, SwipeDirection::Right) => {
+                Decision::Goto(ConfirmOutput::Menu, direction)
+            }
+            _ => Decision::Nothing,
+        }
+    }
+
+    fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
+        match (self, msg) {
+            (_, FlowMsg::Info) => Decision::Goto(ConfirmOutput::Menu, SwipeDirection::Left),
+            (ConfirmOutput::Menu, FlowMsg::Choice(0)) => {
+                Decision::Goto(ConfirmOutput::AccountInfo, SwipeDirection::Left)
+            }
+            (ConfirmOutput::Menu, FlowMsg::Choice(1)) => {
+                Decision::Goto(ConfirmOutput::CancelTap, SwipeDirection::Left)
+            }
+            (ConfirmOutput::Menu, FlowMsg::Cancelled) => {
+                Decision::Goto(ConfirmOutput::Address, SwipeDirection::Right)
+            }
+            (ConfirmOutput::CancelTap, FlowMsg::Confirmed) => Decision::Return(FlowMsg::Cancelled),
+            (_, FlowMsg::Cancelled) => Decision::Goto(ConfirmOutput::Menu, SwipeDirection::Right),
+            _ => Decision::Nothing,
+        }
+    }
+}
+
+use crate::{
+    micropython::{map::Map, obj::Obj, util},
+    ui::layout::obj::LayoutObj,
+};
+
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
+pub extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
+    unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmOutput::new_obj) }
+}
+
+impl ConfirmOutput {
+    const EXTRA_PADDING: i16 = 6;
+
+    fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
+        let title: Option<TString> = kwargs.get(Qstr::MP_QSTR_title)?.try_into_option()?;
+        let account: Option<TString> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?;
+        let account_path: Option<TString> =
+            kwargs.get(Qstr::MP_QSTR_account_path)?.try_into_option()?;
+
+        let address: Obj = kwargs.get(Qstr::MP_QSTR_address)?;
+        let amount: Obj = kwargs.get(Qstr::MP_QSTR_amount)?;
+
+        let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
+        let text_mono: bool = kwargs.get_or(Qstr::MP_QSTR_text_mono, true)?;
+
+        // Address
+        let content_address = ConfirmBlobParams::new(TR::words__address.into(), address, None)
+            .with_subtitle(title)
+            .with_menu_button()
+            .with_footer(TR::instructions__swipe_up.into(), None)
+            .with_chunkify(chunkify)
+            .with_text_mono(text_mono)
+            .into_layout()?;
+        // .one_button_request(ButtonRequestCode::ConfirmOutput, br_type);
+
+        // Amount
+        let content_amount = ConfirmBlobParams::new(TR::words__amount.into(), amount, None)
+            .with_subtitle(title)
+            .with_menu_button()
+            .with_footer(TR::instructions__swipe_up.into(), None)
+            .with_text_mono(text_mono)
+            .into_layout()?;
+        // .one_button_request(ButtonRequestCode::ConfirmOutput, br_type);
+
+        // Menu
+        let content_menu = Frame::left_aligned(
+            "".into(),
+            VerticalMenu::empty()
+                .item(theme::ICON_CHEVRON_RIGHT, "Account info".into())
+                .danger(theme::ICON_CANCEL, "Cancel sign".into()),
+        )
+        .with_cancel_button()
+        .map(|msg| match msg {
+            FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
+            FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
+        });
+
+        // AccountInfo
+        let ad = AddressDetails::new(TR::send__send_from.into(), account, account_path)?;
+        let content_account = SwipePage::horizontal(ad).map(|_| Some(FlowMsg::Cancelled));
+
+        // CancelTap
+        let content_cancel_tap = Frame::left_aligned(
+            TR::send__cancel_sign.into(),
+            PromptScreen::new_tap_to_cancel(),
+        )
+        .with_cancel_button()
+        .with_footer(TR::instructions__tap_to_confirm.into(), None)
+        .map(|msg| match msg {
+            FrameMsg::Content(()) => Some(FlowMsg::Confirmed),
+            FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
+        });
+
+        let store = flow_store()
+            .add(content_address)?
+            .add(content_amount)?
+            .add(content_menu)?
+            .add(content_account)?
+            .add(content_cancel_tap)?;
+        let res = SwipeFlow::new(ConfirmOutput::Address, store)?;
+        Ok(LayoutObj::new(res)?.into())
+    }
+}
diff --git a/core/embed/rust/src/ui/model_mercury/flow/confirm_summary.rs b/core/embed/rust/src/ui/model_mercury/flow/confirm_summary.rs
new file mode 100644
index 0000000000..2b465394cd
--- /dev/null
+++ b/core/embed/rust/src/ui/model_mercury/flow/confirm_summary.rs
@@ -0,0 +1,169 @@
+use crate::{
+    error,
+    micropython::{iter::IterBuf, qstr::Qstr},
+    strutil::TString,
+    translations::TR,
+    ui::{
+        component::{ComponentExt, SwipeDirection},
+        flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
+    },
+};
+
+use super::super::{
+    component::{Frame, FrameMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg},
+    theme,
+};
+
+use super::util::ShowInfoParams;
+
+#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
+pub enum ConfirmSummary {
+    Summary,
+    Hold,
+    Menu,
+    FeeInfo,
+    AccountInfo,
+    CancelTap,
+}
+
+impl FlowState for ConfirmSummary {
+    fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
+        match (self, direction) {
+            (ConfirmSummary::Summary | ConfirmSummary::Hold, SwipeDirection::Left) => {
+                Decision::Goto(ConfirmSummary::Menu, direction)
+            }
+            (ConfirmSummary::Summary, SwipeDirection::Up) => {
+                Decision::Goto(ConfirmSummary::Hold, direction)
+            }
+            (ConfirmSummary::Hold, SwipeDirection::Down) => {
+                Decision::Goto(ConfirmSummary::Summary, direction)
+            }
+            (ConfirmSummary::Menu, SwipeDirection::Right) => {
+                Decision::Goto(ConfirmSummary::Summary, direction)
+            }
+            (ConfirmSummary::Menu, SwipeDirection::Left) => {
+                Decision::Goto(ConfirmSummary::FeeInfo, direction)
+            }
+            (
+                ConfirmSummary::AccountInfo | ConfirmSummary::FeeInfo | ConfirmSummary::CancelTap,
+                SwipeDirection::Right,
+            ) => Decision::Goto(ConfirmSummary::Menu, direction),
+            _ => Decision::Nothing,
+        }
+    }
+
+    fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
+        match (self, msg) {
+            (_, FlowMsg::Info) => Decision::Goto(ConfirmSummary::Menu, SwipeDirection::Left),
+            (ConfirmSummary::Hold, FlowMsg::Confirmed) => Decision::Return(FlowMsg::Confirmed),
+            (ConfirmSummary::Menu, FlowMsg::Choice(0)) => {
+                Decision::Goto(ConfirmSummary::FeeInfo, SwipeDirection::Left)
+            }
+            (ConfirmSummary::Menu, FlowMsg::Choice(1)) => {
+                Decision::Goto(ConfirmSummary::AccountInfo, SwipeDirection::Left)
+            }
+            (ConfirmSummary::Menu, FlowMsg::Choice(2)) => {
+                Decision::Goto(ConfirmSummary::CancelTap, SwipeDirection::Left)
+            }
+            (ConfirmSummary::Menu, FlowMsg::Cancelled) => {
+                Decision::Goto(ConfirmSummary::Summary, SwipeDirection::Right)
+            }
+            (ConfirmSummary::CancelTap, FlowMsg::Confirmed) => Decision::Return(FlowMsg::Cancelled),
+            (_, FlowMsg::Cancelled) => Decision::Goto(ConfirmSummary::Menu, SwipeDirection::Right),
+            _ => Decision::Nothing,
+        }
+    }
+}
+
+use crate::{
+    micropython::{map::Map, obj::Obj, util},
+    ui::layout::obj::LayoutObj,
+};
+
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
+pub extern "C" fn new_confirm_summary(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
+    unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmSummary::new_obj) }
+}
+
+impl ConfirmSummary {
+    fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
+        let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
+        let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
+        let account_items: Obj = kwargs.get(Qstr::MP_QSTR_account_items)?;
+        let fee_items: Obj = kwargs.get(Qstr::MP_QSTR_fee_items)?;
+
+        // Summary
+        let mut summary = ShowInfoParams::new(title)
+            .with_menu_button()
+            .with_footer(TR::instructions__swipe_up.into(), None);
+        for pair in IterBuf::new().try_iterate(items)? {
+            let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
+            summary = unwrap!(summary.add(label, value));
+        }
+        let content_summary = summary.into_layout()?;
+
+        // Hold to confirm
+        let content_hold = Frame::left_aligned(
+            TR::send__sign_transaction.into(),
+            PromptScreen::new_hold_to_confirm(),
+        )
+        .with_menu_button()
+        .with_footer(TR::instructions__hold_to_sign.into(), None)
+        .map(|msg| match msg {
+            FrameMsg::Content(()) => Some(FlowMsg::Confirmed),
+            FrameMsg::Button(_) => Some(FlowMsg::Info),
+        });
+
+        // Menu
+        let content_menu = Frame::left_aligned(
+            "".into(),
+            VerticalMenu::empty()
+                .item(theme::ICON_CHEVRON_RIGHT, "Fee info".into())
+                .item(theme::ICON_CHEVRON_RIGHT, "Account info".into())
+                .danger(theme::ICON_CANCEL, "Cancel sign".into()),
+        )
+        .with_cancel_button()
+        .map(|msg| match msg {
+            FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
+            FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
+        });
+
+        // FeeInfo
+        let mut fee = ShowInfoParams::new(TR::confirm_total__title_fee.into()).with_cancel_button();
+        for pair in IterBuf::new().try_iterate(fee_items)? {
+            let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
+            fee = unwrap!(fee.add(label, value));
+        }
+        let content_fee = fee.into_layout()?;
+
+        // AccountInfo
+        let mut account = ShowInfoParams::new(TR::send__send_from.into()).with_cancel_button();
+        for pair in IterBuf::new().try_iterate(account_items)? {
+            let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
+            account = unwrap!(account.add(label, value));
+        }
+        let content_account = account.into_layout()?;
+
+        // CancelTap
+        let content_cancel_tap = Frame::left_aligned(
+            TR::send__cancel_sign.into(),
+            PromptScreen::new_tap_to_cancel(),
+        )
+        .with_cancel_button()
+        .with_footer(TR::instructions__tap_to_confirm.into(), None)
+        .map(|msg| match msg {
+            FrameMsg::Content(()) => Some(FlowMsg::Confirmed),
+            FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
+        });
+
+        let store = flow_store()
+            .add(content_summary)?
+            .add(content_hold)?
+            .add(content_menu)?
+            .add(content_fee)?
+            .add(content_account)?
+            .add(content_cancel_tap)?;
+        let res = SwipeFlow::new(ConfirmSummary::Summary, store)?;
+        Ok(LayoutObj::new(res)?.into())
+    }
+}
diff --git a/core/embed/rust/src/ui/model_mercury/flow/mod.rs b/core/embed/rust/src/ui/model_mercury/flow/mod.rs
index cf7533821b..ba950ea663 100644
--- a/core/embed/rust/src/ui/model_mercury/flow/mod.rs
+++ b/core/embed/rust/src/ui/model_mercury/flow/mod.rs
@@ -1,16 +1,22 @@
 pub mod confirm_action;
+pub mod confirm_output;
 pub mod confirm_reset_create;
 pub mod confirm_reset_recover;
 pub mod confirm_set_new_pin;
+pub mod confirm_summary;
 pub mod get_address;
 pub mod prompt_backup;
 pub mod show_share_words;
 pub mod warning_hi_prio;
 
 pub use confirm_action::new_confirm_action;
+mod util;
+
+pub use confirm_output::new_confirm_output;
 pub use confirm_reset_create::ConfirmResetCreate;
 pub use confirm_reset_recover::ConfirmResetRecover;
 pub use confirm_set_new_pin::SetNewPin;
+pub use confirm_summary::new_confirm_summary;
 pub use get_address::GetAddress;
 pub use prompt_backup::PromptBackup;
 pub use show_share_words::ShowShareWords;
diff --git a/core/embed/rust/src/ui/model_mercury/flow/util.rs b/core/embed/rust/src/ui/model_mercury/flow/util.rs
new file mode 100644
index 0000000000..41c41fa7bc
--- /dev/null
+++ b/core/embed/rust/src/ui/model_mercury/flow/util.rs
@@ -0,0 +1,236 @@
+use super::super::{
+    component::{Frame, FrameMsg},
+    theme,
+};
+use crate::{
+    error::Error,
+    maybe_trace::MaybeTrace,
+    micropython::obj::Obj,
+    strutil::TString,
+    ui::{
+        component::{
+            base::ComponentExt,
+            text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, VecExt},
+            Component,
+        },
+        flow::{FlowMsg, Swipable, SwipePage},
+        layout::util::ConfirmBlob,
+    },
+};
+use heapless::Vec;
+
+pub struct ConfirmBlobParams {
+    title: TString<'static>,
+    subtitle: Option<TString<'static>>,
+    footer_instruction: Option<TString<'static>>,
+    footer_description: Option<TString<'static>>,
+    data: Obj,
+    description: Option<TString<'static>>,
+    extra: Option<TString<'static>>,
+    menu_button: bool,
+    chunkify: bool,
+    text_mono: bool,
+}
+
+impl ConfirmBlobParams {
+    pub const fn new(
+        title: TString<'static>,
+        data: Obj,
+        description: Option<TString<'static>>,
+    ) -> Self {
+        Self {
+            title,
+            subtitle: None,
+            footer_instruction: None,
+            footer_description: None,
+            data,
+            description,
+            extra: None,
+            menu_button: false,
+            chunkify: false,
+            text_mono: true,
+        }
+    }
+
+    pub const fn with_extra(mut self, extra: Option<TString<'static>>) -> Self {
+        self.extra = extra;
+        self
+    }
+
+    pub const fn with_subtitle(mut self, subtitle: Option<TString<'static>>) -> Self {
+        self.subtitle = subtitle;
+        self
+    }
+
+    pub const fn with_menu_button(mut self) -> Self {
+        self.menu_button = true;
+        self
+    }
+
+    pub const fn with_footer(
+        mut self,
+        instruction: TString<'static>,
+        description: Option<TString<'static>>,
+    ) -> Self {
+        self.footer_instruction = Some(instruction);
+        self.footer_description = description;
+        self
+    }
+
+    pub const fn with_chunkify(mut self, chunkify: bool) -> Self {
+        self.chunkify = chunkify;
+        self
+    }
+
+    pub const fn with_text_mono(mut self, text_mono: bool) -> Self {
+        self.text_mono = text_mono;
+        self
+    }
+
+    pub fn into_layout(
+        self,
+    ) -> Result<impl Component<Msg = FlowMsg> + Swipable + MaybeTrace, Error> {
+        let paragraphs = ConfirmBlob {
+            description: self.description.unwrap_or("".into()),
+            extra: self.extra.unwrap_or("".into()),
+            data: self.data.try_into()?,
+            description_font: &theme::TEXT_NORMAL,
+            extra_font: &theme::TEXT_DEMIBOLD,
+            data_font: if self.chunkify {
+                let data: TString = self.data.try_into()?;
+                theme::get_chunkified_text_style(data.len())
+            } else if self.text_mono {
+                &theme::TEXT_MONO
+            } else {
+                &theme::TEXT_NORMAL
+            },
+        }
+        .into_paragraphs();
+
+        let page = SwipePage::vertical(paragraphs);
+        let mut frame = Frame::left_aligned(self.title, page);
+        if let Some(subtitle) = self.subtitle {
+            frame = frame.with_subtitle(subtitle);
+        }
+        if self.menu_button {
+            frame = frame.with_menu_button();
+        }
+        if let Some(instruction) = self.footer_instruction {
+            frame = frame.with_footer(instruction, self.footer_description);
+        }
+        Ok(frame.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info)))
+    }
+}
+
+pub struct ShowInfoParams {
+    title: TString<'static>,
+    subtitle: Option<TString<'static>>,
+    menu_button: bool,
+    cancel_button: bool,
+    footer_instruction: Option<TString<'static>>,
+    footer_description: Option<TString<'static>>,
+    chunkify: bool,
+    items: Vec<(TString<'static>, TString<'static>), 4>,
+}
+
+impl ShowInfoParams {
+    pub const fn new(title: TString<'static>) -> Self {
+        Self {
+            title,
+            subtitle: None,
+            menu_button: false,
+            cancel_button: false,
+            footer_instruction: None,
+            footer_description: None,
+            chunkify: false,
+            items: Vec::new(),
+        }
+    }
+
+    pub fn add(mut self, key: TString<'static>, value: TString<'static>) -> Option<Self> {
+        if self.items.push((key, value)).is_ok() {
+            Some(self)
+        } else {
+            None
+        }
+    }
+
+    pub const fn with_subtitle(mut self, subtitle: Option<TString<'static>>) -> Self {
+        self.subtitle = subtitle;
+        self
+    }
+
+    pub const fn with_menu_button(mut self) -> Self {
+        self.menu_button = true;
+        self
+    }
+
+    pub const fn with_cancel_button(mut self) -> Self {
+        self.cancel_button = true;
+        self
+    }
+
+    pub const fn with_footer(
+        mut self,
+        instruction: TString<'static>,
+        description: Option<TString<'static>>,
+    ) -> Self {
+        self.footer_instruction = Some(instruction);
+        self.footer_description = description;
+        self
+    }
+
+    pub const fn with_chunkify(mut self, chunkify: bool) -> Self {
+        self.chunkify = chunkify;
+        self
+    }
+
+    pub fn into_layout(
+        self,
+    ) -> Result<impl Component<Msg = FlowMsg> + Swipable + MaybeTrace, Error> {
+        let mut paragraphs = ParagraphVecShort::new();
+        let mut first: bool = true;
+        for item in self.items {
+            // FIXME: padding:
+            if !first {
+                paragraphs.add(Paragraph::new::<TString<'static>>(
+                    &theme::TEXT_SUB_GREY,
+                    " ".into(),
+                ));
+            }
+            first = false;
+            paragraphs.add(Paragraph::new(&theme::TEXT_SUB_GREY, item.0).no_break());
+            if self.chunkify {
+                paragraphs.add(Paragraph::new(
+                    theme::get_chunkified_text_style(item.1.len()),
+                    item.1,
+                ));
+            } else {
+                paragraphs.add(Paragraph::new(&theme::TEXT_MONO_GREY_LIGHT, item.1));
+            }
+        }
+
+        let mut frame = Frame::left_aligned(
+            self.title,
+            SwipePage::vertical(paragraphs.into_paragraphs()),
+        );
+        if let Some(subtitle) = self.subtitle {
+            frame = frame.with_subtitle(subtitle);
+        }
+        if self.cancel_button {
+            frame = frame.with_cancel_button();
+        } else if self.menu_button {
+            frame = frame.with_menu_button();
+        }
+        if let Some(instruction) = self.footer_instruction {
+            frame = frame.with_footer(instruction, self.footer_description);
+        }
+        Ok(frame.map(move |msg| {
+            matches!(msg, FrameMsg::Button(_)).then_some(if self.cancel_button {
+                FlowMsg::Cancelled
+            } else {
+                FlowMsg::Info
+            })
+        }))
+    }
+}
diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs
index 5e498151f0..9cbf6bfbd5 100644
--- a/core/embed/rust/src/ui/model_mercury/layout.rs
+++ b/core/embed/rust/src/ui/model_mercury/layout.rs
@@ -893,6 +893,7 @@ extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map
         let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
         let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
         let value: TString = kwargs.get_or(Qstr::MP_QSTR_value, "".into())?;
+        let action: Option<TString> = kwargs.get(Qstr::MP_QSTR_button)?.try_into_option()?;
 
         let content = SwipeUpScreen::new(Paragraphs::new([
             Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description),
@@ -901,8 +902,7 @@ extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map
         let obj = LayoutObj::new(
             Frame::left_aligned(title, content)
                 .with_warning_button()
-                .button_styled(theme::button_warning_low())
-                .with_footer(TR::instructions__swipe_up.into(), None),
+                .with_footer(TR::instructions__swipe_up.into(), action),
         )?;
         Ok(obj.into())
     };
@@ -1992,6 +1992,28 @@ pub static mp_module_trezorui2: Module = obj_module! {
     /// ) -> LayoutObj[UiResult]:
     ///     """Warning modal with multiple steps to confirm."""
     Qstr::MP_QSTR_flow_warning_hi_prio => obj_fn_kw!(0, flow::warning_hi_prio::new_warning_hi_prio).as_obj(),
+
+    /// def flow_confirm_output(
+    ///     *,
+    ///     title: str | None,
+    ///     address: str,
+    ///     amount: str,
+    ///     chunkify: bool,
+    ///     account: str | None,
+    ///     account_path: str | None,
+    /// ) -> LayoutObj[UiResult]:
+    ///     """Confirm recipient."""
+    Qstr::MP_QSTR_flow_confirm_output => obj_fn_kw!(0, flow::new_confirm_output).as_obj(),
+
+    /// def flow_confirm_summary(
+    ///     *,
+    ///     title: str,
+    ///     items: Iterable[tuple[str, str]],
+    ///     account_items: Iterable[tuple[str, str]],
+    ///     fee_items: Iterable[tuple[str, str]],
+    /// ) -> LayoutObj[UiResult]:
+    ///     """Total summary and hold to confirm."""
+    Qstr::MP_QSTR_flow_confirm_summary => obj_fn_kw!(0, flow::new_confirm_summary).as_obj(),
 };
 
 #[cfg(test)]
diff --git a/core/embed/rust/src/ui/model_tr/layout.rs b/core/embed/rust/src/ui/model_tr/layout.rs
index 4749e61a3f..bc56bd6570 100644
--- a/core/embed/rust/src/ui/model_tr/layout.rs
+++ b/core/embed/rust/src/ui/model_tr/layout.rs
@@ -658,7 +658,7 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
                         .newline()
                         .newline()
                         .newline_half()
-                        .text_bold(TR::confirm_total__fee_rate)
+                        .text_bold(TR::confirm_total__fee_rate_colon)
                         .newline()
                         .text_mono(fee_rate_amount);
 
diff --git a/core/mocks/generated/trezorui2.pyi b/core/mocks/generated/trezorui2.pyi
index 97f0eef915..94e8f6b6f0 100644
--- a/core/mocks/generated/trezorui2.pyi
+++ b/core/mocks/generated/trezorui2.pyi
@@ -549,6 +549,30 @@ def flow_warning_hi_prio(
     value: str = "",
 ) -> LayoutObj[UiResult]:
     """Warning modal with multiple steps to confirm."""
+
+
+# rust/src/ui/model_mercury/layout.rs
+def flow_confirm_output(
+    *,
+    title: str | None,
+    address: str,
+    amount: str,
+    chunkify: bool,
+    account: str | None,
+    account_path: str | None,
+) -> LayoutObj[UiResult]:
+    """Confirm recipient."""
+
+
+# rust/src/ui/model_mercury/layout.rs
+def flow_confirm_summary(
+    *,
+    title: str,
+    items: Iterable[tuple[str, str]],
+    account_items: Iterable[tuple[str, str]],
+    fee_items: Iterable[tuple[str, str]],
+) -> LayoutObj[UiResult]:
+    """Total summary and hold to confirm."""
 CONFIRMED: UiResult
 CANCELLED: UiResult
 INFO: UiResult
diff --git a/core/mocks/trezortranslate_keys.pyi b/core/mocks/trezortranslate_keys.pyi
index f0c83db410..3e9bb6e33d 100644
--- a/core/mocks/trezortranslate_keys.pyi
+++ b/core/mocks/trezortranslate_keys.pyi
@@ -235,9 +235,10 @@ class TR:
     coinjoin__title_do_not_disconnect: str = "Do not disconnect your trezor!"
     coinjoin__title_progress: str = "Coinjoin in progress"
     coinjoin__waiting_for_others: str = "Waiting for others"
-    confirm_total__fee_rate: str = "Fee rate:"
+    confirm_total__fee_rate: str = "Fee rate"
+    confirm_total__fee_rate_colon: str = "Fee rate:"
     confirm_total__sending_from_account: str = "Sending from account:"
-    confirm_total__title_fee: str = "Fee information"
+    confirm_total__title_fee: str = "Fee info"
     confirm_total__title_sending_from: str = "Sending from"
     debug__loading_seed: str = "Loading seed"
     debug__loading_seed_not_recommended: str = "Loading private seed is not recommended."
@@ -275,7 +276,6 @@ class TR:
     eos__requirement: str = "Requirement:"
     eos__sell_ram: str = "Sell RAM"
     eos__sender: str = "Sender:"
-    eos__sign_transaction: str = "Sign transaction"
     eos__threshold: str = "Threshold:"
     eos__to: str = "To:"
     eos__transfer: str = "Transfer:"
@@ -364,6 +364,7 @@ class TR:
     inputs__space: str = "SPACE"
     instructions__continue_in_app: str = "Continue in the app"
     instructions__hold_to_confirm: str = "Hold to confirm"
+    instructions__hold_to_sign: str = "Hold to sign"
     instructions__swipe_up: str = "Swipe up"
     instructions__tap_to_confirm: str = "Tap to confirm"
     joint__title: str = "Joint transaction"
@@ -675,11 +676,15 @@ class TR:
     sd_card__wanna_format: str = "Do you really want to format the SD card?"
     sd_card__wrong_sd_card: str = "Wrong SD card."
     send__address_path: str = "address path"
+    send__cancel_sign: str = "Cancel sign"
     send__confirm_sending: str = "Sending amount"
     send__from_multiple_accounts: str = "Sending from multiple accounts."
+    send__incl_transaction_fee: str = "incl. Transaction fee"
     send__including_fee: str = "Including fee:"
     send__maximum_fee: str = "Maximum fee:"
     send__receiving_to_multisig: str = "Receiving to a multisig address."
+    send__send_from: str = "Send from"
+    send__sign_transaction: str = "Sign transaction"
     send__title_confirm_sending: str = "Confirm sending"
     send__title_joint_transaction: str = "Joint transaction"
     send__title_receiving_to: str = "Receiving to"
@@ -687,7 +692,8 @@ class TR:
     send__title_sending_amount: str = "Sending amount"
     send__title_sending_to: str = "Sending to"
     send__to_the_total_amount: str = "To the total amount:"
-    send__total_amount: str = "Total amount:"
+    send__total_amount: str = "Total amount"
+    send__total_amount_colon: str = "Total amount:"
     send__transaction_id: str = "Transaction ID:"
     send__you_are_contributing: str = "You are contributing:"
     share_words__words_in_order: str = " words in order."
diff --git a/core/src/apps/bitcoin/sign_tx/approvers.py b/core/src/apps/bitcoin/sign_tx/approvers.py
index bdbadf8042..38078478ba 100644
--- a/core/src/apps/bitcoin/sign_tx/approvers.py
+++ b/core/src/apps/bitcoin/sign_tx/approvers.py
@@ -121,6 +121,7 @@ class Approver:
         self,
         txo: TxOutput,
         script_pubkey: bytes,
+        tx_info: TxInfo | None,
         orig_txo: TxOutput | None = None,
     ) -> None:
         await self._add_output(txo, script_pubkey)
@@ -193,11 +194,12 @@ class BasicApprover(Approver):
         self,
         txo: TxOutput,
         script_pubkey: bytes,
+        tx_info: TxInfo | None,
         orig_txo: TxOutput | None = None,
     ) -> None:
         from trezor.enums import OutputScriptType
 
-        await super().add_external_output(txo, script_pubkey, orig_txo)
+        await super().add_external_output(txo, script_pubkey, tx_info, orig_txo)
 
         if orig_txo:
             if txo.amount < orig_txo.amount:
@@ -230,6 +232,7 @@ class BasicApprover(Approver):
                     "Adding new OP_RETURN outputs in replacement transactions is not supported."
                 )
         elif txo.payment_req_index is None or self.show_payment_req_details:
+            source_path = tx_info.wallet_path.get_path() if tx_info else None
             # Ask user to confirm output, unless it is part of a payment
             # request, which gets confirmed separately.
             await helpers.confirm_output(
@@ -238,6 +241,7 @@ class BasicApprover(Approver):
                 self.amount_unit,
                 self.external_output_index,
                 self.chunkify,
+                source_path,
             )
             self.external_output_index += 1
 
diff --git a/core/src/apps/bitcoin/sign_tx/bitcoin.py b/core/src/apps/bitcoin/sign_tx/bitcoin.py
index ec31da941e..08c3aea391 100644
--- a/core/src/apps/bitcoin/sign_tx/bitcoin.py
+++ b/core/src/apps/bitcoin/sign_tx/bitcoin.py
@@ -530,7 +530,9 @@ class Bitcoin:
             # Output is change and does not need approval.
             await approver.add_change_output(txo, script_pubkey)
         else:
-            await approver.add_external_output(txo, script_pubkey, orig_txo)
+            await approver.add_external_output(
+                txo, script_pubkey, self.tx_info, orig_txo
+            )
 
         self.tx_info.add_output(txo, script_pubkey)
 
diff --git a/core/src/apps/bitcoin/sign_tx/decred.py b/core/src/apps/bitcoin/sign_tx/decred.py
index 5ba638d99f..6c842f38ba 100644
--- a/core/src/apps/bitcoin/sign_tx/decred.py
+++ b/core/src/apps/bitcoin/sign_tx/decred.py
@@ -92,7 +92,9 @@ class DecredApprover(BasicApprover):
     ) -> None:
         # NOTE: The following calls Approver.add_external_output(), not BasicApprover.add_external_output().
         # This is needed to skip calling helpers.confirm_output(), which is what BasicApprover would do.
-        await super(BasicApprover, self).add_external_output(txo, script_pubkey, None)
+        await super(BasicApprover, self).add_external_output(
+            txo, script_pubkey, None, None
+        )
         await helpers.confirm_decred_sstx_submission(txo, self.coin, self.amount_unit)
 
 
diff --git a/core/src/apps/bitcoin/sign_tx/helpers.py b/core/src/apps/bitcoin/sign_tx/helpers.py
index a27ef12387..5fa6f0a8a5 100644
--- a/core/src/apps/bitcoin/sign_tx/helpers.py
+++ b/core/src/apps/bitcoin/sign_tx/helpers.py
@@ -45,12 +45,14 @@ class UiConfirmOutput(UiConfirm):
         amount_unit: AmountUnit,
         output_index: int,
         chunkify: bool,
+        address_n: Bip32Path | None,
     ):
         self.output = output
         self.coin = coin
         self.amount_unit = amount_unit
         self.output_index = output_index
         self.chunkify = chunkify
+        self.address_n = address_n
 
     def confirm_dialog(self) -> Awaitable[Any]:
         return layout.confirm_output(
@@ -59,6 +61,7 @@ class UiConfirmOutput(UiConfirm):
             self.amount_unit,
             self.output_index,
             self.chunkify,
+            self.address_n,
         )
 
 
@@ -241,8 +244,12 @@ class UiConfirmMultipleAccounts(UiConfirm):
         return layout.confirm_multiple_accounts()
 
 
-def confirm_output(output: TxOutput, coin: CoinInfo, amount_unit: AmountUnit, output_index: int, chunkify: bool) -> Awaitable[None]:  # type: ignore [awaitable-return-type]
-    return (yield UiConfirmOutput(output, coin, amount_unit, output_index, chunkify))  # type: ignore [awaitable-return-type]
+def confirm_output(output: TxOutput, coin: CoinInfo, amount_unit: AmountUnit, output_index: int, chunkify: bool, address_n: Bip32Path | None) -> Awaitable[None]:  # type: ignore [awaitable-return-type]
+    return (
+        yield UiConfirmOutput(  # type: ignore [awaitable-return-type]
+            output, coin, amount_unit, output_index, chunkify, address_n
+        )
+    )
 
 
 def confirm_decred_sstx_submission(output: TxOutput, coin: CoinInfo, amount_unit: AmountUnit) -> Awaitable[None]:  # type: ignore [awaitable-return-type]
diff --git a/core/src/apps/bitcoin/sign_tx/layout.py b/core/src/apps/bitcoin/sign_tx/layout.py
index fdb55141ef..cf4044cc8a 100644
--- a/core/src/apps/bitcoin/sign_tx/layout.py
+++ b/core/src/apps/bitcoin/sign_tx/layout.py
@@ -62,6 +62,7 @@ async def confirm_output(
     amount_unit: AmountUnit,
     output_index: int,
     chunkify: bool,
+    address_n: Bip32Path | None,
 ) -> None:
     from trezor.enums import OutputScriptType
 
@@ -119,6 +120,8 @@ async def confirm_output(
             address_label=address_label,
             output_index=output_index,
             chunkify=chunkify,
+            source_account=account_label(coin, address_n),
+            source_account_path=address_n_to_str(address_n) if address_n else None,
         )
 
     await layout
@@ -245,7 +248,8 @@ async def confirm_total(
         format_coin_amount(spending, coin, amount_unit),
         format_coin_amount(fee, coin, amount_unit),
         fee_rate_amount=format_fee_rate(fee_rate, coin) if fee_rate >= 0 else None,
-        account_label=account_label(coin, address_n),
+        source_account=account_label(coin, address_n),
+        source_account_path=address_n_to_str(address_n) if address_n else None,
     )
 
 
diff --git a/core/src/apps/eos/layout.py b/core/src/apps/eos/layout.py
index dc12df31c2..994394f0e8 100644
--- a/core/src/apps/eos/layout.py
+++ b/core/src/apps/eos/layout.py
@@ -14,7 +14,7 @@ async def require_sign_tx(num_actions: int) -> None:
 
     await confirm_action(
         "confirm_tx",
-        TR.eos__sign_transaction,
+        TR.send__sign_transaction,
         description=TR.eos__about_to_sign_template,
         description_param=format_plural(
             "{count} {plural}", num_actions, TR.plurals__sign_x_actions
diff --git a/core/src/trezor/ui/layouts/mercury/__init__.py b/core/src/trezor/ui/layouts/mercury/__init__.py
index fc6c3f6e44..c150b7fff1 100644
--- a/core/src/trezor/ui/layouts/mercury/__init__.py
+++ b/core/src/trezor/ui/layouts/mercury/__init__.py
@@ -187,7 +187,7 @@ class RustLayout(ui.Layout):
         # Turn the brightness on again.
         ui.backlight_fade(self.BACKLIGHT_LEVEL)
 
-    def handle_input_and_rendering(self) -> loop.Task:  # type: ignore [awaitable-is-generator]
+    def handle_input_and_rendering(self) -> loop.Task:
         from trezor import workflow
 
         touch = loop.wait(io.TOUCH)
@@ -203,7 +203,7 @@ class RustLayout(ui.Layout):
                 raise ui.Result(msg)
             self._paint()
 
-    def handle_timers(self) -> loop.Task:  # type: ignore [awaitable-is-generator]
+    def handle_timers(self) -> loop.Task:
         while True:
             # Using `yield` instead of `await` to avoid allocations.
             token = yield self.timer
@@ -499,9 +499,9 @@ async def show_warning(
         interact(
             RustLayout(
                 trezorui2.show_warning(
-                    title=content,
-                    description=subheader or "",
-                    button=button,
+                    title=TR.words__important,
+                    value=content,
+                    button=subheader or TR.words__continue_anyway,
                 )
             ),
             br_type,
@@ -539,58 +539,35 @@ async def confirm_output(
     address_label: str | None = None,
     output_index: int | None = None,
     chunkify: bool = False,
+    source_account: str | None = None,
+    source_account_path: str | None = None,
 ) -> None:
-    if title is not None:
-        # TODO: handle translation
-        if title.upper().startswith("CONFIRM "):
-            title = title[len("CONFIRM ") :]
-        amount_title = title
-        recipient_title = title
+    if address_label is not None:
+        title = address_label
+    elif title is not None:
+        pass
     elif output_index is not None:
-        amount_title = f"{TR.words__amount} #{output_index + 1}"
-        recipient_title = f"{TR.words__recipient} #{output_index + 1}"
+        title = f"{TR.words__recipient} #{output_index + 1}"
     else:
-        amount_title = TR.send__confirm_sending
-        recipient_title = TR.send__title_sending_to
+        title = TR.send__title_sending_to
 
-    while True:
-        result = await interact(
+    # TODO: this should send 2x ButtonRequest
+    await raise_if_not_confirmed(
+        interact(
             RustLayout(
-                trezorui2.confirm_value(
-                    title=recipient_title,
-                    subtitle=address_label,
-                    description=None,
-                    value=address,
-                    verb=TR.buttons__continue,
-                    hold=False,
-                    info_button=False,
+                trezorui2.flow_confirm_output(
+                    address=address,
+                    amount=amount,
+                    title=title,
                     chunkify=chunkify,
+                    account=source_account,
+                    account_path=source_account_path,
                 )
             ),
             "confirm_output",
             br_code,
         )
-        if result is not CONFIRMED:
-            raise ActionCancelled
-
-        result = await interact(
-            RustLayout(
-                trezorui2.confirm_value(
-                    title=amount_title,
-                    subtitle=None,
-                    description=None,
-                    value=amount,
-                    verb=None if hold else TR.buttons__confirm,
-                    verb_cancel="^",
-                    hold=hold,
-                    info_button=False,
-                )
-            ),
-            "confirm_output",
-            br_code,
-        )
-        if result is CONFIRMED:
-            return
+    )
 
 
 async def should_show_payment_request_details(
@@ -627,7 +604,7 @@ async def should_show_payment_request_details(
 
 async def should_show_more(
     title: str,
-    para: Iterable[tuple[int, str]],
+    para: Iterable[tuple[int, str | bytes]],
     button_text: str | None = None,
     br_type: str = "should_show_more",
     br_code: ButtonRequestType = BR_TYPE_OTHER,
@@ -876,31 +853,42 @@ async def confirm_total(
     title: str | None = None,
     total_label: str | None = None,
     fee_label: str | None = None,
-    account_label: str | None = None,
+    source_account: str | None = None,
+    source_account_path: str | None = None,
     fee_rate_amount: str | None = None,
     br_type: str = "confirm_total",
     br_code: ButtonRequestType = ButtonRequestType.SignTx,
 ) -> None:
     title = title or TR.words__title_summary  # def_arg
     total_label = total_label or TR.send__total_amount  # def_arg
-    fee_label = fee_label or TR.send__including_fee  # def_arg
+    fee_label = fee_label or TR.send__incl_transaction_fee  # def_arg
 
     items = [
         (total_label, total_amount),
         (fee_label, fee_amount),
     ]
-    info_items = []
-    if account_label:
-        info_items.append((TR.confirm_total__sending_from_account, account_label))
+    fee_items = []
+    account_items = []
+    if source_account:
+        account_items.append((TR.confirm_total__sending_from_account, source_account))
+    if source_account_path:
+        account_items.append((TR.address_details__derivation_path, source_account_path))
     if fee_rate_amount:
-        info_items.append((TR.confirm_total__fee_rate, fee_rate_amount))
+        fee_items.append((TR.confirm_total__fee_rate, fee_rate_amount))
 
-    await confirm_summary(
-        items,
-        TR.words__title_summary,
-        info_items=info_items,
-        br_type=br_type,
-        br_code=br_code,
+    await raise_if_not_confirmed(
+        interact(
+            RustLayout(
+                trezorui2.flow_confirm_summary(
+                    title=title,
+                    items=items,
+                    fee_items=fee_items,
+                    account_items=account_items,
+                )
+            ),
+            br_type,
+            br_code,
+        )
     )
 
 
@@ -912,23 +900,21 @@ async def confirm_summary(
     br_type: str = "confirm_total",
     br_code: ButtonRequestType = ButtonRequestType.SignTx,
 ) -> None:
+    # TODO: info_title
     title = title or TR.words__title_summary  # def_arg
 
-    total_layout = RustLayout(
-        trezorui2.confirm_total(
-            title=title,
-            items=items,
-            info_button=bool(info_items),
+    await raise_if_not_confirmed(
+        RustLayout(
+            trezorui2.flow_confirm_summary(
+                title=title,
+                items=items or (),
+                fee_items=(),
+                account_items=info_items or (),
+            )
         )
+        # TODO br_type,
+        # TODO br_code,
     )
-    info_items = info_items or []
-    info_layout = RustLayout(
-        trezorui2.show_info_with_cancel(
-            title=info_title if info_title else TR.words__title_information,
-            items=info_items,
-        )
-    )
-    await raise_if_not_confirmed(with_info(total_layout, info_layout, br_type, br_code))
 
 
 if not utils.BITCOIN_ONLY:
@@ -1046,20 +1032,14 @@ if not utils.BITCOIN_ONLY:
 
 
 async def confirm_joint_total(spending_amount: str, total_amount: str) -> None:
-    await raise_if_not_confirmed(
-        interact(
-            RustLayout(
-                trezorui2.confirm_total(
-                    title=TR.send__title_joint_transaction,
-                    items=[
-                        (TR.send__you_are_contributing, spending_amount),
-                        (TR.send__to_the_total_amount, total_amount),
-                    ],
-                )
-            ),
-            "confirm_joint_total",
-            ButtonRequestType.SignTx,
-        )
+    await confirm_summary(
+        items=[
+            (TR.send__you_are_contributing, spending_amount),
+            (TR.send__to_the_total_amount, total_amount),
+        ],
+        title=TR.send__title_joint_transaction,
+        br_type="confirm_joint_total",
+        br_code=ButtonRequestType.SignTx,
     )
 
 
diff --git a/core/src/trezor/ui/layouts/tr/__init__.py b/core/src/trezor/ui/layouts/tr/__init__.py
index c3de1166d1..8101160d52 100644
--- a/core/src/trezor/ui/layouts/tr/__init__.py
+++ b/core/src/trezor/ui/layouts/tr/__init__.py
@@ -734,6 +734,8 @@ async def confirm_output(
     address_label: str | None = None,
     output_index: int | None = None,
     chunkify: bool = False,
+    source_account: str | None = None,  # ignored on safe 3
+    source_account_path: str | None = None,  # ignored on safe 3
 ) -> None:
     title = title or TR.send__confirm_sending  # def_arg
     address_title = TR.words__recipient
@@ -1096,11 +1098,12 @@ def confirm_total(
     title: str | None = None,
     total_label: str | None = None,
     fee_label: str | None = None,
-    account_label: str | None = None,
+    source_account: str | None = None,
+    source_account_path: str | None = None,
     br_type: str = "confirm_total",
     br_code: ButtonRequestType = ButtonRequestType.SignTx,
 ) -> Awaitable[None]:
-    total_label = total_label or TR.send__total_amount  # def_arg
+    total_label = total_label or TR.send__total_amount_colon  # def_arg
     fee_label = fee_label or TR.send__including_fee  # def_arg
     return raise_if_not_confirmed(
         interact(
@@ -1110,7 +1113,7 @@ def confirm_total(
                     total_amount=total_amount,  # type: ignore [No parameter named]
                     fee_amount=fee_amount,  # type: ignore [No parameter named]
                     fee_rate_amount=fee_rate_amount,  # type: ignore [No parameter named]
-                    account_label=account_label,  # type: ignore [No parameter named]
+                    account_label=source_account,  # type: ignore [No parameter named]
                     total_label=total_label,  # type: ignore [No parameter named]
                     fee_label=fee_label,  # type: ignore [No parameter named]
                 )
diff --git a/core/src/trezor/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py
index 0735cffcd9..aa954e13c9 100644
--- a/core/src/trezor/ui/layouts/tt/__init__.py
+++ b/core/src/trezor/ui/layouts/tt/__init__.py
@@ -641,6 +641,8 @@ async def confirm_output(
     address_label: str | None = None,
     output_index: int | None = None,
     chunkify: bool = False,
+    source_account: str | None = None,  # ignored on model t
+    source_account_path: str | None = None,  # ignored on model t
 ) -> None:
     if title is not None:
         # TODO: handle translation:
@@ -978,13 +980,14 @@ def confirm_total(
     title: str | None = None,
     total_label: str | None = None,
     fee_label: str | None = None,
-    account_label: str | None = None,
+    source_account: str | None = None,
+    source_account_path: str | None = None,
     fee_rate_amount: str | None = None,
     br_type: str = "confirm_total",
     br_code: ButtonRequestType = ButtonRequestType.SignTx,
 ) -> Awaitable[None]:
     title = title or TR.words__title_summary  # def_arg
-    total_label = total_label or TR.send__total_amount  # def_arg
+    total_label = total_label or TR.send__total_amount_colon  # def_arg
     fee_label = fee_label or TR.send__including_fee  # def_arg
 
     items = [
@@ -992,10 +995,10 @@ def confirm_total(
         (fee_label, fee_amount),
     ]
     info_items = []
-    if account_label:
-        info_items.append((TR.confirm_total__sending_from_account, account_label))
+    if source_account:
+        info_items.append((TR.confirm_total__sending_from_account, source_account))
     if fee_rate_amount:
-        info_items.append((TR.confirm_total__fee_rate, fee_rate_amount))
+        info_items.append((TR.confirm_total__fee_rate_colon, fee_rate_amount))
 
     return confirm_summary(
         items,
diff --git a/core/tests/test_apps.bitcoin.approver.py b/core/tests/test_apps.bitcoin.approver.py
index fbbee64d6b..41a2a98e33 100644
--- a/core/tests/test_apps.bitcoin.approver.py
+++ b/core/tests/test_apps.bitcoin.approver.py
@@ -175,6 +175,7 @@ class TestApprover(unittest.TestCase):
         authorization = CoinJoinAuthorization(self.msg_auth)
         approver = CoinJoinApprover(tx, self.coin, authorization)
         signer = Bitcoin(tx, None, self.coin, approver)
+        tx_info = TxInfo(signer, tx)
 
         for txi in inputs:
             if txi.script_type == InputScriptType.EXTERNAL:
@@ -186,9 +187,9 @@ class TestApprover(unittest.TestCase):
             if txo.address_n:
                 await_result(approver.add_change_output(txo, script_pubkey=bytes(22)))
             else:
-                await_result(approver.add_external_output(txo, script_pubkey=bytes(22)))
+                await_result(approver.add_external_output(txo, script_pubkey=bytes(22), tx_info=tx_info))
 
-        await_result(approver.approve_tx(TxInfo(signer, tx), [], None))
+        await_result(approver.approve_tx(tx_info, [], None))
 
     def test_coinjoin_input_account_depth_mismatch(self):
         txi = TxInput(
diff --git a/core/tests/test_apps.bitcoin.segwit.signtx.native_p2wpkh.py b/core/tests/test_apps.bitcoin.segwit.signtx.native_p2wpkh.py
index cd58acee78..c7f0e42cd6 100644
--- a/core/tests/test_apps.bitcoin.segwit.signtx.native_p2wpkh.py
+++ b/core/tests/test_apps.bitcoin.segwit.signtx.native_p2wpkh.py
@@ -112,7 +112,7 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(49), H_(1), H_(0)]),
             True,
             TxRequest(
                 request_type=TXOUTPUT,
@@ -120,7 +120,7 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out2)),
-            helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1, False),
+            helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1, False, [H_(49), H_(1), H_(0)]),
             True,
             helpers.UiConfirmTotal(
                 12300000, 11000, fee_rate, coin, AmountUnit.BITCOIN, inp1.address_n[:3]
@@ -309,7 +309,7 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(49), H_(1), H_(0)]),
             True,
             TxRequest(
                 request_type=TXOUTPUT,
diff --git a/core/tests/test_apps.bitcoin.segwit.signtx.native_p2wpkh_grs.py b/core/tests/test_apps.bitcoin.segwit.signtx.native_p2wpkh_grs.py
index 0294a41f59..6860dd7977 100644
--- a/core/tests/test_apps.bitcoin.segwit.signtx.native_p2wpkh_grs.py
+++ b/core/tests/test_apps.bitcoin.segwit.signtx.native_p2wpkh_grs.py
@@ -123,7 +123,7 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(84), H_(1), H_(0)]),
             True,
             TxRequest(
                 request_type=TXOUTPUT,
@@ -131,7 +131,7 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out2)),
-            helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1, False),
+            helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1, False, [H_(84), H_(1), H_(0)]),
             True,
             helpers.UiConfirmNonDefaultLocktime(tx.lock_time, lock_time_disabled=False),
             True,
@@ -332,7 +332,7 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(84), H_(1), H_(0)]),
             True,
             TxRequest(
                 request_type=TXOUTPUT,
diff --git a/core/tests/test_apps.bitcoin.segwit.signtx.p2wpkh_in_p2sh.py b/core/tests/test_apps.bitcoin.segwit.signtx.p2wpkh_in_p2sh.py
index 228f4a8011..8e0f592871 100644
--- a/core/tests/test_apps.bitcoin.segwit.signtx.p2wpkh_in_p2sh.py
+++ b/core/tests/test_apps.bitcoin.segwit.signtx.p2wpkh_in_p2sh.py
@@ -114,7 +114,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(49), H_(1), H_(0)]),
             True,
             TxRequest(
                 request_type=TXOUTPUT,
@@ -122,7 +122,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out2)),
-            helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1, False),
+            helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1, False, [H_(49), H_(1), H_(0)]),
             True,
             helpers.UiConfirmTotal(
                 123445789 + 11000,
@@ -317,7 +317,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(49), H_(1), H_(0)]),
             True,
             TxRequest(
                 request_type=TXOUTPUT,
@@ -531,7 +531,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(49), H_(1), H_(0)]),
             True,
             TxRequest(
                 request_type=TXOUTPUT,
diff --git a/core/tests/test_apps.bitcoin.segwit.signtx.p2wpkh_in_p2sh_grs.py b/core/tests/test_apps.bitcoin.segwit.signtx.p2wpkh_in_p2sh_grs.py
index 7e45cf8a94..0abf34cacb 100644
--- a/core/tests/test_apps.bitcoin.segwit.signtx.p2wpkh_in_p2sh_grs.py
+++ b/core/tests/test_apps.bitcoin.segwit.signtx.p2wpkh_in_p2sh_grs.py
@@ -123,7 +123,7 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(49), H_(1), H_(0)]),
             True,
             TxRequest(
                 request_type=TXOUTPUT,
@@ -131,7 +131,7 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out2)),
-            helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1, False),
+            helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1, False, [H_(49), H_(1), H_(0)]),
             True,
             helpers.UiConfirmNonDefaultLocktime(tx.lock_time, lock_time_disabled=False),
             True,
@@ -336,7 +336,7 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(49), H_(1), H_(0)]),
             True,
             TxRequest(
                 request_type=TXOUTPUT,
diff --git a/core/tests/test_apps.bitcoin.signtx.fee_threshold.py b/core/tests/test_apps.bitcoin.signtx.fee_threshold.py
index e5e0320bb4..9aebc7b07a 100644
--- a/core/tests/test_apps.bitcoin.signtx.fee_threshold.py
+++ b/core/tests/test_apps.bitcoin.signtx.fee_threshold.py
@@ -180,7 +180,7 @@ class TestSignTxFeeThreshold(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN, 0, False, None),
             True,
             helpers.UiConfirmMultipleAccounts(),
             True,
diff --git a/core/tests/test_apps.bitcoin.signtx.py b/core/tests/test_apps.bitcoin.signtx.py
index e9e094696b..1d8a0339a6 100644
--- a/core/tests/test_apps.bitcoin.signtx.py
+++ b/core/tests/test_apps.bitcoin.signtx.py
@@ -111,7 +111,7 @@ class TestSignTx(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN, 0, False, [H_(44), H_(0), H_(0)]),
             True,
             helpers.UiConfirmTotal(
                 3_801_747,
diff --git a/core/tests/test_apps.bitcoin.signtx_decred.py b/core/tests/test_apps.bitcoin.signtx_decred.py
index a8f4fc7e0d..490538e0b8 100644
--- a/core/tests/test_apps.bitcoin.signtx_decred.py
+++ b/core/tests/test_apps.bitcoin.signtx_decred.py
@@ -112,7 +112,7 @@ class TestSignTxDecred(unittest.TestCase):
                 ),
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin_decred, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin_decred, AmountUnit.BITCOIN, 0, False, [H_(44), H_(1), H_(0)]),
             True,
             helpers.UiConfirmTotal(
                 200_000_000,
diff --git a/core/tests/test_apps.bitcoin.signtx_grs.py b/core/tests/test_apps.bitcoin.signtx_grs.py
index 573e3017ff..8fd6e7cd0d 100644
--- a/core/tests/test_apps.bitcoin.signtx_grs.py
+++ b/core/tests/test_apps.bitcoin.signtx_grs.py
@@ -112,7 +112,7 @@ class TestSignTx_GRS(unittest.TestCase):
                 serialized=EMPTY_SERIALIZED,
             ),
             TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
-            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False),
+            helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0, False, [H_(44), H_(17), H_(0)]),
             True,
             helpers.UiConfirmTotal(
                 210016, 192, fee_rate, coin, AmountUnit.BITCOIN, inp1.address_n[:3]
diff --git a/core/tools/translations/rules.json b/core/tools/translations/rules.json
index 5893eebdaa..7b87a61fcd 100644
--- a/core/tools/translations/rules.json
+++ b/core/tools/translations/rules.json
@@ -219,7 +219,7 @@
   "coinjoin__title_do_not_disconnect": "title,2",
   "coinjoin__title_progress": "title,1",
   "coinjoin__waiting_for_others": "text,1",
-  "confirm_total__fee_rate": "text,1",
+  "confirm_total__fee_rate_colon": "text,1",
   "confirm_total__sending_from_account": "text,1",
   "confirm_total__title_fee": "title,1",
   "confirm_total__title_sending_from": "title,1",
@@ -259,7 +259,7 @@
   "eos__requirement": "text,1",
   "eos__sell_ram": "text,1",
   "eos__sender": "text,1",
-  "eos__sign_transaction": "text,1",
+  "send__sign_transaction": "text,1",
   "eos__threshold": "text,1",
   "eos__to": "text,1",
   "eos__transfer": "text,1",
@@ -654,7 +654,7 @@
   "send__title_sending_amount": "title,1",
   "send__title_sending_to": "title,1",
   "send__to_the_total_amount": "text,1",
-  "send__total_amount": "text,1",
+  "send__total_amount_colon": "text,1",
   "send__transaction_id": "text,1",
   "send__you_are_contributing": "text,1",
   "share_words__words_in_order": "text,2",
diff --git a/core/translations/cs.json b/core/translations/cs.json
index 5e0605513b..c2beae0e28 100644
--- a/core/translations/cs.json
+++ b/core/translations/cs.json
@@ -257,7 +257,8 @@
     "coinjoin__title_do_not_disconnect": "Neodpojujte trezor!",
     "coinjoin__title_progress": "Probíhá coinjoin",
     "coinjoin__waiting_for_others": "Čeká se na ostatní",
-    "confirm_total__fee_rate": "Výše poplatku:",
+    "confirm_total__fee_rate": "Výše poplatku",
+    "confirm_total__fee_rate_colon": "Výše poplatku:",
     "confirm_total__sending_from_account": "Odeslání z účtu:",
     "confirm_total__title_fee": "Info o poplatcích",
     "confirm_total__title_sending_from": "Odeslání z",
@@ -297,7 +298,7 @@
     "eos__requirement": "Požadavek:",
     "eos__sell_ram": "Prodat RAM",
     "eos__sender": "Odesílatel:",
-    "eos__sign_transaction": "Podepsat transakci",
+    "send__sign_transaction": "Podepsat transakci",
     "eos__threshold": "Počet částí zálohy pro obnovu:",
     "eos__to": "Komu:",
     "eos__transfer": "Převod:",
@@ -699,7 +700,8 @@
     "send__title_sending_amount": "Odesílání částky",
     "send__title_sending_to": "Odesílání",
     "send__to_the_total_amount": "Do celkové částky:",
-    "send__total_amount": "Celková částka:",
+    "send__total_amount": "Celková částka",
+    "send__total_amount_colon": "Celková částka:",
     "send__transaction_id": "ID transakce:",
     "send__you_are_contributing": "Přispíváte:",
     "share_words__words_in_order": " slova v pořadí.",
diff --git a/core/translations/de.json b/core/translations/de.json
index 6fca28d28f..683e5273c5 100644
--- a/core/translations/de.json
+++ b/core/translations/de.json
@@ -257,7 +257,8 @@
     "coinjoin__title_do_not_disconnect": "Trenne deinen trezor nicht!",
     "coinjoin__title_progress": "Coinjoin läuft",
     "coinjoin__waiting_for_others": "Auf andere warten",
-    "confirm_total__fee_rate": "Gebührensatz:",
+    "confirm_total__fee_rate": "Gebührensatz",
+    "confirm_total__fee_rate_colon": "Gebührensatz:",
     "confirm_total__sending_from_account": "Gesendet von Konto:",
     "confirm_total__title_fee": "Gebühren-info",
     "confirm_total__title_sending_from": "Gesendet von",
@@ -297,7 +298,7 @@
     "eos__requirement": "Anforderung:",
     "eos__sell_ram": "RAM verkaufen",
     "eos__sender": "Sender:",
-    "eos__sign_transaction": "Transaktion signieren",
+    "send__sign_transaction": "Transaktion signieren",
     "eos__threshold": "Schwelle:",
     "eos__to": "An:",
     "eos__transfer": "Überweisung:",
@@ -699,7 +700,8 @@
     "send__title_sending_amount": "Betrag senden",
     "send__title_sending_to": "Senden an",
     "send__to_the_total_amount": "Gesamtbetrag:",
-    "send__total_amount": "Gesamtbetrag:",
+    "send__total_amount": "Gesamtbetrag",
+    "send__total_amount_colon": "Gesamtbetrag:",
     "send__transaction_id": "Transaktions-ID:",
     "send__you_are_contributing": "Dein Anteil:",
     "share_words__words_in_order": " Wörter der Reihe nach notiert.",
diff --git a/core/translations/en.json b/core/translations/en.json
index adca071828..63c9f4b939 100644
--- a/core/translations/en.json
+++ b/core/translations/en.json
@@ -237,9 +237,10 @@
     "coinjoin__title_do_not_disconnect": "Do not disconnect your trezor!",
     "coinjoin__title_progress": "Coinjoin in progress",
     "coinjoin__waiting_for_others": "Waiting for others",
-    "confirm_total__fee_rate": "Fee rate:",
+    "confirm_total__fee_rate": "Fee rate",
+    "confirm_total__fee_rate_colon": "Fee rate:",
     "confirm_total__sending_from_account": "Sending from account:",
-    "confirm_total__title_fee": "Fee information",
+    "confirm_total__title_fee": "Fee info",
     "confirm_total__title_sending_from": "Sending from",
     "debug__loading_seed": "Loading seed",
     "debug__loading_seed_not_recommended": "Loading private seed is not recommended.",
@@ -277,7 +278,6 @@
     "eos__requirement": "Requirement:",
     "eos__sell_ram": "Sell RAM",
     "eos__sender": "Sender:",
-    "eos__sign_transaction": "Sign transaction",
     "eos__threshold": "Threshold:",
     "eos__to": "To:",
     "eos__transfer": "Transfer:",
@@ -365,9 +365,10 @@
     "inputs__show": "SHOW",
     "inputs__space": "SPACE",
     "instructions__continue_in_app": "Continue in the app",
+    "instructions__hold_to_confirm": "Hold to confirm",
+    "instructions__hold_to_sign": "Hold to sign",
     "instructions__swipe_up": "Swipe up",
     "instructions__tap_to_confirm": "Tap to confirm",
-    "instructions__hold_to_confirm": "Hold to confirm",
     "joint__title": "Joint transaction",
     "joint__to_the_total_amount": "To the total amount:",
     "joint__you_are_contributing": "You are contributing:",
@@ -677,11 +678,15 @@
     "sd_card__wanna_format": "Do you really want to format the SD card?",
     "sd_card__wrong_sd_card": "Wrong SD card.",
     "send__address_path": "address path",
+    "send__cancel_sign": "Cancel sign",
     "send__confirm_sending": "Sending amount",
     "send__from_multiple_accounts": "Sending from multiple accounts.",
+    "send__incl_transaction_fee": "incl. Transaction fee",
     "send__including_fee": "Including fee:",
     "send__maximum_fee": "Maximum fee:",
     "send__receiving_to_multisig": "Receiving to a multisig address.",
+    "send__send_from": "Send from",
+    "send__sign_transaction": "Sign transaction",
     "send__title_confirm_sending": "Confirm sending",
     "send__title_joint_transaction": "Joint transaction",
     "send__title_receiving_to": "Receiving to",
@@ -689,7 +694,8 @@
     "send__title_sending_amount": "Sending amount",
     "send__title_sending_to": "Sending to",
     "send__to_the_total_amount": "To the total amount:",
-    "send__total_amount": "Total amount:",
+    "send__total_amount": "Total amount",
+    "send__total_amount_colon": "Total amount:",
     "send__transaction_id": "Transaction ID:",
     "send__you_are_contributing": "You are contributing:",
     "share_words__words_in_order": " words in order.",
diff --git a/core/translations/es.json b/core/translations/es.json
index 4f57043244..fb42195c67 100644
--- a/core/translations/es.json
+++ b/core/translations/es.json
@@ -257,7 +257,8 @@
     "coinjoin__title_do_not_disconnect": "¡No desconectes el trezor!",
     "coinjoin__title_progress": "Coinjoin en curso",
     "coinjoin__waiting_for_others": "Esperando a los demás",
-    "confirm_total__fee_rate": "Comisión:",
+    "confirm_total__fee_rate": "Comisión",
+    "confirm_total__fee_rate_colon": "Comisión:",
     "confirm_total__sending_from_account": "Envío desde cuenta:",
     "confirm_total__title_fee": "Info. comisión",
     "confirm_total__title_sending_from": "Envío desde",
@@ -297,7 +298,7 @@
     "eos__requirement": "Requisito:",
     "eos__sell_ram": "Vender RAM",
     "eos__sender": "Remitente:",
-    "eos__sign_transaction": "Firmar transacción",
+    "send__sign_transaction": "Firmar transacción",
     "eos__threshold": "Umbral:",
     "eos__to": "Para:",
     "eos__transfer": "Transferencia:",
@@ -699,7 +700,8 @@
     "send__title_sending_amount": "Importe envío",
     "send__title_sending_to": "Envío a",
     "send__to_the_total_amount": "Al importe total:",
-    "send__total_amount": "Importe total:",
+    "send__total_amount": "Importe total",
+    "send__total_amount_colon": "Importe total:",
     "send__transaction_id": "ID de la transacción:",
     "send__you_are_contributing": "Estás aportando:",
     "share_words__words_in_order": " palabras en orden.",
diff --git a/core/translations/fr.json b/core/translations/fr.json
index 2a33588dfc..8ce8d483e5 100644
--- a/core/translations/fr.json
+++ b/core/translations/fr.json
@@ -257,7 +257,8 @@
     "coinjoin__title_do_not_disconnect": "Ne déconnectez pas votre trezor !",
     "coinjoin__title_progress": "Coinjoin en cours",
     "coinjoin__waiting_for_others": "En attente des autres",
-    "confirm_total__fee_rate": "Taux des frais :",
+    "confirm_total__fee_rate": "Taux des frais",
+    "confirm_total__fee_rate_colon": "Taux des frais :",
     "confirm_total__sending_from_account": "Compte d'envoi :",
     "confirm_total__title_fee": "Infos sur les frais",
     "confirm_total__title_sending_from": "Envoi depuis",
@@ -297,7 +298,7 @@
     "eos__requirement": "Exigence :",
     "eos__sell_ram": "Vendre de la RAM",
     "eos__sender": "Expéditeur :",
-    "eos__sign_transaction": "Signer la transaction",
+    "send__sign_transaction": "Signer la transaction",
     "eos__threshold": "Seuil :",
     "eos__to": "À :",
     "eos__transfer": "Transfert :",
@@ -699,7 +700,8 @@
     "send__title_sending_amount": "Montant de l'envoi",
     "send__title_sending_to": "Envoi à",
     "send__to_the_total_amount": "Au montant total :",
-    "send__total_amount": "Montant total :",
+    "send__total_amount": "Montant total",
+    "send__total_amount_colon": "Montant total :",
     "send__transaction_id": "ID de transaction :",
     "send__you_are_contributing": "Votre contribution :",
     "share_words__words_in_order": " mots dans l'ordre.",
diff --git a/core/translations/order.json b/core/translations/order.json
index 6d15f658a3..c24bf027a4 100644
--- a/core/translations/order.json
+++ b/core/translations/order.json
@@ -219,7 +219,7 @@
   "217": "coinjoin__title_do_not_disconnect",
   "218": "coinjoin__title_progress",
   "219": "coinjoin__waiting_for_others",
-  "220": "confirm_total__fee_rate",
+  "220": "confirm_total__fee_rate_colon",
   "221": "confirm_total__sending_from_account",
   "222": "confirm_total__title_fee",
   "223": "confirm_total__title_sending_from",
@@ -259,7 +259,7 @@
   "257": "eos__requirement",
   "258": "eos__sell_ram",
   "259": "eos__sender",
-  "260": "eos__sign_transaction",
+  "260": "send__sign_transaction",
   "261": "eos__threshold",
   "262": "eos__to",
   "263": "eos__transfer",
@@ -652,7 +652,7 @@
   "650": "send__title_sending_amount",
   "651": "send__title_sending_to",
   "652": "send__to_the_total_amount",
-  "653": "send__total_amount",
+  "653": "send__total_amount_colon",
   "654": "send__transaction_id",
   "655": "send__you_are_contributing",
   "656": "share_words__words_in_order",
@@ -871,5 +871,11 @@
   "869": "address__confirmed",
   "870": "pin__cancel_description",
   "871": "pin__cancel_info",
-  "872": "pin__cancel_setup"
+  "872": "pin__cancel_setup",
+  "873": "send__cancel_sign",
+  "874": "send__send_from",
+  "875": "instructions__hold_to_sign",
+  "876": "confirm_total__fee_rate",
+  "877": "send__incl_transaction_fee",
+  "878": "send__total_amount"
 }
diff --git a/core/translations/signatures.json b/core/translations/signatures.json
index 2e93c3afb8..626bf5fa71 100644
--- a/core/translations/signatures.json
+++ b/core/translations/signatures.json
@@ -1,8 +1,8 @@
 {
   "current": {
-    "merkle_root": "928438526b993d433d52359d86099848d570c13fbe6aac72a2f5a29a4e8e94c5",
-    "datetime": "2024-05-17T10:55:04.124405",
-    "commit": "1409ed27df07827a2a3e3756420db1b41fe108e5"
+    "merkle_root": "329b06dbf2564bf17ba46d2b3304f91df15abc42794763a55ea33bc04281ac42",
+    "datetime": "2024-05-20T15:37:23.831427",
+    "commit": "2a5dc6f8d54701e86c32451fb154d3e40a778ca9"
   },
   "history": [
     {