diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationItemView.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationItemView.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6a5507360948cbc9053871709f0fb16c4e98a2e6
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationItemView.kt
@@ -0,0 +1,173 @@
+package org.briarproject.briar.desktop.conversation
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.Card
+import androidx.compose.material.Icon
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Done
+import androidx.compose.material.icons.filled.DoneAll
+import androidx.compose.material.icons.filled.Schedule
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import org.briarproject.bramble.api.sync.GroupId
+import org.briarproject.bramble.api.sync.MessageId
+import org.briarproject.briar.api.client.SessionId
+import org.briarproject.briar.desktop.conversation.ConversationRequestItem.RequestType.INTRODUCTION
+import org.briarproject.briar.desktop.theme.msgIn
+import org.briarproject.briar.desktop.theme.msgOut
+import org.briarproject.briar.desktop.theme.msgStroke
+import org.briarproject.briar.desktop.theme.privateMessageDate
+import org.briarproject.briar.desktop.theme.textPrimary
+import org.briarproject.briar.desktop.utils.InternationalizationUtils
+import org.briarproject.briar.desktop.utils.PreviewUtils.preview
+import org.briarproject.briar.desktop.utils.TimeUtils.getFormattedTimestamp
+import java.time.Instant
+
+fun main() = preview {
+    LazyColumn {
+        item {
+            ConversationNoticeItemView(
+                ConversationNoticeItem(
+                    msgText = "Let's test a received notice message.",
+                    text = "Text of notice message.",
+                    id = MessageId(getRandomId()),
+                    groupId = GroupId(getRandomId()),
+                    time = Instant.now().toEpochMilli(),
+                    autoDeleteTimer = 0,
+                    isIncoming = true,
+                    isRead = true,
+                    isSent = false,
+                    isSeen = false,
+                )
+            )
+        }
+        item {
+            ConversationMessageItemView(
+                ConversationMessageItem(
+                    text = "This is a medium-sized message that has been sent before receiving the request message.",
+                    id = MessageId(getRandomId()),
+                    groupId = GroupId(getRandomId()),
+                    time = Instant.now().toEpochMilli(),
+                    autoDeleteTimer = 0,
+                    isIncoming = false,
+                    isRead = false,
+                    isSent = true,
+                    isSeen = true,
+                )
+            )
+        }
+        item {
+            ConversationRequestItemView(
+                ConversationRequestItem(
+                    requestedGroupId = null,
+                    requestType = INTRODUCTION,
+                    sessionId = SessionId(getRandomId()),
+                    answered = false,
+                    msgText = "Short message.",
+                    text = "Text of notice message.",
+                    id = MessageId(getRandomId()),
+                    groupId = GroupId(getRandomId()),
+                    time = Instant.now().toEpochMilli(),
+                    autoDeleteTimer = 0,
+                    isIncoming = true,
+                    isRead = true,
+                    isSent = false,
+                    isSeen = false,
+                )
+            )
+        }
+        item {
+            ConversationNoticeItemView(
+                ConversationNoticeItem(
+                    msgText = "This is a long long long message that spans over several lines.\n\nIt ends here.",
+                    text = "Text of notice message.",
+                    id = MessageId(getRandomId()),
+                    groupId = GroupId(getRandomId()),
+                    time = Instant.now().toEpochMilli(),
+                    autoDeleteTimer = 0,
+                    isIncoming = false,
+                    isRead = false,
+                    isSent = true,
+                    isSeen = true,
+                )
+            )
+        }
+        item {
+            ConversationMessageItemView(
+                ConversationMessageItem(
+                    text = "Just also receiving a normal message.",
+                    id = MessageId(getRandomId()),
+                    groupId = GroupId(getRandomId()),
+                    time = Instant.now().toEpochMilli(),
+                    autoDeleteTimer = 0,
+                    isIncoming = true,
+                    isRead = true,
+                    isSent = false,
+                    isSeen = false,
+                )
+            )
+        }
+    }
+}
+
+@Composable
+fun ConversationItemView(
+    item: ConversationItem,
+    content: @Composable () -> Unit
+) {
+    val alignment = if (item.isIncoming) Alignment.Start else Alignment.End
+    val color = if (item.isIncoming) MaterialTheme.colors.msgIn else MaterialTheme.colors.msgOut
+    val shape = if (item.isIncoming)
+        RoundedCornerShape(topStart = 4.dp, topEnd = 16.dp, bottomStart = 16.dp, bottomEnd = 16.dp)
+    else
+        RoundedCornerShape(topStart = 16.dp, topEnd = 4.dp, bottomStart = 16.dp, bottomEnd = 16.dp)
+
+    Column(Modifier.fillMaxWidth()) {
+        Column(Modifier.fillMaxWidth(fraction = 0.8f).align(alignment)) {
+            Card(
+                backgroundColor = color,
+                elevation = 2.dp,
+                shape = shape,
+                border = BorderStroke(Dp.Hairline, MaterialTheme.colors.msgStroke),
+                modifier = Modifier.align(alignment).padding(8.dp),
+            ) {
+                content()
+            }
+        }
+    }
+}
+
+@Composable
+fun ColumnScope.ConversationItemStatusView(item: ConversationItem, rowModifier: Modifier = Modifier) {
+    val statusColor = if (item.isIncoming) MaterialTheme.colors.textPrimary else MaterialTheme.colors.privateMessageDate
+    val statusAlignment = if (item.isIncoming) Alignment.End else Alignment.Start
+    Row(rowModifier.align(statusAlignment)) {
+        Text(
+            text = getFormattedTimestamp(item.time),
+            fontSize = 12.sp,
+            color = statusColor,
+        )
+        if (!item.isIncoming) {
+            val modifier = Modifier.padding(start = 4.dp).size(12.dp).align(Alignment.CenterVertically)
+            val icon =
+                if (item.isSeen) Icons.Filled.DoneAll // acknowledged
+                else if (item.isSent) Icons.Filled.Done // sent
+                else Icons.Filled.Schedule // waiting
+            Icon(icon, InternationalizationUtils.i18n("access.message.sent"), modifier, statusColor)
+        }
+    }
+}
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationMessageItemView.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationMessageItemView.kt
new file mode 100644
index 0000000000000000000000000000000000000000..74833a0d0790f76c6b2f878dca62fbf0f4a15ddf
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationMessageItemView.kt
@@ -0,0 +1,58 @@
+package org.briarproject.briar.desktop.conversation
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import org.briarproject.bramble.api.sync.GroupId
+import org.briarproject.bramble.api.sync.MessageId
+import org.briarproject.briar.desktop.theme.textPrimary
+import org.briarproject.briar.desktop.utils.PreviewUtils.preview
+import java.time.Instant
+
+fun main() = preview(
+    "text" to "This is a long long long message that spans over several lines.\n\nIt ends here.",
+    "time" to Instant.now().toEpochMilli(),
+    "isIncoming" to false,
+    "isRead" to false,
+    "isSent" to false,
+    "isSeen" to true,
+) {
+    ConversationMessageItemView(
+        ConversationMessageItem(
+            text = getStringParameter("text"),
+            id = MessageId(getRandomId()),
+            groupId = GroupId(getRandomId()),
+            time = getLongParameter("time"),
+            autoDeleteTimer = 0,
+            isIncoming = getBooleanParameter("isIncoming"),
+            isRead = getBooleanParameter("isRead"),
+            isSent = getBooleanParameter("isSent"),
+            isSeen = getBooleanParameter("isSeen"),
+        )
+    )
+}
+
+@Composable
+fun ConversationMessageItemView(m: ConversationMessageItem) {
+    val textColor = if (m.isIncoming) MaterialTheme.colors.textPrimary else Color.White
+    ConversationItemView(m) {
+        Column(
+            Modifier.padding(12.dp, 8.dp)
+        ) {
+            Text(
+                m.text!!,
+                fontSize = 16.sp,
+                color = textColor,
+                modifier = Modifier.align(Alignment.Start).padding(bottom = 8.dp)
+            )
+            ConversationItemStatusView(m)
+        }
+    }
+}
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationNoticeItemView.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationNoticeItemView.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6bea0b49922220fb54bdfd8c41c66fecb462fda1
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationNoticeItemView.kt
@@ -0,0 +1,80 @@
+package org.briarproject.briar.desktop.conversation
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import org.briarproject.bramble.api.sync.GroupId
+import org.briarproject.bramble.api.sync.MessageId
+import org.briarproject.briar.desktop.theme.noticeIn
+import org.briarproject.briar.desktop.theme.noticeOut
+import org.briarproject.briar.desktop.theme.privateMessageDate
+import org.briarproject.briar.desktop.theme.textPrimary
+import org.briarproject.briar.desktop.theme.textSecondary
+import org.briarproject.briar.desktop.utils.PreviewUtils.preview
+import java.time.Instant
+
+fun main() = preview(
+    "msgText" to "This is a long long long message that spans over several lines.\n\nIt ends here.",
+    "text" to "Text of notice message.",
+    "time" to Instant.now().toEpochMilli(),
+    "isIncoming" to false,
+    "isRead" to false,
+    "isSent" to false,
+    "isSeen" to true,
+) {
+    ConversationNoticeItemView(
+        ConversationNoticeItem(
+            msgText = getStringParameter("msgText"),
+            text = getStringParameter("text"),
+            id = MessageId(getRandomId()),
+            groupId = GroupId(getRandomId()),
+            time = getLongParameter("time"),
+            autoDeleteTimer = 0,
+            isIncoming = getBooleanParameter("isIncoming"),
+            isRead = getBooleanParameter("isRead"),
+            isSent = getBooleanParameter("isSent"),
+            isSeen = getBooleanParameter("isSeen"),
+        )
+    )
+}
+
+@Composable
+fun ConversationNoticeItemView(m: ConversationNoticeItem) {
+    val textColor = if (m.isIncoming) MaterialTheme.colors.textPrimary else Color.White
+    val noticeBackground = if (m.isIncoming) MaterialTheme.colors.noticeIn else MaterialTheme.colors.noticeOut
+    val noticeColor = if (m.isIncoming) MaterialTheme.colors.textSecondary else MaterialTheme.colors.privateMessageDate
+    ConversationItemView(m) {
+        Column(Modifier.width(IntrinsicSize.Max)) {
+            Text(
+                m.msgText,
+                fontSize = 16.sp,
+                color = textColor,
+                modifier = Modifier.padding(12.dp, 8.dp).align(Alignment.Start)
+            )
+            Column(
+                Modifier.fillMaxWidth().background(noticeBackground).padding(12.dp, 8.dp)
+            ) {
+                Text(
+                    text = m.text!!,
+                    fontSize = 14.sp,
+                    fontStyle = FontStyle.Italic,
+                    color = noticeColor,
+                    modifier = Modifier.align(Alignment.Start).padding(bottom = 8.dp)
+                )
+                ConversationItemStatusView(m)
+            }
+        }
+    }
+}
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationRequestItemView.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationRequestItemView.kt
new file mode 100644
index 0000000000000000000000000000000000000000..07b6bf6d6f5fb75ed4e6a7efc6b4046e80d25484
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationRequestItemView.kt
@@ -0,0 +1,99 @@
+package org.briarproject.briar.desktop.conversation
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import org.briarproject.bramble.api.sync.GroupId
+import org.briarproject.bramble.api.sync.MessageId
+import org.briarproject.briar.api.client.SessionId
+import org.briarproject.briar.desktop.conversation.ConversationRequestItem.RequestType.INTRODUCTION
+import org.briarproject.briar.desktop.theme.buttonTextNegative
+import org.briarproject.briar.desktop.theme.buttonTextPositive
+import org.briarproject.briar.desktop.theme.noticeIn
+import org.briarproject.briar.desktop.theme.noticeOut
+import org.briarproject.briar.desktop.theme.privateMessageDate
+import org.briarproject.briar.desktop.theme.textPrimary
+import org.briarproject.briar.desktop.theme.textSecondary
+import org.briarproject.briar.desktop.utils.PreviewUtils.preview
+import java.time.Instant
+
+fun main() = preview(
+    "msgText" to "Short message",
+    "text" to "Text of notice message.",
+    "time" to Instant.now().toEpochMilli(),
+    "isIncoming" to true,
+    "isRead" to false,
+    "isSent" to false,
+    "isSeen" to true,
+) {
+    ConversationRequestItemView(
+        ConversationRequestItem(
+            requestedGroupId = null,
+            requestType = INTRODUCTION,
+            sessionId = SessionId(getRandomId()),
+            answered = false,
+            msgText = getStringParameter("msgText"),
+            text = getStringParameter("text"),
+            id = MessageId(getRandomId()),
+            groupId = GroupId(getRandomId()),
+            time = getLongParameter("time"),
+            autoDeleteTimer = 0,
+            isIncoming = getBooleanParameter("isIncoming"),
+            isRead = getBooleanParameter("isRead"),
+            isSent = getBooleanParameter("isSent"),
+            isSeen = getBooleanParameter("isSeen"),
+        )
+    )
+}
+
+@Composable
+fun ConversationRequestItemView(m: ConversationRequestItem) {
+    val statusAlignment = if (m.isIncoming) Alignment.End else Alignment.Start
+    val textColor = if (m.isIncoming) MaterialTheme.colors.textPrimary else Color.White
+    val noticeBackground = if (m.isIncoming) MaterialTheme.colors.noticeIn else MaterialTheme.colors.noticeOut
+    val noticeColor = if (m.isIncoming) MaterialTheme.colors.textSecondary else MaterialTheme.colors.privateMessageDate
+    ConversationItemView(m) {
+        Column(Modifier.width(IntrinsicSize.Max)) {
+            Text(
+                m.msgText,
+                fontSize = 16.sp,
+                color = textColor,
+                modifier = Modifier.padding(12.dp, 8.dp).align(Alignment.Start)
+            )
+            Column(
+                Modifier.fillMaxWidth().background(noticeBackground).padding(12.dp, 8.dp)
+            ) {
+                Text(
+                    text = m.text!!,
+                    fontSize = 14.sp,
+                    fontStyle = FontStyle.Italic,
+                    color = noticeColor,
+                    modifier = Modifier.align(Alignment.Start),
+                )
+                Row(modifier = Modifier.align(statusAlignment)) {
+                    TextButton({}) {
+                        Text("Decline".uppercase(), fontSize = 16.sp, color = MaterialTheme.colors.buttonTextNegative)
+                    }
+                    TextButton({}) {
+                        Text("Accept".uppercase(), fontSize = 16.sp, color = MaterialTheme.colors.buttonTextPositive)
+                    }
+                }
+                ConversationItemStatusView(m)
+            }
+        }
+    }
+}
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationScreen.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationScreen.kt
index bde1041e197380018711a1741127dbb4ef920319..654a3472ec4557e99f407100e412bd97b42d2e48 100644
--- a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationScreen.kt
+++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationScreen.kt
@@ -21,7 +21,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material.MaterialTheme
 import androidx.compose.material.Scaffold
