diff --git a/app/javascript/fonts/inter/inter-variable-font-slnt-wght.woff2 b/app/javascript/fonts/inter/inter-variable-font-slnt-wght.woff2
new file mode 100644
index 000000000..e6345f2e3
Binary files /dev/null and b/app/javascript/fonts/inter/inter-variable-font-slnt-wght.woff2 differ
diff --git a/app/javascript/images/mailer-new/common/header-bg-end.png b/app/javascript/images/mailer-new/common/header-bg-end.png
new file mode 100644
index 000000000..900196678
Binary files /dev/null and b/app/javascript/images/mailer-new/common/header-bg-end.png differ
diff --git a/app/javascript/images/mailer-new/common/header-bg-start.png b/app/javascript/images/mailer-new/common/header-bg-start.png
new file mode 100644
index 000000000..0037c1ad9
Binary files /dev/null and b/app/javascript/images/mailer-new/common/header-bg-start.png differ
diff --git a/app/javascript/images/mailer-new/common/logo-footer.png b/app/javascript/images/mailer-new/common/logo-footer.png
new file mode 100644
index 000000000..2baafd8d7
Binary files /dev/null and b/app/javascript/images/mailer-new/common/logo-footer.png differ
diff --git a/app/javascript/images/mailer-new/common/logo-header.png b/app/javascript/images/mailer-new/common/logo-header.png
new file mode 100644
index 000000000..46a6bddaa
Binary files /dev/null and b/app/javascript/images/mailer-new/common/logo-header.png differ
diff --git a/app/javascript/images/mailer-new/heading/2fa-disabled.png b/app/javascript/images/mailer-new/heading/2fa-disabled.png
new file mode 100644
index 000000000..b1e342a87
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/2fa-disabled.png differ
diff --git a/app/javascript/images/mailer-new/heading/2fa-enabled.png b/app/javascript/images/mailer-new/heading/2fa-enabled.png
new file mode 100644
index 000000000..3ce3e04f8
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/2fa-enabled.png differ
diff --git a/app/javascript/images/mailer-new/heading/2fa-recovery.png b/app/javascript/images/mailer-new/heading/2fa-recovery.png
new file mode 100644
index 000000000..cefb21e1e
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/2fa-recovery.png differ
diff --git a/app/javascript/images/mailer-new/heading/appeal-approved.png b/app/javascript/images/mailer-new/heading/appeal-approved.png
new file mode 100755
index 000000000..b2476ec34
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/appeal-approved.png differ
diff --git a/app/javascript/images/mailer-new/heading/appeal-rejected.png b/app/javascript/images/mailer-new/heading/appeal-rejected.png
new file mode 100644
index 000000000..7ae38ad0c
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/appeal-rejected.png differ
diff --git a/app/javascript/images/mailer-new/heading/archive.png b/app/javascript/images/mailer-new/heading/archive.png
new file mode 100644
index 000000000..b0c7fad84
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/archive.png differ
diff --git a/app/javascript/images/mailer-new/heading/boost.png b/app/javascript/images/mailer-new/heading/boost.png
new file mode 100644
index 000000000..e33b75997
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/boost.png differ
diff --git a/app/javascript/images/mailer-new/heading/email.png b/app/javascript/images/mailer-new/heading/email.png
new file mode 100644
index 000000000..c922c5239
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/email.png differ
diff --git a/app/javascript/images/mailer-new/heading/favorite.png b/app/javascript/images/mailer-new/heading/favorite.png
new file mode 100644
index 000000000..0e483ee9b
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/favorite.png differ
diff --git a/app/javascript/images/mailer-new/heading/follow.png b/app/javascript/images/mailer-new/heading/follow.png
new file mode 100644
index 000000000..ff5b7e004
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/follow.png differ
diff --git a/app/javascript/images/mailer-new/heading/key-added.png b/app/javascript/images/mailer-new/heading/key-added.png
new file mode 100755
index 000000000..82dcd464b
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/key-added.png differ
diff --git a/app/javascript/images/mailer-new/heading/key-deleted.png b/app/javascript/images/mailer-new/heading/key-deleted.png
new file mode 100755
index 000000000..2930f591a
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/key-deleted.png differ
diff --git a/app/javascript/images/mailer-new/heading/key-disabled.png b/app/javascript/images/mailer-new/heading/key-disabled.png
new file mode 100755
index 000000000..e0f259359
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/key-disabled.png differ
diff --git a/app/javascript/images/mailer-new/heading/key-enabled.png b/app/javascript/images/mailer-new/heading/key-enabled.png
new file mode 100644
index 000000000..b2476ec34
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/key-enabled.png differ
diff --git a/app/javascript/images/mailer-new/heading/login.png b/app/javascript/images/mailer-new/heading/login.png
new file mode 100644
index 000000000..89a6e9ee3
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/login.png differ
diff --git a/app/javascript/images/mailer-new/heading/mention.png b/app/javascript/images/mailer-new/heading/mention.png
new file mode 100644
index 000000000..c4dccff8e
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/mention.png differ
diff --git a/app/javascript/images/mailer-new/heading/password.png b/app/javascript/images/mailer-new/heading/password.png
new file mode 100755
index 000000000..552c7c068
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/password.png differ
diff --git a/app/javascript/images/mailer-new/heading/user.png b/app/javascript/images/mailer-new/heading/user.png
new file mode 100644
index 000000000..f1dd58a18
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/user.png differ
diff --git a/app/javascript/images/mailer-new/heading/warning.png b/app/javascript/images/mailer-new/heading/warning.png
new file mode 100755
index 000000000..7764837ab
Binary files /dev/null and b/app/javascript/images/mailer-new/heading/warning.png differ
diff --git a/app/javascript/images/mailer-new/welcome/checkbox-off.png b/app/javascript/images/mailer-new/welcome/checkbox-off.png
new file mode 100644
index 000000000..51c190efe
Binary files /dev/null and b/app/javascript/images/mailer-new/welcome/checkbox-off.png differ
diff --git a/app/javascript/images/mailer-new/welcome/checkbox-on.png b/app/javascript/images/mailer-new/welcome/checkbox-on.png
new file mode 100644
index 000000000..162095e7d
Binary files /dev/null and b/app/javascript/images/mailer-new/welcome/checkbox-on.png differ
diff --git a/app/javascript/images/mailer-new/welcome/step1-on.png b/app/javascript/images/mailer-new/welcome/step1-on.png
new file mode 100644
index 000000000..c3776d17d
Binary files /dev/null and b/app/javascript/images/mailer-new/welcome/step1-on.png differ
diff --git a/app/javascript/images/mailer-new/welcome/step2-off.png b/app/javascript/images/mailer-new/welcome/step2-off.png
new file mode 100755
index 000000000..a262454d2
Binary files /dev/null and b/app/javascript/images/mailer-new/welcome/step2-off.png differ
diff --git a/app/javascript/images/mailer-new/welcome/step3-off.png b/app/javascript/images/mailer-new/welcome/step3-off.png
new file mode 100755
index 000000000..972de65a5
Binary files /dev/null and b/app/javascript/images/mailer-new/welcome/step3-off.png differ
diff --git a/app/javascript/images/mailer-new/welcome/step4-off.png b/app/javascript/images/mailer-new/welcome/step4-off.png
new file mode 100755
index 000000000..f45e9a2c9
Binary files /dev/null and b/app/javascript/images/mailer-new/welcome/step4-off.png differ
diff --git a/app/javascript/images/mailer-new/welcome/step5-off.png b/app/javascript/images/mailer-new/welcome/step5-off.png
new file mode 100755
index 000000000..ca270f547
Binary files /dev/null and b/app/javascript/images/mailer-new/welcome/step5-off.png differ
diff --git a/app/javascript/styles/fonts/inter.scss b/app/javascript/styles/fonts/inter.scss
new file mode 100644
index 000000000..bb4899b70
--- /dev/null
+++ b/app/javascript/styles/fonts/inter.scss
@@ -0,0 +1,8 @@
+@font-face {
+  font-family: Inter;
+  src: url('../fonts/inter/inter-variable-font-slnt-wght.woff2')
+    format('woff2-variations');
+  font-weight: 100 900;
+  font-style: normal;
+  mso-generic-font-family: swiss; /* stylelint-disable-line property-no-unknown -- Proprietary property for Outlook on Windows. */
+}
diff --git a/app/javascript/styles/mailer.scss b/app/javascript/styles/mailer.scss
index 92d00cae8..6d0168969 100644
--- a/app/javascript/styles/mailer.scss
+++ b/app/javascript/styles/mailer.scss
@@ -1,574 +1,534 @@
-@import 'mastodon/variables';
-@import 'fonts/roboto';
+@import 'fonts/inter';
 
-table,
-td,
-div {
-  box-sizing: border-box;
-}
-
-html,
 body {
-  width: 100% !important;
-  min-width: 100%;
+  accent-color: #6364ff;
+  word-break: break-word;
   margin: 0;
+  background-color: #f3f2f5;
   padding: 0;
-  -webkit-text-size-adjust: 100%;
-  -ms-text-size-adjust: 100%;
-}
-
-.email-body {
-  td,
-  div,
-  a,
-  span {
-    line-height: inherit;
-  }
-}
-
-a {
-  &,
-  &:visited,
-  span {
-    text-decoration: none;
-    color: $ui-highlight-color;
-  }
-
-  #outlook & {
-    padding: 0;
-  }
-}
-
-img {
-  outline: none;
-  border: 0;
-  text-decoration: none;
-  -ms-interpolation-mode: bicubic;
-  clear: both;
-  line-height: 100%;
-}
-
-table {
-  border-spacing: 0;
-  mso-table-lspace: 0;
-  mso-table-rspace: 0;
-}
-
-td {
-  vertical-align: top;
-}
-
-.auto-dir {
-  p {
-    unicode-bidi: plaintext;
-  }
-
-  a {
-    unicode-bidi: isolate;
-  }
-}
-
-.email-table,
-.content-section,
-.column,
-.column-cell {
-  width: 100%;
-  min-width: 100%;
-}
-
-.email-body {
-  font-size: 0 !important;
-  line-height: 100%;
-  text-align: center;
-  padding-left: 16px;
-  padding-right: 16px;
-}
-
-.email-start {
-  padding-top: 32px;
-}
-
-.email-end {
-  padding-bottom: 32px;
-}
-
-.email-body,
-html,
-body {
-  background-color: lighten($ui-base-color, 4%);
-}
-
-.email-container,
-.email-row,
-.col-0,
-.col-1,
-.col-2,
-.col-3,
-.col-4,
-.col-5,
-.col-6 {
-  font-size: 0;
-  display: inline-block;
-  width: 100%;
-  min-width: 100%;
-  min-width: 0 !important;
-  vertical-align: top;
-}
-
-.content-cell {
-  width: 100%;
-  min-width: 100%;
-  min-width: 0 !important;
-}
-
-.column-cell {
-  padding-top: 16px;
-  padding-bottom: 16px;
-  vertical-align: top;
-
-  &.button-cell {
-    padding-top: 0;
-  }
-}
-
-.email-container {
-  max-width: 632px;
-  margin: 0 auto;
-  text-align: center;
-}
-
-.email-row {
-  display: block;
-  max-width: 600px !important;
-  margin: 0 auto;
-  text-align: center;
-  clear: both;
-}
-
-.col-0 {
-  max-width: 50px;
-}
-
-.col-1 {
-  max-width: 100px;
-}
-
-.col-2 {
-  max-width: 200px;
-}
-
-.col-3 {
-  max-width: 300px;
-}
-
-.col-4 {
-  max-width: 400px;
-}
-
-.col-5 {
-  max-width: 500px;
-}
-
-.col-6 {
-  max-width: 600px;
-}
-
-.column-cell,
-.column-cell td,
-p {
-  font-family: Helvetica, Arial, sans-serif;
-
-  @media only screen {
-    font-family: $font-sans-serif, sans-serif !important;
-  }
-}
-
-.email-body .column-cell,
-.column-cell,
-p {
-  font-size: 15px;
-  line-height: 23px;
-  color: $ui-primary-color;
-  mso-line-height-rule: exactly;
-  text-rendering: optimizelegibility;
-}
-
-p {
-  display: block;
-  margin-top: 0;
-  margin-bottom: 16px;
-
-  &.small {
-    font-size: 13px;
-  }
-
-  &.lead {
-    font-size: 19px;
-    line-height: 27px;
-  }
+  -webkit-text-size-adjust: none;
+  text-size-adjust: none;
 }
 
+p,
 h1,
 h2,
 h3,
 h4,
 h5,
 h6 {
-  color: $ui-secondary-color;
-  margin-left: 0;
-  margin-right: 0;
-  margin-top: 20px;
-  margin-bottom: 8px;
+  margin: 0;
+  background-color: transparent;
   padding: 0;
-  font-weight: 500;
+  border: none;
+  font-family: Inter, 'Lucida Grande', sans-serif;
 }
 