-import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
@@ -81,8 +80,9 @@ fun ConversationScreen(
                 ) {
                     items(viewModel.messages) { m ->
                         when (m) {
-                            is ConversationMessageItem -> TextBubble(m)
-                            else -> Text("Placeholder for something else.")
+                            is ConversationMessageItem -> ConversationMessageItemView(m)
+                            is ConversationNoticeItem -> ConversationNoticeItemView(m)
+                            is ConversationRequestItem -> ConversationRequestItemView(m)
                         }
                     }
                 }
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/TextBubble.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/TextBubble.kt
deleted file mode 100644
index 044eba7d4187c805e1a212668d2b8a61419839b8..0000000000000000000000000000000000000000
--- a/src/main/kotlin/org/briarproject/briar/desktop/conversation/TextBubble.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.briarproject.briar.desktop.conversation
-
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.Card
-import androidx.compose.material.Icon
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Done
-import androidx.compose.material.icons.filled.DoneAll
-import androidx.compose.material.icons.filled.Schedule
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import org.briarproject.bramble.api.sync.GroupId
-import org.briarproject.bramble.api.sync.MessageId
-import org.briarproject.briar.desktop.theme.awayMsgBubble
-import org.briarproject.briar.desktop.theme.localMsgBubble
-import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
-import org.briarproject.briar.desktop.utils.PreviewUtils.preview
-import org.briarproject.briar.desktop.utils.TimeUtils
-import java.time.Instant
-
-fun main() = preview(
-    "text" to "Lorem ipsum dolor sit amet.",
-    "time" to Instant.now().toEpochMilli(),
-    "isIncoming" to false,
-    "isRead" to false,
-    "isSent" to false,
-    "isSeen" to false,
-) {
-    TextBubble(
-        ConversationMessageItem(
-            text = getStringParameter("text"),
-            id = MessageId(getRandomId()),
-            groupId = GroupId(getRandomId()),
-            time = getLongParameter("time"),
-            autoDeleteTimer = 0,
-            isIncoming = getBooleanParameter("isIncoming"),
-            isRead = getBooleanParameter("isRead"),
-            isSent = getBooleanParameter("isSent"),
-            isSeen = getBooleanParameter("isSeen"),
-        )
-    )
-}
-
-@Composable
-fun TextBubble(m: ConversationMessageItem) {
-    val alignment = if (m.isIncoming) Alignment.Start else Alignment.End
-    val color = if (m.isIncoming) MaterialTheme.colors.awayMsgBubble else MaterialTheme.colors.localMsgBubble
-    val shape = if (m.isIncoming)
-        RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp, bottomEnd = 10.dp)
-    else
-        RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp, bottomStart = 10.dp)
-
-    Column(Modifier.fillMaxWidth()) {
-        Column(Modifier.fillMaxWidth(fraction = 0.8f).align(alignment)) {
-            Card(Modifier.align(alignment), backgroundColor = color, shape = shape) {
-                Column(
-                    Modifier.padding(8.dp)
-                ) {
-                    Text(m.text!!, fontSize = 14.sp, modifier = Modifier.align(Alignment.Start))
-                    Row(modifier = Modifier.padding(top = 4.dp)) {
-                        Text(TimeUtils.getFormattedTimestamp(m.time), Modifier.padding(end = 4.dp), fontSize = 10.sp)
-                        if (!m.isIncoming) {
-                            val modifier = Modifier.size(12.dp).align(Alignment.CenterVertically)
-                            val icon =
-                                if (m.isSeen) Icons.Filled.DoneAll // acknowledged
-                                else if (m.isSent) Icons.Filled.Done // sent
-                                else Icons.Filled.Schedule // waiting
-                            Icon(icon, i18n("access.message.sent"), modifier)
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/theme/Colors.kt b/src/main/kotlin/org/briarproject/briar/desktop/theme/Colors.kt
index f3fa146562a1680be413e2ea10c92029df4db076..c91d4cce51243cdbe52c6b3f9f61278332bc24e1 100644
--- a/src/main/kotlin/org/briarproject/briar/desktop/theme/Colors.kt
+++ b/src/main/kotlin/org/briarproject/briar/desktop/theme/Colors.kt
@@ -2,8 +2,11 @@ package org.briarproject.briar.desktop.theme
 
 import androidx.compose.ui.graphics.Color
 
-val Night500 = Color(0xff435B77)
-val Night700 = Color(0xff2E3D4F)
+val Night50 = Color(0xffebf3fa)
+val Night500 = Color(0xff435b77)
+val Night700 = Color(0xff2e3d4f)
+val Night800 = Color(0xff212d3b)
+val Night950 = Color(0xff0e171f)
 
 val Gray50 = Color(0xfffafafa)
 val Gray100 = Color(0xfff2f2f2)
@@ -17,10 +20,19 @@ val Gray900 = Color(0xff2e2e2e)
 val Gray950 = Color(0xff1f1f1f)
 val materialDarkBg = Color(0xff121212)
 
-val Blue500 = Color(0xff1f78d1)
+val Red500 = Color(0xffdb3b21)
+
+val Blue400 = Color(0xff418cd8)
+val Blue500 = Color(0xff1f78d1) // todo: unused in Android
+val Blue600 = Color(0xff1b69b6)
 val Blue800 = Color(0xff134a81)
 
 val Lime300 = Color(0xff95DE2D)
 val Lime500 = Color(0xff74B816)
 
+val TextPrimaryMaterialDark = Color(0xffffffff)
+val TextPrimaryMaterialLight = Color(0xde000000)
+val TextSecondaryMaterialDark = Color(0xb3ffffff)
+val TextSecondaryMaterialLight = Color(0x8a000000)
+
 val briarError = Color(0xffb00020)
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/theme/Theme.kt b/src/main/kotlin/org/briarproject/briar/desktop/theme/Theme.kt
index d04411c20142f0cb2fdfa1fdfdbe6d732a8e4c62..07559de1c5a7be9dfbee964a54d4a102f18147e9 100644
--- a/src/main/kotlin/org/briarproject/briar/desktop/theme/Theme.kt
+++ b/src/main/kotlin/org/briarproject/briar/desktop/theme/Theme.kt
@@ -13,8 +13,16 @@ val Colors.outline: Color get() = if (isLight) Gray900 else Gray200
 val Colors.surfaceVariant: Color get() = if (isLight) Gray100 else Gray950
 val Colors.sidebarSurface: Color get() = if (isLight) Gray200 else Gray900
 val Colors.selectedCard: Color get() = if (isLight) Gray400 else Gray700
-val Colors.localMsgBubble: Color get() = Blue500
-val Colors.awayMsgBubble: Color get() = if (isLight) Gray300 else Gray800
+val Colors.msgStroke: Color get() = if (isLight) Gray300 else Gray900
+val Colors.msgIn: Color get() = if (isLight) Color.White else Night700
+val Colors.msgOut: Color get() = if (isLight) Blue400 else Blue600
+val Colors.noticeIn: Color get() = if (isLight) Night50 else Night800
+val Colors.noticeOut: Color get() = if (isLight) Blue600 else Blue800
+val Colors.textPrimary: Color get() = if (isLight) TextPrimaryMaterialLight else TextPrimaryMaterialDark
+val Colors.textSecondary: Color get() = if (isLight) TextSecondaryMaterialLight else TextSecondaryMaterialDark
+val Colors.privateMessageDate: Color get() = Gray200
+val Colors.buttonTextNegative: Color get() = Red500
+val Colors.buttonTextPositive: Color get() = Blue400
 
 val DarkColors = darkColors(
     primary = Blue500,