-h1 {
-  font-size: 26px;
-  line-height: 36px;
+img {
+  max-width: 100%;
+  height: auto;
+  border: none;
+  text-indent: 0;
+  vertical-align: middle;
+  color: inherit;
+  font-family: inherit;
 }
 
-h2 {
-  font-size: 23px;
-  line-height: 30px;
+table {
+  border: none;
 }
 
-h3 {
-  font-size: 19px;
-  line-height: 25px;
+table + p {
+  margin-top: 16px;
 }
 
-h5 {
-  font-size: 16px;
-  line-height: 21px;
-  font-weight: 700;
-  color: lighten($ui-base-color, 34%);
+.email {
+  min-width: 280px;
+  font-family: Inter, 'Lucida Grande', sans-serif;
+  word-break: break-word;
+  color: #17063b;
+  background-color: #f3f2f5;
 }
 
-.input-cell {
-  h5 {
-    margin-top: 4px;
-  }
-}
-
-.input {
-  td {
-    background: darken($ui-base-color, 8%);
-    border-radius: 4px;
-    padding: 16px;
-    line-height: 20px;
-    mso-line-height-rule: exactly;
-    text-align: center;
-    font-weight: 500;
-    font-size: 17px;
-  }
-}
-
-.content-cell,
-.blank-cell {
+.email-container {
+  max-width: 740px;
+  margin: 0 auto;
   width: 100%;
-  font-size: 0;
-  text-align: center;
-  vertical-align: top;
-  padding-left: 16px;
-  padding-right: 16px;
 }
 
-.content-cell {
-  background-color: darken($ui-base-color, 4%);
-
-  &.darker {
-    background-color: darken($ui-base-color, 8%);
-  }
+// Outer email card
+.email-card-table {
+  border-collapse: collapse;
+  width: 100%;
 }
 
-.hero {
-  background-color: $ui-base-color;
-  padding-top: 20px;
+.email-card-td {
+  overflow: hidden;
+  box-shadow: 0 4px 16px 0 rgba(23, 6, 59, 4%);
+  background-color: #fff;
 }
 
-.hero-with-button {
-  padding-bottom: 16px;
-
-  h1 {
-    margin-bottom: 4px;
-  }
-
-  p.lead {
-    margin-bottom: 32px;
-  }
+// Inner email card
+.email-inner-card-table {
+  border-collapse: separate;
+  width: 100%;
+  border-radius: 12px;
 }
 
-.header {
-  border-radius: 5px 5px 0 0;
-  background-color: darken($ui-base-color, 8%);
-
-  .column-cell {
-    text-align: center;
-    padding-top: 20px;
-    padding-bottom: 8px;
-  }
+.email-inner-card-td-without-padding,
+.email-inner-card-td {
+  border-radius: 12px;
+  overflow: hidden;
+  box-shadow: 0 4px 16px 0 rgba(23, 6, 59, 8%);
+  background-color: #fff;
+  border: 1px solid #dfdee3;
 }
 
-.content-start {
-  padding-top: 32px;
+.email-inner-card-td {
+  padding: 24px;
 }
 
-.content-end {
-  border-radius: 0 0 5px 5px;
-  padding-top: 16px;
+// Utility classes
+.email-w-full {
+  width: 100%;
 }
 
-.footer {
-  .column-cell,
+.email-prose {
   p {
-    color: lighten($ui-base-color, 34%);
-  }
-
-  p {
-    margin-bottom: 0;
-    font-size: 13px;
-
-    &.small {
-      margin-bottom: 0;
-    }
-  }
-
-  a {
-    color: lighten($ui-base-color, 34%);
-    text-decoration: underline;
-  }
-
-  img {
-    opacity: 0.3;
-  }
-}
-
-.logo {
-  position: relative;
-  left: -4px;
-}
-
-.button {
-  display: table;
-  margin-left: auto;
-  margin-right: auto;
-
-  td {
+    color: #17063b;
+    font-size: 14px;
     line-height: 20px;
-    mso-line-height-rule: exactly;
-    border-radius: 4px;
-    text-align: center;
-    font-weight: 500;
-    font-size: 17px;
-    padding: 0 !important;
 
-    a,
-    a span {
-      color: $primary-text-color;
-      display: block !important;
-      text-align: center !important;
-      vertical-align: top !important;
-      line-height: inherit !important;
+    &:not(:last-child) {
+      margin-bottom: 16px;
     }
 
-    a {
-      padding: 10px 22px !important;
-      line-height: 26px !important;
-      font-weight: 500 !important;
-    }
-  }
+    a:not([class]) {
+      color: #6364ff;
+      text-decoration: none;
 
-  &.button-small {
-    td {
-      border-radius: 4px;
-      font-size: 14px;
-      padding: 8px 16px;
-
-      a {
-        padding: 5px 16px !important;
-        line-height: 26px !important;
+      &:hover {
+        color: #563acc !important;
       }
     }
   }
 }
 
-.button-default {
-  background-color: darken($ui-base-color, 8%);
+.email-padding-24 {
+  padding: 24px;
 }
 
-.button-primary {
-  background-color: darken($ui-highlight-color, 3%);
+.email-padding-top-24 {
+  padding-top: 24px;
 }
 
-.text-center {
-  text-align: center;
+.email-border-top {
+  border-top: 1px solid #dfdee3;
 }
 
-.text-right {
+.email-border-bottom {
+  border-bottom: 1px solid #dfdee3;
+}
+
+// Header
+.email-header-td {
+  padding: 16px 32px;
+  background-color: #1b001f;
+  background-image: url('../images/mailer-new/common/header-bg-start.png');
+  background-position: left top;
+  background-repeat: repeat;
+}
+
+.email-header-logo-table {
+  width: auto;
+  margin: 0;
+}
+
+.email-header-logo-td {
+  padding: 16px 0;
+  font-size: 0;
+
+  img {
+    color: #fff;
+    font-size: 16px;
+    font-weight: bold;
+    max-height: 40px;
+  }
+}
+
+.email-header-logo-a {
+  display: inline-block;
+
+  img {
+    display: inline-block;
+    color: #fff;
+  }
+}
+
+.email-header-logo-div {
+  max-height: 0;
+}
+
+.email-header-logo-p {
+  word-break: break-all;
+  padding-left: 40px;
+  padding-top: 26px;
+  font-size: 11px;
+  line-height: 13px;
+  color: #8d808f;
+  text-align: left;
+}
+
+.email-header-logo-span {
+  display: block;
   text-align: right;
 }
 
-.padded {
-  padding-left: 16px;
-  padding-right: 16px;
+.email-header-heading-td {
+  padding: 16px 0;
 }
 
-.padded-bottom {
-  padding-bottom: 32px;
-}
-
-.margin-bottom {
-  margin-bottom: 20px;
-}
-
-.hero-icon {
-  width: 64px;
-
-  td {
-    text-align: center;
-    vertical-align: middle;
-    line-height: 100%;
-    mso-line-height-rule: exactly;
-    padding: 16px;
-    border-radius: 80px;
-    background: $success-green;
-  }
-
-  &.warning-icon td {
-    background: $gold-star;
-  }
-
-  &.alert-icon td {
-    background: $error-red;
-  }
+.email-header-heading-img-td {
+  width: 56px;
+  text-align: left;
+  vertical-align: top;
 
   img {
-    max-width: 32px;
-    width: 32px;
-    height: 32px;
-    display: block;
-    line-height: 100%;
+    width: 56px;
+    height: 56px;
+    border-radius: 12px;
   }
 }
 
-.hr {
-  width: 100%;
+.email-header-heading-txt-td {
+  vertical-align: middle;
+  padding-left: 16px;
+  padding-right: 16px;
 
-  td {
-    font-size: 0;
-    line-height: 1px;
-    mso-line-height-rule: exactly;
-    min-height: 1px;
-    overflow: hidden;
-    height: 2px;
-    background-color: transparent !important;
-    border-top: 1px solid lighten($ui-base-color, 8%);
-  }
-}
-
-.status {
-  padding-bottom: 32px;
-
-  &--highlighted {
-    border: 1px solid lighten($ui-base-color, 8%);
-    border-radius: 4px;
-    padding-bottom: 16px;
-    margin-bottom: 16px;
-  }
-
-  .status-header {
-    td {
-      font-size: 14px;
-      padding-bottom: 15px;
-    }
-
-    bdi {
-      color: $white;
-      font-size: 16px;
-      display: block;
-      font-weight: 500;
-    }
-
-    td:first-child {
-      padding-right: 10px;
-    }
-
-    img {
-      width: 48px;
-      height: 48px;
-      border-radius: 4px;
-    }
+  h1 {
+    margin-bottom: 5px;
+    color: #fff;
+    font-size: 24px;
+    line-height: 28px;
+    font-weight: 600;
   }
 
   p {
-    font-size: 19px;
-    margin-bottom: 20px;
+    color: #a399a5;
+    font-size: 18px;
+    line-height: 21.6px;
+    font-weight: 500;
+  }
 
-    &.status-footer {
-      color: lighten($ui-base-color, 26%);
-      font-size: 14px;
-      margin-bottom: 0;
+  &:only-child {
+    padding-left: 0;
+    padding-right: 0;
+  }
+}
 
-      a {
-        color: lighten($ui-base-color, 26%);
+// To make the design work with images off
+// we create an empty div that overlaps with
+// the rest of the content with a dark background.
+.email-header-after-div {
+  max-height: 0;
+}
+
+.email-header-after-inside-div {
+  height: 30px;
+  background-color: #1b001f;
+}
+
+// Body content
+.email-body-td {
+  background-image: url('../images/mailer-new/common/header-bg-end.png');
+  background-position: left top;
+  background-repeat: no-repeat;
+}
+
+.email-body-padding-td {
+  padding: 0 32px 32px;
+  mso-padding-alt: 32px;
+}
+
+.email-body-padding-td {
+  & > p {
+    font-size: 14px;
+    line-height: 20px;
+    color: #17063b;
+
+    a {
+      color: #6364ff;
+      text-decoration: none;
+
+      &:hover {
+        color: #563acc !important;
       }
     }
   }
 }
 
-.border-top {
-  border-top: 1px solid lighten($ui-base-color, 8%);
+// Footer
+.email-footer-td {
+  padding: 28px 32px 32px;
+  text-align: center;
 }
 
-ul {
-  padding-left: 15px;
-  margin-top: 0;
-  margin-bottom: 0;
-  padding-top: 16px;
+.email-footer-logo-a {
+  display: inline-block;
+}
 
-  li {
-    margin-bottom: 16px;
-    color: lighten($ui-base-color, 26%);
+.email-footer-p {
+  color: #9b94ab;
+  text-align: center;
+  font-size: 12px;
+  line-height: 20px;
 
-    span {
-      color: $ui-primary-color;
+  a {
+    color: #9b94ab;
+    text-decoration: underline;
+  }
+
+  &:first-child {
+    margin-bottom: 12px;
+  }
+}
+
+// Button
+.email-btn-table {
+  margin: 0;
+  max-width: 100%;
+  border-collapse: separate;
+  border-radius: 8px;
+  background-color: #6364ff;
+}
+
+.email-btn-td {
+  height: 40px;
+  text-align: center;
+  mso-padding-alt: 0 35px;
+}
+
+.email-btn-a {
+  display: block;
+  border-radius: 8px;
+  padding-left: 35px;
+  padding-right: 35px;
+  padding-top: 10px;
+  padding-bottom: 10px;
+  text-align: center;
+  font-family: Inter, 'Lucida Grande', sans-serif;
+  font-size: 14px;
+  font-weight: 600;
+  line-height: 20px;
+  color: #fff;
+  text-decoration: none;
+  transition: background-color 0.3s ease-in-out;
+}
+
+// Status
+.email-status-header-img {
+  vertical-align: top;
+  width: 48px;
+
+  img {
+    width: 48px;
+    height: 48px;
+    border-radius: 8px;
+    overflow: hidden;
+  }
+}
+
+.email-status-header-text {
+  padding-left: 16px;
+  padding-right: 16px;
+  vertical-align: middle;
+}
+
+.email-status-header-name {
+  font-size: 16px;
+  font-weight: 600;
+  line-height: 24px;
+  color: #17063b;
+}
+
+.email-status-header-handle {
+  font-size: 14px;
+  line-height: 20px;
+  color: #746a89;
+}
+
+.email-status-content {
+  padding-top: 24px;
+}
+
+.email-status-spoiler {
+  color: #746a89;
+  font-style: italic;
+  margin-bottom: 8px;
+}
+
+.email-status-prose {
+  p {
+    font-size: 14px;
+    line-height: 20px;
+    color: #17063b;
+  }
+
+  a {
+    color: #6364ff;
+    text-decoration: none;
+
+    &:hover {
+      color: #563acc !important;
     }
   }
 }
 
-ul.rules-list {
-  padding-top: 0;
-}
+.email-status-media {
+  margin-top: 16px;
+  font-size: 14px;
+  line-height: 20px;
+  color: #17063b;
 
-@media only screen and (device-width >= 768px) and (device-width <= 1024px) and (orientation: landscape) {
-  body {
-    min-height: 1024px !important;
+  img {
+    border-radius: 8px;
+  }
+
+  a {
+    color: #6364ff;
+    text-decoration: none;
+
+    &:hover {
+      color: #563acc !important;
+    }
   }
 }
 
-@media (width <= 697px) {
-  .email-container,
-  .col-1,
-  .col-2,
-  .col-3,
-  .col-4,
-  .col-5,
-  .col-6 {
-    width: 100% !important;
-    max-width: none !important;
+.email-status-footer {
+  margin-top: 16px;
+  font-size: 12px;
+  line-height: 16px;
+  color: #746a89;
+
+  a {
+    color: #746a89;
   }
 
-  .email-start {
-    padding-top: 16px !important;
-  }
-
-  .email-end {
-    padding-bottom: 16px !important;
-  }
-
-  .padded {
-    padding-left: 0 !important;
-    padding-right: 0 !important;
+  a:hover {
+    color: #746a89 !important;
+    text-decoration: underline !important;
+  }
+}
+
+// Purple frame for emphasis
+.email-frame-table {
+  background-color: #efefff;
+  border-radius: 8px;
+}
+
+.email-frame-td {
+  padding: 16px;
+}
+
+.email-frame-wrapper-td {
+  padding-bottom: 16px;
+}
+
+.email-frame-td > p {
+  text-align: center;
+  font-size: 16px;
+  line-height: 24px;
+}
+
+// Checklist item
+.email-checklist-wrapper-td {
+  padding: 4px 0;
+}
+
+.email-checklist-table {
+  border-radius: 12px;
+  border-width: 1px;
+  border-style: solid;
+  border-color: #efefff;
+  background-color: #fff;
+}
+
+.email-checklist-td {
+  padding: 16px;
+}
+
+.email-checklist-icons-td {
+  width: 84px;
+  vertical-align: top;
+}
+
+.email-checklist-icons-checkbox-td {
+  width: 20px;
+  vertical-align: middle;
+
+  img {
+    max-width: 100%;
+    width: 20px;
+  }
+}
+
+.email-checklist-icons-step-td {
+  width: 64px;
+  text-align: center;
+  vertical-align: middle;
+
+  img {
+    max-width: 100%;
+    width: 40px;
+  }
+}
+
+.email-checklist-text-td {
+  h3 {
+    margin: 0 0 4px;
+    color: #17063b;
+    font-size: 14px;
+    font-weight: 600;
+    line-height: 16.8px;
+  }
+
+  p {
+    margin: 0 0 2px;
+    color: #746a89;
+    font-size: 14px;
+    line-height: 16.8px;
+  }
+
+  .email-btn-table {
+    width: 100px;
+  }
+
+  .email-btn-td {
+    mso-padding-alt: 10px;
+  }
+
+  .email-btn-a {
+    padding-left: 10px;
+    padding-right: 10px;
+  }
+}
+
+// Responsive
+/* stylelint-disable-next-line media-feature-range-notation -- Basic media queries have better support across email clients. */
+@media only screen and (min-width: 740px) {
+  .email-desktop-p-8 {
+    padding: 32px !important;
+  }
+
+  .email-desktop-rounded-16px {
+    border-radius: 16px !important;
+  }
+
+  .email-header-td {
+    border-radius: 16px 16px 0 0 !important;
+  }
+
+  .email-desktop-flex {
+    display: flex;
   }
 }
diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb
index 5eecfed10..4eb38ec34 100644
--- a/app/mailers/notification_mailer.rb
+++ b/app/mailers/notification_mailer.rb
@@ -12,6 +12,8 @@ class NotificationMailer < ApplicationMailer
 
   default to: -> { email_address_with_name(@user.email, @me.username) }
 
+  layout 'mailer'
+
   def mention
     return unless @user.functional? && @status.present?
 
diff --git a/app/views/application/mailer/_button.html.haml b/app/views/application/mailer/_button.html.haml
new file mode 100644
index 000000000..61430732e
--- /dev/null
+++ b/app/views/application/mailer/_button.html.haml
@@ -0,0 +1,4 @@
+%table.email-btn-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-btn-td
+      = link_to "#{text} ➜", url, class: 'email-btn-a email-btn-hover'
diff --git a/app/views/application/mailer/_checklist.html.haml b/app/views/application/mailer/_checklist.html.haml
new file mode 100644
index 000000000..9ee965593
--- /dev/null
+++ b/app/views/application/mailer/_checklist.html.haml
@@ -0,0 +1,29 @@
+%table.email-w-full.email-checklist-wrapper-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-checklist-wrapper-td
+      %table.email-w-full.email-checklist-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-checklist-td
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+              %tr
+                %td.email-checklist-icons-td
+                  %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+                    %tr
+                      %td.email-checklist-icons-checkbox-td
+                        - if defined?(checked) && checked
+                          = image_tag full_pack_url('media/images/mailer-new/welcome/checkbox-on.png'), alt: '', width: 20, height: 20
+                        - else
+                          = image_tag full_pack_url('media/images/mailer-new/welcome/checkbox-off.png'), alt: '', width: 20, height: 20
+                      %td.email-checklist-icons-step-td
+                        - if defined?(step_image_url)
+                          = image_tag step_image_url, alt: '', width: 40, height: 40
+                %td.email-checklist-text-td
+                  .email-desktop-flex
+                    %div
+                      - if defined?(title)
+                        %h3= title
+                      - if defined?(text)
+                        %p= text
+                    %div
+                      - if defined?(button_text) && defined?(button_url) && defined?(checked) && !checked
+                        = render 'application/mailer/button', text: button_text, url: button_url
diff --git a/app/views/application/mailer/_frame.html.haml b/app/views/application/mailer/_frame.html.haml
new file mode 100644
index 000000000..74403e767
--- /dev/null
+++ b/app/views/application/mailer/_frame.html.haml
@@ -0,0 +1,4 @@
+%table.email-w-full.email-frame-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-frame-td
+      %p= text
diff --git a/app/views/application/mailer/_heading.html.haml b/app/views/application/mailer/_heading.html.haml
new file mode 100644
index 000000000..9fc5dc747
--- /dev/null
+++ b/app/views/application/mailer/_heading.html.haml
@@ -0,0 +1,13 @@
+%table.email-w-full.email-header-heading-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-header-heading-td
+      %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          - if defined?(heading_image_url)
+            %td.email-header-heading-img-td
+              = image_tag heading_image_url, alt: '', width: 56, height: 56
+          %td.email-header-heading-txt-td
+            - if defined?(heading_title)
+              %h1= heading_title
+            - if defined?(heading_subtitle)
+              %p= heading_subtitle
diff --git a/app/views/layouts/mailer.html.haml b/app/views/layouts/mailer.html.haml
index 7fa344a9b..c0f9a0a55 100644
--- a/app/views/layouts/mailer.html.haml
+++ b/app/views/layouts/mailer.html.haml
@@ -1,54 +1,87 @@
 !!!
-%html{ lang: I18n.locale }
+%html{ lang: I18n.locale, dir: locale_direction }
   %head
-    %meta{ 'http-equiv' => 'Content-Type', 'content' => 'text/html; charset=utf-8' }/
-    %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1.0, shrink-to-fit=no' }
-
+    %meta{ 'charset' => 'utf-8' }
+    %title Mastodon
+    %meta{ name: 'x-apple-disable-message-reformatting' }
+    %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
+    %meta{ name: 'format-detection', content: 'telephone=no, date=no, address=no, email=no, url=no' }
+    %meta{ name: 'supported-color-schemes', content: 'light' }
+    %style
+      \table { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
+    %style{ 'data-premailer': 'ignore' }
+      \.email a { color: inherit; text-decoration: none; }
+      \.email-btn-hover:hover { background-color: #563acc !important; }
+    /[if mso]
+      <xml>
+      <o:OfficeDocumentSettings xmlns:o="urn:schemas-microsoft-com:office:office">
+      <o:PixelsPerInch>96</o:PixelsPerInch>
+      </o:OfficeDocumentSettings>
+      </xml>
     = stylesheet_pack_tag 'mailer'
-  %body{ dir: locale_direction }
-    %table.email-table{ cellspacing: 0, cellpadding: 0 }
-      %tbody
+  %body
+    .email{ dir: locale_direction }
+      %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
         %tr
-          %td.email-body.email-start
+          %td.email-desktop-p-8
             .email-container
-              %table.content-section{ cellspacing: 0, cellpadding: 0 }
-                %tbody
-                  %tr
-                    %td.content-cell.header
-                      .email-row
-                        .col-6
-                          %table.column{ cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.column-cell
-                                  = link_to root_url do
-                                    = image_tag full_pack_url('media/images/mailer/wordmark.png'), alt: 'Mastodon', height: 34, class: 'logo'
+              /[if mso]
+                <table border="0" cellpadding="0" cellspacing="0" align="center" style="width:740px;" role="presentation"><tr><td>
+              %table.email-w-full.email-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+                %tr
+                  %td.email-card-td.email-desktop-rounded-16px
 
-    = yield
+                    -# Header
+                    %table.email-header-table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+                      %tr
+                        %td.email-header-td
 
-    %table.email-table{ cellspacing: 0, cellpadding: 0 }
-      %tbody
-        %tr
-          %td.email-body.email-end
+                          -# Logo
+                          %table.email-header-logo-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+                            %tr
+                              %td.email-header-logo-td
+                                /[if mso]
+                                  <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="false" stroke="false" style="position:absolute; left:40px; top:26px; width:636px;"><v:textbox style="mso-fit-shape-to-text:true" inset="0,0,0,0">
+                                .email-header-logo-div
+                                  %p.email-header-logo-p
+                                    %span.email-header-logo-span
+                                      = '/ '
+                                      = site_hostname
+                                /[if mso]
+                                  </v:textbox></v:rect>
+                                = link_to root_url, class: 'email-header-logo-a' do
+                                  = image_tag full_pack_url('media/images/mailer-new/common/logo-header.png'), alt: 'Mastodon', width: 157, height: 40
+
+                          -# Heading
+                          = yield :heading
+
+                    .email-header-after-div
+                      .email-header-after-inside-div
+                    %table.email-body-table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+                      %tr
+                        %td.email-body-td
+                          -# Content
+                          = yield
+
+              /[if mso]
+                </td></tr></table>
+
+            -# Footer
             .email-container
-              %table.content-section{ cellspacing: 0, cellpadding: 0 }
-                %tbody
-                  %tr
-                    %td.content-cell.content-end
-                      != '&nbsp; '
-                  %tr
-                    %td.blank-cell.footer
-                      .email-row
-                        .col-6
-                          %table.column{ cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %td.column-cell
-                                %p= t 'about.hosted_on', domain: site_hostname
-                                %p
-                                  = link_to t('application_mailer.notification_preferences'), settings_preferences_notifications_url
-                                  - if defined?(@unsubscribe_url)
-                                    ·
-                                    = link_to t('application_mailer.unsubscribe'), @unsubscribe_url
-                              %td.column-cell.text-right
-                                = link_to root_url do
-                                  = image_tag full_pack_url('media/images/mailer/logo.png'), alt: 'Mastodon', height: 24
+              /[if mso]
+                <table border="0" cellpadding="0" cellspacing="0" align="center" style="width:740px;" role="presentation"><tr><td>
+              %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+                %tr
+                  %td.email-footer-td
+                    %p.email-footer-p
+                      = link_to root_url, class: 'email-footer-logo-a' do
+                        = image_tag full_pack_url('media/images/mailer-new/common/logo-footer.png'), alt: 'Mastodon', width: 44, height: 44
+                    %p.email-footer-p
+                      = t 'about.hosted_on', domain: site_hostname
+                    %p.email-footer-p
+                      = link_to t('application_mailer.notification_preferences'), settings_preferences_notifications_url
+                      - if defined?(@unsubscribe_url)
+                        ·
+                        = link_to t('application_mailer.unsubscribe'), @unsubscribe_url
+              /[if mso]
+                </td></tr></table>
diff --git a/app/views/notification_mailer/_status.html.haml b/app/views/notification_mailer/_status.html.haml
index e053a30fd..bf38dc9aa 100644
--- a/app/views/notification_mailer/_status.html.haml
+++ b/app/views/notification_mailer/_status.html.haml
@@ -1,45 +1,31 @@
-- i ||= 0
-- highlighted ||= false
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-status-header-img
+      = image_tag full_asset_url(status.account.avatar.url), alt: '', width: 48, height: 48
+    %td.email-status-header-text
+      %h2.email-status-header-name
+        = display_name(status.account)
+      %p.email-status-header-handle
+        @#{status.account.pretty_acct}
 
-%table.email-table{ cellspacing: 0, cellpadding: 0, dir: 'ltr' }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell{ class: i.zero? ? 'content-start' : nil }
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.padded.status{ class: highlighted ? 'status--highlighted' : '' }
-                              %table.status-header{ cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td{ align: 'left', width: 48 }
-                                      = image_tag full_asset_url(status.account.avatar.url), alt: ''
-                                    %td{ align: 'left' }
-                                      %bdi= display_name(status.account)
-                                      @#{status.account.pretty_acct}
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-status-content
+      .auto-dir
+        - if status.spoiler_text?
+          %p.email-status-spoiler
+            = status.spoiler_text
 
-                              - if status.spoiler_text?
-                                .auto-dir
-                                  %p
-                                    = status.spoiler_text
+        .email-status-prose
+          = status_content_format(status)
 
-                              .auto-dir
-                                = status_content_format(status)
+        - if status.ordered_media_attachments.size.positive?
+          %p.email-status-media
+            - status.ordered_media_attachments.each do |a|
+              - if status.local?
+                = link_to full_asset_url(a.file.url(:original)), full_asset_url(a.file.url(:original))
+              - else
+                = link_to a.remote_url, a.remote_url
 
-                                - if status.ordered_media_attachments.size.positive?
-                                  %p
-                                    - status.ordered_media_attachments.each do |a|
-                                      - if status.local?
-                                        = link_to full_asset_url(a.file.url(:original)), full_asset_url(a.file.url(:original))
-                                      - else
-                                        = link_to a.remote_url, a.remote_url
-
-                              %p.status-footer
-                                = link_to l(status.created_at.in_time_zone(time_zone.presence), format: :with_time_zone), web_url("@#{status.account.pretty_acct}/#{status.id}")
+      %p.email-status-footer
+        = link_to l(status.created_at.in_time_zone(time_zone.presence), format: :with_time_zone), web_url("@#{status.account.pretty_acct}/#{status.id}")
diff --git a/app/views/notification_mailer/favourite.html.haml b/app/views/notification_mailer/favourite.html.haml
index 325f0aff5..26bb31731 100644
--- a/app/views/notification_mailer/favourite.html.haml
+++ b/app/views/notification_mailer/favourite.html.haml
@@ -1,45 +1,13 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('notification_mailer.favourite.title'), heading_subtitle: t('notification_mailer.favourite.body', name: @account.pretty_acct), heading_image_url: full_pack_url('media/images/mailer-new/heading/favorite.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td
+            = render 'status', status: @status, time_zone: @me.user_time_zone
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_grade.png'), alt: ''
-
-                              %h1= t 'notification_mailer.favourite.title'
-                              %p.lead= t('notification_mailer.favourite.body', name: @account.pretty_acct)
-
-= render 'status', status: @status, time_zone: @me.user_time_zone
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start.border-top
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to web_url("@#{@status.account.pretty_acct}/#{@status.id}") do
-                                    %span= t 'application_mailer.view_status'
+                %td.email-padding-top-24
+                  = render 'application/mailer/button', text: t('application_mailer.view_status'), url: web_url("@#{@status.account.pretty_acct}/#{@status.id}")
diff --git a/app/views/notification_mailer/follow.html.haml b/app/views/notification_mailer/follow.html.haml
index f250cbbd2..2f7ba0a9c 100644
--- a/app/views/notification_mailer/follow.html.haml
+++ b/app/views/notification_mailer/follow.html.haml
@@ -1,43 +1,9 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_person_add.png'), alt: ''
-
-                              %h1= t 'notification_mailer.follow.title'
-                              %p.lead= t('notification_mailer.follow.body', name: @account.pretty_acct)
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to web_url("@#{@account.pretty_acct}") do
-                                    %span= t 'application_mailer.view_profile'
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('notification_mailer.follow.title'), heading_subtitle: t('notification_mailer.follow.body', name: @account.pretty_acct), heading_image_url: full_pack_url('media/images/mailer-new/heading/user.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td
+            = render 'application/mailer/button', text: t('application_mailer.view_profile'), url: web_url("@#{@account.pretty_acct}")
diff --git a/app/views/notification_mailer/follow_request.html.haml b/app/views/notification_mailer/follow_request.html.haml
index 3885a411d..275d0c5b0 100644
--- a/app/views/notification_mailer/follow_request.html.haml
+++ b/app/views/notification_mailer/follow_request.html.haml
@@ -1,43 +1,9 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_person_add.png'), alt: ''
-
-                              %h1= t 'notification_mailer.follow_request.title'
-                              %p.lead= t('notification_mailer.follow_request.body', name: @account.pretty_acct)
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to web_url('follow_requests') do
-                                    %span= t 'notification_mailer.follow_request.action'
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('notification_mailer.follow_request.title'), heading_subtitle: t('notification_mailer.follow_request.body', name: @account.pretty_acct), heading_image_url: full_pack_url('media/images/mailer-new/heading/follow.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td
+            = render 'application/mailer/button', text: t('notification_mailer.follow_request.action'), url: web_url('follow_requests')
diff --git a/app/views/notification_mailer/mention.html.haml b/app/views/notification_mailer/mention.html.haml
index e830644c3..2420a42bf 100644
--- a/app/views/notification_mailer/mention.html.haml
+++ b/app/views/notification_mailer/mention.html.haml
@@ -1,45 +1,13 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('notification_mailer.mention.title'), heading_subtitle: t('notification_mailer.mention.body', name: @status.account.pretty_acct), heading_image_url: full_pack_url('media/images/mailer-new/heading/mention.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td
+            = render 'status', status: @status, time_zone: @me.user_time_zone
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_reply.png'), alt: ''
-
-                              %h1= t 'notification_mailer.mention.title'
-                              %p.lead= t('notification_mailer.mention.body', name: @status.account.pretty_acct)
-
-= render 'status', status: @status, time_zone: @me.user_time_zone
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start.border-top
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to web_url("@#{@status.account.pretty_acct}/#{@status.id}") do
-                                    %span= t 'notification_mailer.mention.action'
+                %td.email-padding-top-24
+                  = render 'application/mailer/button', text: t('notification_mailer.mention.action'), url: web_url("@#{@status.account.pretty_acct}/#{@status.id}")
diff --git a/app/views/notification_mailer/reblog.html.haml b/app/views/notification_mailer/reblog.html.haml
index e4f944123..b32c98470 100644
--- a/app/views/notification_mailer/reblog.html.haml
+++ b/app/views/notification_mailer/reblog.html.haml
@@ -1,45 +1,13 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('notification_mailer.reblog.title'), heading_subtitle: t('notification_mailer.reblog.body', name: @account.pretty_acct), heading_image_url: full_pack_url('media/images/mailer-new/heading/boost.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td
+            = render 'status', status: @status, time_zone: @me.user_time_zone
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_cached.png'), alt: ''
-
-                              %h1= t 'notification_mailer.reblog.title'
-                              %p.lead= t('notification_mailer.reblog.body', name: @account.pretty_acct)
-
-= render 'status', status: @status, time_zone: @me.user_time_zone
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start.border-top
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to web_url("@#{@status.account.pretty_acct}/#{@status.id}") do
-                                    %span= t 'application_mailer.view_status'
+                %td.email-padding-top-24
+                  = render 'application/mailer/button', text: t('application_mailer.view_status'), url: web_url("@#{@status.account.pretty_acct}/#{@status.id}")
diff --git a/app/views/user_mailer/appeal_approved.html.haml b/app/views/user_mailer/appeal_approved.html.haml
index 223ba7f0b..2cf62de39 100644
--- a/app/views/user_mailer/appeal_approved.html.haml
+++ b/app/views/user_mailer/appeal_approved.html.haml
@@ -1,61 +1,12 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_done.png'), alt: ''
-
-                              %h1= t 'user_mailer.appeal_approved.title'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center
-                              %p= t 'user_mailer.appeal_approved.explanation',
-                                    appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone),
-                                    strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to root_url do
-                                    %span= t 'user_mailer.appeal_approved.action'
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('user_mailer.appeal_approved.title'), heading_subtitle: t('user_mailer.appeal_approved.subtitle'), heading_image_url: full_pack_url('media/images/mailer-new/heading/appeal-approved.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'user_mailer.appeal_approved.explanation',
+                  appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone),
+                  strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
+            = render 'application/mailer/button', text: t('user_mailer.appeal_approved.action'), url: root_url
diff --git a/app/views/user_mailer/appeal_rejected.html.haml b/app/views/user_mailer/appeal_rejected.html.haml
index 59354f1d4..c24cf7647 100644
--- a/app/views/user_mailer/appeal_rejected.html.haml
+++ b/app/views/user_mailer/appeal_rejected.html.haml
@@ -1,61 +1,12 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_flag.png'), alt: ''
-
-                              %h1= t 'user_mailer.appeal_rejected.title'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center
-                              %p= t 'user_mailer.appeal_rejected.explanation',
-                                    appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone),
-                                    strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to root_url do
-                                    %span= t 'user_mailer.appeal_approved.action'
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('user_mailer.appeal_rejected.title'), heading_subtitle: t('user_mailer.appeal_rejected.subtitle'), heading_image_url: full_pack_url('media/images/mailer-new/heading/appeal-rejected.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'user_mailer.appeal_rejected.explanation',
+                  appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone),
+                  strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
+            = render 'application/mailer/button', text: t('user_mailer.appeal_approved.action'), url: root_url
diff --git a/app/views/user_mailer/backup_ready.html.haml b/app/views/user_mailer/backup_ready.html.haml
index 465ead2c8..4a1e7b1c6 100644
--- a/app/views/user_mailer/backup_ready.html.haml
+++ b/app/views/user_mailer/backup_ready.html.haml
@@ -1,59 +1,10 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_file_download.png'), alt: ''
-
-                              %h1= t 'user_mailer.backup_ready.title'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center
-                              %p= t 'user_mailer.backup_ready.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to download_backup_url(@backup) do
-                                    %span= t 'exports.archive_takeout.download'
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('user_mailer.backup_ready.title'), heading_subtitle: t('user_mailer.backup_ready.explanation'), heading_image_url: full_pack_url('media/images/mailer-new/heading/archive.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'user_mailer.backup_ready.extra'
+            = render 'application/mailer/button', text: t('exports.archive_takeout.download'), url: download_backup_url(@backup)
diff --git a/app/views/user_mailer/confirmation_instructions.html.haml b/app/views/user_mailer/confirmation_instructions.html.haml
index 447e689b4..4fd66d079 100644
--- a/app/views/user_mailer/confirmation_instructions.html.haml
+++ b/app/views/user_mailer/confirmation_instructions.html.haml
@@ -1,80 +1,16 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_email.png'), alt: ''
-
-                              %h1= t 'devise.mailer.confirmation_instructions.title'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center
-                              %p= t @resource.approved? ? 'devise.mailer.confirmation_instructions.explanation' : 'devise.mailer.confirmation_instructions.explanation_when_pending', host: site_hostname
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  - if @resource.created_by_application
-                                    = link_to confirmation_url(@resource, confirmation_token: @token, redirect_to_app: 'true') do
-                                      %span= t 'devise.mailer.confirmation_instructions.action_with_app', app: @resource.created_by_application.name
-                                  - else
-                                    = link_to confirmation_url(@resource, confirmation_token: @token) do
-                                      %span= t 'devise.mailer.confirmation_instructions.action'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center
-                              %p= t 'devise.mailer.confirmation_instructions.extra_html', terms_path: about_more_url, policy_path: privacy_policy_url
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.confirmation_instructions.title'), heading_image_url: full_pack_url('media/images/mailer-new/heading/email.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t @resource.approved? ? 'devise.mailer.confirmation_instructions.explanation' : 'devise.mailer.confirmation_instructions.explanation_when_pending', host: site_hostname
+            - if @resource.created_by_application
+              = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
+              = link_to confirmation_url(@resource, confirmation_token: @token, redirect_to_app: 'true') do
+                %span= t 'devise.mailer.confirmation_instructions.action_with_app', app: @resource.created_by_application.name
+            - else
+              = render 'application/mailer/button', text: t('devise.mailer.confirmation_instructions.action'), url: confirmation_url(@resource, confirmation_token: @token)
+            %p= t 'devise.mailer.confirmation_instructions.extra_html', terms_path: about_more_url, policy_path: privacy_policy_url
diff --git a/app/views/user_mailer/email_changed.html.haml b/app/views/user_mailer/email_changed.html.haml
index 96be8624d..741c2bde1 100644
--- a/app/views/user_mailer/email_changed.html.haml
+++ b/app/views/user_mailer/email_changed.html.haml
@@ -1,58 +1,11 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_email.png'), alt: ''
-
-                              %h1= t 'devise.mailer.email_changed.title'
-                              %p.lead= t 'devise.mailer.email_changed.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.input-cell
-                          %table.input{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td= @resource.unconfirmed_email
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %p= t 'devise.mailer.email_changed.extra'
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.email_changed.title'), heading_subtitle: t('devise.mailer.email_changed.explanation'), heading_image_url: full_pack_url('media/images/mailer-new/heading/email.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            = render 'application/mailer/frame', text: @resource.unconfirmed_email
+            %p= t 'devise.mailer.email_changed.extra'
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
diff --git a/app/views/user_mailer/password_change.html.haml b/app/views/user_mailer/password_change.html.haml
index 559abf027..08b4ecbbd 100644
--- a/app/views/user_mailer/password_change.html.haml
+++ b/app/views/user_mailer/password_change.html.haml
@@ -1,40 +1,10 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'devise.mailer.password_change.title'
-                              %p.lead= t 'devise.mailer.password_change.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %p= t 'devise.mailer.password_change.extra'
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.password_change.title'), heading_subtitle: t('devise.mailer.password_change.explanation'), heading_image_url: full_pack_url('media/images/mailer-new/heading/password.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'devise.mailer.password_change.extra'
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
diff --git a/app/views/user_mailer/reconfirmation_instructions.html.haml b/app/views/user_mailer/reconfirmation_instructions.html.haml
index 7f10ba94f..8aa223015 100644
--- a/app/views/user_mailer/reconfirmation_instructions.html.haml
+++ b/app/views/user_mailer/reconfirmation_instructions.html.haml
@@ -1,60 +1,11 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_email.png'), alt: ''
-
-                              %h1= t 'devise.mailer.reconfirmation_instructions.title'
-                              %p.lead= t 'devise.mailer.reconfirmation_instructions.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to confirmation_url(@resource, confirmation_token: @token) do
-                                    %span= t 'devise.mailer.confirmation_instructions.action'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %p= t 'devise.mailer.reconfirmation_instructions.extra'
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.reconfirmation_instructions.title'), heading_image_url: full_pack_url('media/images/mailer-new/heading/email.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t('devise.mailer.reconfirmation_instructions.explanation')
+            = render 'application/mailer/button', text: t('devise.mailer.confirmation_instructions.action'), url: confirmation_url(@resource, confirmation_token: @token)
+            %p= t 'devise.mailer.reconfirmation_instructions.extra'
diff --git a/app/views/user_mailer/reset_password_instructions.html.haml b/app/views/user_mailer/reset_password_instructions.html.haml
index eeed38c9e..0db79daaf 100644
--- a/app/views/user_mailer/reset_password_instructions.html.haml
+++ b/app/views/user_mailer/reset_password_instructions.html.haml
@@ -1,60 +1,10 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'devise.mailer.reset_password_instructions.title'
-                              %p.lead= t 'devise.mailer.reset_password_instructions.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to edit_password_url(@resource, reset_password_token: @token) do
-                                    %span= t 'devise.mailer.reset_password_instructions.action'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %p= t 'devise.mailer.reset_password_instructions.extra'
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.reset_password_instructions.title'), heading_subtitle: t('devise.mailer.reset_password_instructions.explanation'), heading_image_url: full_pack_url('media/images/mailer-new/heading/password.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'devise.mailer.reset_password_instructions.extra'
+            = render 'application/mailer/button', text: t('devise.mailer.reset_password_instructions.action'), url: edit_password_url(@resource, reset_password_token: @token)
diff --git a/app/views/user_mailer/suspicious_sign_in.html.haml b/app/views/user_mailer/suspicious_sign_in.html.haml
index 0cd21b4e6..e2cb916bf 100644
--- a/app/views/user_mailer/suspicious_sign_in.html.haml
+++ b/app/views/user_mailer/suspicious_sign_in.html.haml
@@ -1,71 +1,24 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon.warning-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'user_mailer.suspicious_sign_in.title'
-                              %p= t 'user_mailer.suspicious_sign_in.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center
-                              %p= t 'user_mailer.suspicious_sign_in.details'
-                          %tr
-                            %td.column-cell.text-center
-                              %p
-                                %strong #{t('sessions.ip')}:
-                                = @remote_ip
-                                %br/
-                                %strong #{t('sessions.browser')}:
-                                %span{ title: @user_agent }
-                                  = t 'sessions.description',
-                                      browser: t("sessions.browsers.#{@detection.id}", default: @detection.id.to_s),
-                                      platform: t("sessions.platforms.#{@detection.platform.id}", default: @detection.platform.id.to_s)
-                                %br/
-                                = l(@timestamp.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center
-                              %p= t 'user_mailer.suspicious_sign_in.further_actions_html',
-                                    action: link_to(t('user_mailer.suspicious_sign_in.change_password'), edit_user_registration_url)
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('user_mailer.suspicious_sign_in.title'), heading_subtitle: t('user_mailer.suspicious_sign_in.explanation'), heading_image_url: full_pack_url('media/images/mailer-new/heading/login.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'user_mailer.suspicious_sign_in.details'
+            %p
+              %strong #{t('sessions.ip')}:
+              = @remote_ip
+              %br/
+              %strong #{t('sessions.browser')}:
+              %span{ title: @user_agent }
+                = t 'sessions.description',
+                    browser: t("sessions.browsers.#{@detection.id}", default: @detection.id.to_s),
+                    platform: t("sessions.platforms.#{@detection.platform.id}", default: @detection.platform.id.to_s)
+              %br/
+              %strong #{t('sessions.date')}:
+              = l(@timestamp.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
+      %p= t 'user_mailer.suspicious_sign_in.further_actions_html',
+            action: link_to(t('user_mailer.suspicious_sign_in.change_password'), edit_user_registration_url)
diff --git a/app/views/user_mailer/two_factor_disabled.html.haml b/app/views/user_mailer/two_factor_disabled.html.haml
index 651c6f940..0d8ff5c69 100644
--- a/app/views/user_mailer/two_factor_disabled.html.haml
+++ b/app/views/user_mailer/two_factor_disabled.html.haml
@@ -1,43 +1,10 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon.alert-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'devise.mailer.two_factor_disabled.title'
-                              %p.lead= t 'devise.mailer.two_factor_disabled.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to edit_user_registration_url do
-                                    %span= t('settings.account_settings')
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.two_factor_disabled.title'), heading_subtitle: t('devise.mailer.two_factor_disabled.subtitle'), heading_image_url: full_pack_url('media/images/mailer-new/heading/2fa-disabled.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'devise.mailer.two_factor_disabled.explanation'
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
diff --git a/app/views/user_mailer/two_factor_enabled.html.haml b/app/views/user_mailer/two_factor_enabled.html.haml
index fc31bd979..6fe03eab2 100644
--- a/app/views/user_mailer/two_factor_enabled.html.haml
+++ b/app/views/user_mailer/two_factor_enabled.html.haml
@@ -1,43 +1,10 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'devise.mailer.two_factor_enabled.title'
-                              %p.lead= t 'devise.mailer.two_factor_enabled.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to edit_user_registration_url do
-                                    %span= t('settings.account_settings')
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.two_factor_enabled.title'), heading_subtitle: t('devise.mailer.two_factor_enabled.subtitle'), heading_image_url: full_pack_url('media/images/mailer-new/heading/2fa-enabled.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'devise.mailer.two_factor_enabled.explanation'
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
diff --git a/app/views/user_mailer/two_factor_recovery_codes_changed.html.haml b/app/views/user_mailer/two_factor_recovery_codes_changed.html.haml
index 833708868..dff0620ce 100644
--- a/app/views/user_mailer/two_factor_recovery_codes_changed.html.haml
+++ b/app/views/user_mailer/two_factor_recovery_codes_changed.html.haml
@@ -1,43 +1,10 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon.alert-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'devise.mailer.two_factor_recovery_codes_changed.title'
-                              %p.lead= t 'devise.mailer.two_factor_recovery_codes_changed.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to edit_user_registration_url do
-                                    %span= t('settings.account_settings')
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.two_factor_recovery_codes_changed.title'), heading_subtitle: t('devise.mailer.two_factor_recovery_codes_changed.subtitle'), heading_image_url: full_pack_url('media/images/mailer-new/heading/2fa-recovery.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'devise.mailer.two_factor_recovery_codes_changed.explanation'
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
diff --git a/app/views/user_mailer/warning.html.haml b/app/views/user_mailer/warning.html.haml
index 5d64e8324..4dfbfc231 100644
--- a/app/views/user_mailer/warning.html.haml
+++ b/app/views/user_mailer/warning.html.haml
@@ -1,98 +1,46 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t("user_mailer.warning.title.#{@warning.action}"), heading_image_url: full_pack_url('media/images/mailer-new/heading/warning.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td-without-padding
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon.alert-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_flag.png'), alt: ''
+                %td.email-prose.email-padding-24
+                  - unless @warning.none_action?
+                    %p= t "user_mailer.warning.explanation.#{@warning.action}", instance: @instance
 
-                              %h1= t "user_mailer.warning.title.#{@warning.action}"
+                  - if @warning.text.present?
+                    = linkify(@warning.text)
 
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+                  - if @warning.report && !@warning.report.other?
+                    %p
+                      %strong= t('user_mailer.warning.reason')
+                      = t("user_mailer.warning.categories.#{@warning.report.category}")
+
+                    - if @warning.report.violation? && @warning.report.rule_ids.present?
+                      %ul.rules-list
+                        - @warning.report.rules.each do |rule|
+                          %li= rule.text
+
+                  - unless @statuses.empty?
+                    %p
+                      %strong= t('user_mailer.warning.statuses')
+
+            - unless @statuses.empty?
+              %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+                %tr
+                  %td.email-border-top
+                    - @statuses.each_with_index do |status, i|
+                      %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+                        %tr
+                          %td.email-border-bottom.email-padding-24
+                            = render 'notification_mailer/status', status: status, i: i + 1, highlighted: true, time_zone: @resource.time_zone.presence
+
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.content-start
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center
-                              - unless @warning.none_action?
-                                %p= t "user_mailer.warning.explanation.#{@warning.action}", instance: @instance
-
-                              - if @warning.text.present?
-                                = linkify(@warning.text)
-
-                              - if @warning.report && !@warning.report.other?
-                                %p
-                                  %strong= t('user_mailer.warning.reason')
-                                  = t("user_mailer.warning.categories.#{@warning.report.category}")
-
-                                - if @warning.report.violation? && @warning.report.rule_ids.present?
-                                  %ul.rules-list
-                                    - @warning.report.rules.each do |rule|
-                                      %li= rule.text
-
-                              - unless @statuses.empty?
-                                %p
-                                  %strong= t('user_mailer.warning.statuses')
-
-- unless @statuses.empty?
-  - @statuses.each_with_index do |status, i|
-    = render 'notification_mailer/status', status: status, i: i + 1, highlighted: true, time_zone: @resource.time_zone.presence
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell{ class: @statuses.blank? ? '' : 'content-start' }
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to disputes_strike_url(@warning) do
-                                    %span= t 'user_mailer.warning.appeal'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center
-                              %p= t 'user_mailer.warning.appeal_description', instance: @instance
+                %td.email-prose.email-padding-24
+                  %p= t 'user_mailer.warning.appeal_description', instance: @instance
+                  = render 'application/mailer/button', text: t('user_mailer.warning.appeal'), url: disputes_strike_url(@warning)
diff --git a/app/views/user_mailer/webauthn_credential_added.html.haml b/app/views/user_mailer/webauthn_credential_added.html.haml
index 2ecb62d96..334eb3e32 100644
--- a/app/views/user_mailer/webauthn_credential_added.html.haml
+++ b/app/views/user_mailer/webauthn_credential_added.html.haml
@@ -1,44 +1,13 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.webauthn_credential.added.title'), heading_subtitle: t('devise.mailer.webauthn_credential.added.explanation'), heading_image_url: full_pack_url('media/images/mailer-new/heading/key-added.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'devise.mailer.webauthn_credential.added.title'
-                              %p.lead #{t('devise.mailer.webauthn_credential.added.explanation')}:
-                              %p.lead= @webauthn_credential.nickname
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to edit_user_registration_url do
-                                    %span= t('settings.account_settings')
+                %td.email-frame-wrapper-td
+                  = render 'application/mailer/frame', text: @webauthn_credential.nickname
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
diff --git a/app/views/user_mailer/webauthn_credential_deleted.html.haml b/app/views/user_mailer/webauthn_credential_deleted.html.haml
index f282985b1..5fad523b4 100644
--- a/app/views/user_mailer/webauthn_credential_deleted.html.haml
+++ b/app/views/user_mailer/webauthn_credential_deleted.html.haml
@@ -1,44 +1,13 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.webauthn_credential.deleted.title'), heading_subtitle: t('devise.mailer.webauthn_credential.deleted.explanation'), heading_image_url: full_pack_url('media/images/mailer-new/heading/key-deleted.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon.alert-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'devise.mailer.webauthn_credential.deleted.title'
-                              %p.lead #{t('devise.mailer.webauthn_credential.deleted.explanation')}:
-                              %p.lead= @webauthn_credential.nickname
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to edit_user_registration_url do
-                                    %span= t('settings.account_settings')
+                %td.email-frame-wrapper-td
+                  = render 'application/mailer/frame', text: @webauthn_credential.nickname
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
diff --git a/app/views/user_mailer/webauthn_disabled.html.haml b/app/views/user_mailer/webauthn_disabled.html.haml
index 81a2a7954..017412536 100644
--- a/app/views/user_mailer/webauthn_disabled.html.haml
+++ b/app/views/user_mailer/webauthn_disabled.html.haml
@@ -1,43 +1,10 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon.alert-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'devise.mailer.webauthn_disabled.title'
-                              %p.lead= t 'devise.mailer.webauthn_disabled.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to edit_user_registration_url do
-                                    %span= t('settings.account_settings')
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.webauthn_disabled.title'), heading_subtitle: t('devise.mailer.webauthn_disabled.explanation'), heading_image_url: full_pack_url('media/images/mailer-new/heading/key-disabled.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'devise.mailer.webauthn_disabled.extra'
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
diff --git a/app/views/user_mailer/webauthn_enabled.html.haml b/app/views/user_mailer/webauthn_enabled.html.haml
index f08e764e8..3257d14df 100644
--- a/app/views/user_mailer/webauthn_enabled.html.haml
+++ b/app/views/user_mailer/webauthn_enabled.html.haml
@@ -1,43 +1,10 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: ''
-
-                              %h1= t 'devise.mailer.webauthn_enabled.title'
-                              %p.lead= t 'devise.mailer.webauthn_enabled.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
-              %tr
-                %td.content-cell.content-start
-                  %table.column{ cellspacing: 0, cellpadding: 0 }
-                    %tbody
-                      %tr
-                        %td.column-cell.button-cell
-                          %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                            %tbody
-                              %tr
-                                %td.button-primary
-                                  = link_to edit_user_registration_url do
-                                    %span= t('settings.account_settings')
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('devise.mailer.webauthn_enabled.title'), heading_subtitle: t('devise.mailer.webauthn_enabled.explanation'), heading_image_url: full_pack_url('media/images/mailer-new/heading/key-enabled.png')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td.email-prose
+            %p= t 'devise.mailer.webauthn_enabled.extra'
+            = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
diff --git a/app/views/user_mailer/welcome.html.haml b/app/views/user_mailer/welcome.html.haml
index 0d8a15cfd..b77d40fb0 100644
--- a/app/views/user_mailer/welcome.html.haml
+++ b/app/views/user_mailer/welcome.html.haml
@@ -1,99 +1,25 @@
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+= content_for :heading do
+  = render 'application/mailer/heading', heading_title: t('user_mailer.welcome.title', name: @resource.account.username), heading_subtitle: t('user_mailer.welcome.explanation')
+%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+  %tr
+    %td.email-body-padding-td
+      %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
+        %tr
+          %td.email-inner-card-td-without-padding
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.hero
-                  .email-row
-                    .col-6
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.text-center.padded
-                              %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td
-                                      = image_tag full_pack_url('media/images/mailer/icon_done.png'), alt: ''
-
-                              %h1= t 'user_mailer.welcome.title', name: @resource.account.username
-                              %p.lead= t 'user_mailer.welcome.explanation'
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+                %td.email-prose.email-padding-24
+                  %p
+                    %b= t 'user_mailer.welcome.full_handle'
+                  = render 'application/mailer/frame', text: "#{@resource.account.username}@#{@instance}"
+                  %p= t 'user_mailer.welcome.full_handle_hint', instance: @instance
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.content-start
-                  .email-row
-                    .col-3
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.input-cell.text-center.padded-bottom
-                              %h5= t 'user_mailer.welcome.full_handle'
-                              %table.input{ align: 'center', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td @#{@resource.account.username}@#{@instance}
-                    .col-3
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell
-                              %p= t 'user_mailer.welcome.full_handle_hint', instance: @instance
-
-%table.email-table{ cellspacing: 0, cellpadding: 0 }
-  %tbody
-    %tr
-      %td.email-body
-        .email-container
-          %table.content-section{ cellspacing: 0, cellpadding: 0 }
-            %tbody
+                %td.email-border-top.email-prose.email-padding-24
+                  %p= t 'user_mailer.welcome.edit_profile_step'
+                  = render 'application/mailer/button', text: t('user_mailer.welcome.edit_profile_action'), url: settings_profile_url
+            %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
               %tr
-                %td.content-cell.content-start.border-top
-                  .email-row
-                    .col-4
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.padded
-                              = t 'user_mailer.welcome.edit_profile_step'
-                    .col-2
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.padded
-                              %table.button.button-small{ align: 'left', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td.button-primary
-                                      = link_to settings_profile_url do
-                                        %span= t 'user_mailer.welcome.edit_profile_action'
-
-              %tr
-                %td.content-cell.padded-bottom
-                  .email-row
-                    .col-4
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.padded
-                              = t 'user_mailer.welcome.final_step'
-                    .col-2
-                      %table.column{ cellspacing: 0, cellpadding: 0 }
-                        %tbody
-                          %tr
-                            %td.column-cell.padded
-                              %table.button.button-small{ align: 'left', cellspacing: 0, cellpadding: 0 }
-                                %tbody
-                                  %tr
-                                    %td.button-primary
-                                      = link_to web_url do
-                                        %span= t 'user_mailer.welcome.final_action'
+                %td.email-border-top.email-prose.email-padding-24
+                  %p= t 'user_mailer.welcome.edit_profile_step'
+                  = render 'application/mailer/button', text: t('user_mailer.welcome.final_action'), url: web_url
diff --git a/config/initializers/premailer_rails.rb b/config/initializers/premailer_rails.rb
index 52576ef88..5e9576be7 100644
--- a/config/initializers/premailer_rails.rb
+++ b/config/initializers/premailer_rails.rb
@@ -5,4 +5,5 @@ require_relative '../../lib/premailer_webpack_strategy'
 Premailer::Rails.config.merge!(remove_ids: true,
                                adapter: :nokogiri,
                                generate_text_part: false,
+                               css_to_attributes: false,
                                strategies: [PremailerWebpackStrategy])
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index eef821481..4439397c8 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -47,16 +47,19 @@ en:
         subject: 'Mastodon: Reset password instructions'
         title: Password reset
       two_factor_disabled:
-        explanation: Two-factor authentication for your account has been disabled. Login is now possible using only e-mail address and password.
+        explanation: Login is now possible using only e-mail address and password.
         subject: 'Mastodon: Two-factor authentication disabled'
+        subtitle: Two-factor authentication for your account has been disabled.
         title: 2FA disabled
       two_factor_enabled:
-        explanation: Two-factor authentication has been enabled for your account. A token generated by the paired TOTP app will be required for login.
+        explanation: A token generated by the paired TOTP app will be required for login.
         subject: 'Mastodon: Two-factor authentication enabled'
+        subtitle: Two-factor authentication has been enabled for your account.
         title: 2FA enabled
       two_factor_recovery_codes_changed:
         explanation: The previous recovery codes have been invalidated and new ones generated.
         subject: 'Mastodon: Two-factor recovery codes re-generated'
+        subtitle: The previous recovery codes have been invalidated and new ones generated.
         title: 2FA recovery codes changed
       unlock_instructions:
         subject: 'Mastodon: Unlock instructions'
@@ -70,11 +73,13 @@ en:
           subject: 'Mastodon: Security key deleted'
           title: One of your security keys has been deleted
       webauthn_disabled:
-        explanation: Authentication with security keys has been disabled for your account. Login is now possible using only the token generated by the paired TOTP app.
+        explanation: Authentication with security keys has been disabled for your account.
+        extra: Login is now possible using only the token generated by the paired TOTP app.
         subject: 'Mastodon: Authentication with security keys disabled'
         title: Security keys disabled
       webauthn_enabled:
-        explanation: Security key authentication has been enabled for your account. Your security key can now be used for login.
+        explanation: Security key authentication has been enabled for your account.
+        extra: Your security key can now be used for login.
         subject: 'Mastodon: Security key authentication enabled'
         title: Security keys enabled
     omniauth_callbacks:
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 50f814a81..78820c3b5 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1609,6 +1609,7 @@ en:
       unknown_browser: Unknown Browser
       weibo: Weibo
     current_session: Current session
+    date: Date
     description: "%{browser} on %{platform}"
     explanation: These are the web browsers currently logged in to your Mastodon account.
     ip: IP
@@ -1775,16 +1776,19 @@ en:
     webauthn: Security keys
   user_mailer:
     appeal_approved:
-      action: Go to your account
+      action: Account Settings
       explanation: The appeal of the strike against your account on %{strike_date} that you submitted on %{appeal_date} has been approved. Your account is once again in good standing.
       subject: Your appeal from %{date} has been approved
+      subtitle: Your account is once again in good standing.
       title: Appeal approved
     appeal_rejected:
       explanation: The appeal of the strike against your account on %{strike_date} that you submitted on %{appeal_date} has been rejected.
       subject: Your appeal from %{date} has been rejected
+      subtitle: Your appeal has been rejected.
       title: Appeal rejected
     backup_ready:
-      explanation: You requested a full backup of your Mastodon account. It's now ready for download!
+      explanation: You requested a full backup of your Mastodon account.
+      extra: It's now ready for download!
       subject: Your archive is ready for download
       title: Archive takeout
     suspicious_sign_in: