diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/AboutFragment.kt b/app/src/main/java/partisan/weforge/xyz/pulse/AboutFragment.kt
index 48ec0a1..e312052 100644
--- a/app/src/main/java/partisan/weforge/xyz/pulse/AboutFragment.kt
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/AboutFragment.kt
@@ -25,6 +25,13 @@ class AboutFragment : Fragment() {
         return binding.root
     }
 
+    override fun onResume() {
+        super.onResume()
+        (requireActivity() as? MainActivity)?.setAppBarTitle(
+            getString(R.string.about_name)
+        )
+    }
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/CallRedirectionService.kt b/app/src/main/java/partisan/weforge/xyz/pulse/CallRedirectionService.kt
index 105157b..5f7a9b3 100644
--- a/app/src/main/java/partisan/weforge/xyz/pulse/CallRedirectionService.kt
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/CallRedirectionService.kt
@@ -63,9 +63,16 @@ class CallRedirectionService : CallRedirectionService() {
             return
         }
 
+        val phoneNumber = handle.schemeSpecificPart
+
+        if (prefs.isBlacklistEnabled && !prefs.isContactWhitelisted(phoneNumber)) {
+            placeCallUnmodified()
+            return
+        }
+
         val records: Array<Record>
         try {
-            records = getRecordsFromPhoneNumber(handle.schemeSpecificPart)
+            records = getRecordsFromPhoneNumber(phoneNumber)
         } catch (exc: SecurityException) {
             placeCallUnmodified()
             return
diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/ContactsFragment.kt b/app/src/main/java/partisan/weforge/xyz/pulse/ContactsFragment.kt
index d7d9822..2244501 100644
--- a/app/src/main/java/partisan/weforge/xyz/pulse/ContactsFragment.kt
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/ContactsFragment.kt
@@ -26,6 +26,27 @@ class ContactsFragment : Fragment() {
         return binding.root
     }
 
+    override fun onResume() {
+        super.onResume()
+        (requireActivity() as? MainActivity)?.apply {
+            setAppBarTitle(getString(R.string.settings_name), getString(R.string.whitelist_name))
+            setupPopupToggle(true, prefs.isBlacklistEnabled) { isChecked ->
+                prefs.isBlacklistEnabled = isChecked
+                binding.contactRecycler.isEnabled = isChecked
+                binding.contactRecycler.alpha = if (isChecked) 1f else 0.4f
+            }
+        }
+
+        // Initial state
+        binding.contactRecycler.isEnabled = prefs.isBlacklistEnabled
+        binding.contactRecycler.alpha = if (prefs.isBlacklistEnabled) 1f else 0.4f
+    }
+
+    override fun onPause() {
+        super.onPause()
+        (requireActivity() as? MainActivity)?.setupPopupToggle(false)
+    }
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/MainActivity.kt b/app/src/main/java/partisan/weforge/xyz/pulse/MainActivity.kt
index 8a281be..a291b4e 100644
--- a/app/src/main/java/partisan/weforge/xyz/pulse/MainActivity.kt
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/MainActivity.kt
@@ -2,6 +2,9 @@ package partisan.weforge.xyz.pulse
 
 import android.content.Intent
 import android.os.Bundle
+import android.view.View
+import android.view.Menu
+import android.view.MenuItem
 import androidx.appcompat.app.AppCompatActivity
 import partisan.weforge.xyz.pulse.databinding.ActivityMainBinding
 import androidx.appcompat.app.ActionBarDrawerToggle
@@ -9,17 +12,24 @@ import partisan.weforge.xyz.pulse.REQUIRED_PERMISSIONS
 import partisan.weforge.xyz.pulse.hasCallRedirectionRole
 import partisan.weforge.xyz.pulse.hasDrawOverlays
 import partisan.weforge.xyz.pulse.hasGeneralPermissions
+import com.google.android.material.switchmaterial.SwitchMaterial
 
 class MainActivity : AppCompatActivity() {
 
     private lateinit var binding: ActivityMainBinding
     private lateinit var prefs: Preferences
 
+    private var popupSwitch: SwitchMaterial? = null
+    private var popupMenuItem: MenuItem? = null
+
+    val popupToggle: SwitchMaterial
+        get() = findViewById(R.id.globalPopupToggle)
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         binding = ActivityMainBinding.inflate(layoutInflater)
         setContentView(binding.root)
-
+        prefs = Preferences(this)
         setSupportActionBar(binding.topAppBar)
 
         val drawerToggle = ActionBarDrawerToggle(
@@ -27,7 +37,7 @@ class MainActivity : AppCompatActivity() {
             binding.drawerLayout,
             binding.topAppBar,
             R.string.navigation_drawer_open,
-            R.string.navigation_drawer_close
+            R.string.navigation_drawer_open // The "close" string is never actually shown in the UI, so I reuse "navigation_drawer_open" as sort of a placeholder
         )
         binding.drawerLayout.addDrawerListener(drawerToggle)
         drawerToggle.syncState()
@@ -36,6 +46,8 @@ class MainActivity : AppCompatActivity() {
             .replace(R.id.fragmentContainer, MainFragment())
             .commit()
 
+        setupPopupToggle(false)
+
         binding.navigationView.setNavigationItemSelectedListener { item ->
             when (item.itemId) {
                 R.id.action_popup_settings -> {
@@ -73,6 +85,33 @@ class MainActivity : AppCompatActivity() {
         }
     }
 
+    override fun onCreateOptionsMenu(menu: Menu): Boolean {
+        menuInflater.inflate(R.menu.topbar_toggle, menu)
+        popupMenuItem = menu.findItem(R.id.globalPopupToggle)
+        popupSwitch = popupMenuItem?.actionView?.findViewById(R.id.globalPopupToggle)
+        popupMenuItem?.isVisible = false // hide by default
+        return true
+    }
+
+    fun setupPopupToggle(
+        visible: Boolean,
+        initialState: Boolean = false,
+        onToggle: ((Boolean) -> Unit)? = null
+    ) {
+        popupMenuItem?.isVisible = visible
+        popupSwitch?.apply {
+            setOnCheckedChangeListener(null)
+            isChecked = initialState
+            setOnCheckedChangeListener { _, isChecked ->
+                onToggle?.invoke(isChecked)
+            }
+        }
+    }
+
+    fun setAppBarTitle(vararg parts: String) {
+        binding.topAppBar.title = parts.joinToString(" > ")
+    }
+
     private fun hasPermissions(): Boolean {
         return hasGeneralPermissions(this) &&
                hasDrawOverlays(this) &&
diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/MainFragment.kt b/app/src/main/java/partisan/weforge/xyz/pulse/MainFragment.kt
index 90b53ca..9e8c3b4 100644
--- a/app/src/main/java/partisan/weforge/xyz/pulse/MainFragment.kt
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/MainFragment.kt
@@ -18,6 +18,11 @@ class MainFragment : Fragment() {
     private lateinit var prefs: Preferences
     private var lastConfettiTime = 0L
 
+    override fun onResume() {
+        super.onResume()
+        (requireActivity() as? MainActivity)?.setAppBarTitle(getString(R.string.app_name))
+    }
+
     override fun onCreateView(
         inflater: LayoutInflater,
         container: ViewGroup?,
diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/MatrixRainView.kt b/app/src/main/java/partisan/weforge/xyz/pulse/MatrixRainView.kt
new file mode 100644
index 0000000..01b61c4
--- /dev/null
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/MatrixRainView.kt
@@ -0,0 +1,48 @@
+package partisan.weforge.xyz.pulse
+
+import android.content.Context
+import android.graphics.*
+import android.view.View
+import kotlin.random.Random
+
+class MatrixRainView(context: Context) : View(context) {
+    private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
+        color = Color.GREEN
+        textSize = 5f * resources.displayMetrics.density
+        typeface = Typeface.MONOSPACE
+    }
+
+    private val charset = "01アイウエオカキクケコ".toCharArray()
+    private val random = Random
+    private var columns = 0
+    private lateinit var yOffsets: IntArray
+
+    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
+        super.onSizeChanged(w, h, oldw, oldh)
+        columns = w / paint.textSize.toInt()
+        yOffsets = IntArray(columns) { random.nextInt(h) }
+    }
+
+    override fun onDraw(canvas: Canvas) {
+        // drawColor with transparent clear instead of black
+        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
+
+        for (i in 0 until columns) {
+            val x = i * paint.textSize
+            val y = yOffsets[i].toFloat()
+            val char = charset[random.nextInt(charset.size)]
+
+            paint.alpha = 255
+            canvas.drawText(char.toString(), x, y, paint)
+
+            paint.alpha = 100
+            canvas.drawText(char.toString(), x, y - paint.textSize, paint)
+
+            yOffsets[i] += paint.textSize.toInt()
+            if (yOffsets[i] > height) {
+                yOffsets[i] = 0
+            }
+        }
+        postInvalidateDelayed(50)
+    }
+}
diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/PopupSettingsFragment.kt b/app/src/main/java/partisan/weforge/xyz/pulse/PopupSettingsFragment.kt
index 6bd8d97..29eda70 100644
--- a/app/src/main/java/partisan/weforge/xyz/pulse/PopupSettingsFragment.kt
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/PopupSettingsFragment.kt
@@ -7,6 +7,10 @@ import android.util.DisplayMetrics
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.widget.ArrayAdapter
+import android.widget.AdapterView
+import android.widget.CompoundButton
+import android.widget.Spinner
 import androidx.fragment.app.Fragment
 import androidx.core.content.getSystemService
 import partisan.weforge.xyz.pulse.databinding.FragmentPopupSettingsBinding
@@ -28,20 +32,35 @@ class PopupSettingsFragment : Fragment() {
         return binding.root
     }
 
+    override fun onResume() {
+        super.onResume()
+        (requireActivity() as? MainActivity)?.apply {
+            setAppBarTitle(getString(R.string.settings_name), getString(R.string.popup_name))
+            setupPopupToggle(true, prefs.popupEnabled) { isChecked ->
+                prefs.popupEnabled = isChecked
+                updateControls(isChecked)
+            }
+        }
+    }
+
+    override fun onPause() {
+        super.onPause()
+        (requireActivity() as? MainActivity)?.setupPopupToggle(false)
+    }
+
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
         prefs = Preferences(requireContext())
         window = PopupWindow(requireContext(), null)
 
-        binding.popupEnabledCheckbox.isChecked = prefs.popupEnabled
-        binding.popupEnabledCheckbox.setOnCheckedChangeListener { _, isChecked ->
-            prefs.popupEnabled = isChecked
-            updateControls(isChecked)
-        }
-
         binding.popupPreview.setOnClickListener {
-            window.preview()
+            window.preview(false)
+        }
+        binding.popupPreview.setOnLongClickListener {
+            window.preview(true)
+            true
         }
 
         binding.redirectionDelay.value = (prefs.redirectionDelay / 1000).toFloat()
@@ -52,6 +71,22 @@ class PopupSettingsFragment : Fragment() {
             prefs.redirectionDelay = (value * 1000).toLong()
         }
 
+        val effectNames = resources.getStringArray(R.array.popup_effects)
+        val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, effectNames)
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+        binding.popupEffectSpinner.adapter = adapter
+
+        // Select current setting
+        binding.popupEffectSpinner.setSelection(prefs.popupEffect.ordinal)
+
+        binding.popupEffectSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+            override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
+                prefs.popupEffect = Preferences.PopupEffect.values()[position]
+            }
+
+            override fun onNothingSelected(parent: AdapterView<*>) {}
+        }
+
         val screenHeight = getScreenHeightPx()
         binding.popupHeightSlider.valueFrom = 0f
         binding.popupHeightSlider.valueTo = screenHeight.toFloat()
@@ -67,6 +102,8 @@ class PopupSettingsFragment : Fragment() {
         binding.redirectionDelay.isEnabled = enabled
         binding.popupHeightSlider.isEnabled = enabled
         binding.popupPreview.isEnabled = enabled
+        binding.popupEffectSpinner.isEnabled = enabled
+        binding.popupEffectLabel.isEnabled = enabled
     }
 
     private fun getScreenHeightPx(): Int {
diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/PopupWindow.kt b/app/src/main/java/partisan/weforge/xyz/pulse/PopupWindow.kt
index fa81ca6..d3059ec 100644
--- a/app/src/main/java/partisan/weforge/xyz/pulse/PopupWindow.kt
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/PopupWindow.kt
@@ -5,15 +5,19 @@ import android.content.Context
 import android.content.Intent
 import android.graphics.Color
 import android.graphics.PixelFormat
+import android.graphics.Rect
 import android.media.AudioManager
 import android.net.Uri
 import android.view.Gravity
 import android.view.LayoutInflater
+import android.view.View
 import android.view.WindowManager
 import android.view.ContextThemeWrapper
 import android.widget.TextView
 import android.animation.ObjectAnimator
 import android.widget.ProgressBar
+import android.view.animation.OvershootInterpolator
+import android.view.animation.DecelerateInterpolator
 import androidx.annotation.RequiresPermission
 import androidx.core.content.res.use
 import com.google.android.material.card.MaterialCardView
@@ -24,6 +28,8 @@ import android.util.Log
 import android.content.res.ColorStateList
 import com.google.android.material.color.DynamicColors
 import com.google.android.material.color.MaterialColors
+import partisan.weforge.xyz.pulse.Preferences.PopupEffect
+import partisan.weforge.xyz.pulse.MatrixRainView
 
 class PopupWindow(
     ctx: Context,
@@ -46,7 +52,9 @@ class PopupWindow(
         height = WindowManager.LayoutParams.WRAP_CONTENT
         y = prefs.popupPosition
     }
-    private var timer: Timer? = null
+    private var currentEffect: PopupEffect = PopupEffect.NONE
+    private var matrixOverlay: View? = null
+    private var timer: Timer? = null 
 
     init {
         view.setOnClickListener {
@@ -58,16 +66,25 @@ class PopupWindow(
         applyResolvedColors(view)
     }
 
-    fun preview() {
+    fun preview(isLongPress: Boolean = false) {
         remove()
         layoutParams.y = prefs.popupPosition
+
         val destinations = listOf(
             R.string.destination_signal,
             R.string.destination_telegram,
             R.string.destination_threema,
+            // Whatsapp smells
         )
         setDescription(destinations.random())
         add()
+
+        val duration = if (isLongPress) prefs.redirectionDelay * 5 else prefs.redirectionDelay
+        timer?.cancel()
+        timer = Timer()
+        timer?.schedule(timerTask {
+            remove()
+        }, duration)
     }
 
     fun show(uri: Uri, destinationId: Int) {
@@ -128,10 +145,125 @@ class PopupWindow(
         }
     }
 
+    private fun animateAppear() {
+        view.animate().cancel()
+        view.rotationX = 0f
+        view.scaleX = 1f
+        view.scaleY = 1f
+        view.alpha = 1f
+
+        val effect = when (prefs.popupEffect) {
+            PopupEffect.RANDOM -> PopupEffect.values().filter { it != PopupEffect.RANDOM && it != PopupEffect.NONE }.random()
+            else -> prefs.popupEffect
+        }
+        currentEffect = effect
+
+        when (effect) {
+            PopupEffect.NONE -> {}
+            PopupEffect.FADE -> {
+                view.alpha = 0f
+                view.animate().alpha(1f).setDuration(300).start()
+            }
+            PopupEffect.SCALE -> {
+                view.scaleX = 0f
+                view.scaleY = 0f
+                view.animate().scaleX(1f).scaleY(1f).setDuration(300).start()
+            }
+            PopupEffect.BOUNCE -> {
+                view.scaleX = 0.7f
+                view.scaleY = 0.7f
+                view.animate().scaleX(1f).scaleY(1f)
+                    .setInterpolator(OvershootInterpolator())
+                    .setDuration(400).start()
+            }
+            PopupEffect.FLOP -> {
+                view.rotationX = 90f
+                view.alpha = 0f
+                view.animate().rotationX(0f).alpha(1f)
+                    .setDuration(350)
+                    .setInterpolator(DecelerateInterpolator())
+                    .start()
+            }
+            PopupEffect.MATRIX -> {
+                val rainView = MatrixRainView(themedCtx)
+                matrixOverlay?.let {
+                    try {
+                        windowManager?.removeViewImmediate(it)
+                    } catch (_: Exception) {}
+                }
+                matrixOverlay = rainView
+
+                val popupBounds = Rect()
+                view.getGlobalVisibleRect(popupBounds)
+
+                val overlayParams = WindowManager.LayoutParams().apply {
+                    type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
+                    format = PixelFormat.TRANSLUCENT
+                    flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    width = view.width
+                    height = view.height
+                    gravity = Gravity.BOTTOM
+                    x = 0
+                    y = layoutParams.y
+                }
+
+                try {
+                    windowManager?.addView(rainView, overlayParams)
+                } catch (e: Exception) {
+                    Log.e("MatrixRain", "Failed to add rainView", e)
+                    return
+                }
+
+                // Fade-in popup over 500ms
+                view.alpha = 0f
+                view.animate().cancel()
+                view.animate().alpha(1f).setDuration(500).start()
+
+                // Remove MatrixRainView in sync
+                rainView.animate().alpha(0f).setDuration(500).withEndAction {
+                    try {
+                        windowManager?.removeView(rainView)
+                        matrixOverlay = null
+                    } catch (_: Exception) {}
+                }.start()
+            }
+            else -> {}
+        }
+    }
+
+    private fun animateDisappear(onEnd: () -> Unit) {
+        when (currentEffect) {
+            PopupEffect.NONE -> onEnd()
+            PopupEffect.FADE -> view.animate().alpha(0f).setDuration(200).withEndAction(onEnd).start()
+            PopupEffect.SCALE, PopupEffect.BOUNCE -> view.animate().scaleX(0f).scaleY(0f).setDuration(200).withEndAction(onEnd).start()
+            PopupEffect.FLOP -> view.animate().rotationX(90f).alpha(0f).setDuration(200).withEndAction(onEnd).start()
+            PopupEffect.MATRIX -> {
+                view.animate().alpha(0f).setDuration(150).withEndAction(onEnd).start()
+                matrixOverlay?.let { overlay ->
+                    overlay.animate().cancel()
+                    overlay.animate().alpha(0f).setDuration(150).withEndAction {
+                        try {
+                            windowManager?.removeViewImmediate(overlay)
+                        } catch (_: Exception) {}
+                        matrixOverlay = null
+                    }.start()
+                }
+            }
+            else -> onEnd()
+        }
+    }
+
     private fun add(): Boolean {
         try {
+            // If already attached, force remove and re-add
+            if (view.parent != null) {
+                windowManager?.removeViewImmediate(view)
+            }
+            view.animate().cancel()
             windowManager?.addView(view, layoutParams)
-        } catch (exc: WindowManager.BadTokenException) {
+            animateAppear()
+        } catch (exc: Exception) {
+            Log.e("PopupWindow", "Failed to add popup view", exc)
             return false
         }
         return true
@@ -139,9 +271,18 @@ class PopupWindow(
 
     private fun remove(): Boolean {
         try {
-            windowManager?.removeView(view)
-        } catch (_: IllegalArgumentException) {
-        } catch (_: WindowManager.BadTokenException) {
+            animateDisappear {
+                try {
+                    windowManager?.removeView(view)
+                    matrixOverlay?.let {
+                        try {
+                            windowManager?.removeViewImmediate(it)
+                        } catch (_: Exception) {}
+                        matrixOverlay = null
+                    }
+                } catch (_: Exception) {}
+            }
+        } catch (_: Exception) {
             return false
         }
         return true
diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/Preferences.kt b/app/src/main/java/partisan/weforge/xyz/pulse/Preferences.kt
index d9b87a8..bad91c5 100644
--- a/app/src/main/java/partisan/weforge/xyz/pulse/Preferences.kt
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/Preferences.kt
@@ -10,7 +10,9 @@ class Preferences(private val context: Context) {
         private const val REDIRECTION_DELAY = "redirection_delay"
         private const val POPUP_POSITION = "popup_position_y"
         private const val POPUP_ENABLED = "popup_enabled"
+        private val POPUP_EFFECT = "popup_effect"
         private const val BLACKLISTED_CONTACTS = "blacklisted_contacts"
+        private const val BLACKLIST_ENABLED = "blacklist_enabled"
         private val SERVICE_ORDER_KEY = "service_order"
 
         private const val DEFAULT_REDIRECTION_DELAY = 2000L
@@ -32,6 +34,29 @@ class Preferences(private val context: Context) {
                 hasDrawOverlays(context) &&
                 hasCallRedirectionRole(context)
 
+    enum class PopupEffect {
+        NONE, FADE, SCALE, BOUNCE, FLOP, MATRIX, RANDOM
+    }
+
+    var popupEffect: PopupEffect
+        get() {
+            val name = prefs.getString(POPUP_EFFECT, PopupEffect.FADE.name) ?: PopupEffect.FADE.name
+            return try {
+                PopupEffect.valueOf(name)
+            } catch (_: IllegalArgumentException) {
+                // If invalid, fallback and clear the broken value
+                prefs.edit().remove(POPUP_EFFECT).apply()
+                PopupEffect.BOUNCE
+            }
+        }
+        set(value) {
+            prefs.edit().putString(POPUP_EFFECT, value.name).apply()
+        }
+
+    var isBlacklistEnabled: Boolean
+    get() = prefs.getBoolean(BLACKLIST_ENABLED, false)
+    set(value) = prefs.edit { putBoolean(BLACKLIST_ENABLED, value) }
+
     var popupEnabled: Boolean
         get() = prefs.getBoolean(POPUP_ENABLED, true)
         set(value) = prefs.edit { putBoolean(POPUP_ENABLED, value) }
diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/ServicesFragment.kt b/app/src/main/java/partisan/weforge/xyz/pulse/ServicesFragment.kt
index 2d82657..add151a 100644
--- a/app/src/main/java/partisan/weforge/xyz/pulse/ServicesFragment.kt
+++ b/app/src/main/java/partisan/weforge/xyz/pulse/ServicesFragment.kt
@@ -23,6 +23,14 @@ class ServiceSettingsFragment : Fragment() {
         return binding.root
     }
 
+    override fun onResume() {
+        super.onResume()
+        (requireActivity() as? MainActivity)?.setAppBarTitle(
+            getString(R.string.settings_name),
+            getString(R.string.services_name)
+        )
+    }
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 36fed6b..c0ed222 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -19,9 +19,11 @@
             app:titleTextColor="?attr/colorOnSurface"
             app:navigationIconTint="?attr/colorOnSurface"
             app:title="@string/app_name"
+            app:titleTextAppearance="@style/Toolbar.Title.Small"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent" />
+            app:layout_constraintEnd_toEndOf="parent">
+        </com.google.android.material.appbar.MaterialToolbar>
 
         <FrameLayout
             android:id="@+id/fragmentContainer"
diff --git a/app/src/main/res/layout/fragment_popup_settings.xml b/app/src/main/res/layout/fragment_popup_settings.xml
index e11fade..d9fb419 100644
--- a/app/src/main/res/layout/fragment_popup_settings.xml
+++ b/app/src/main/res/layout/fragment_popup_settings.xml
@@ -5,44 +5,24 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:padding="32dp"
-    tools:context=".PopupSettingsFragment">
+    android:padding="32dp">
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 
+        <!-- Delay label -->
         <TextView
-            android:id="@+id/description"
+            android:id="@+id/delayDescription"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:text="@string/popup_settings_description"
-            android:textSize="16sp"
+            android:text="@string/redirection_delay_description"
+            android:textSize="12sp"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent" />
 
-        <CheckBox
-            android:id="@+id/popupEnabledCheckbox"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:text="@string/popup_enabled"
-            android:textSize="14sp"
-            app:layout_constraintTop_toBottomOf="@id/description"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toStartOf="@id/popupPreview"
-            android:layout_marginTop="16dp" />
-
-        <Button
-            android:id="@+id/popupPreview"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/test"
-            app:layout_constraintTop_toTopOf="@id/popupEnabledCheckbox"
-            app:layout_constraintBottom_toBottomOf="@id/popupEnabledCheckbox"
-            app:layout_constraintEnd_toEndOf="parent"
-            android:layout_marginStart="8dp" />
-
+        <!-- Delay slider -->
         <com.google.android.material.slider.Slider
             android:id="@+id/redirectionDelay"
             android:layout_width="0dp"
@@ -51,22 +31,24 @@
             android:valueFrom="2"
             android:valueTo="4"
             android:contentDescription="@string/redirection_delay_description"
-            app:layout_constraintTop_toBottomOf="@id/popupEnabledCheckbox"
+            app:layout_constraintTop_toBottomOf="@id/delayDescription"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
-            android:layout_marginTop="16dp" />
+            android:layout_marginTop="8dp" />
 
+        <!-- Position label -->
         <TextView
-            android:id="@+id/delayDescription"
+            android:id="@+id/heightDescription"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:text="@string/redirection_delay_description"
+            android:text="@string/popup_position"
             android:textSize="12sp"
             app:layout_constraintTop_toBottomOf="@id/redirectionDelay"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
-            android:layout_marginTop="4dp" />
+            android:layout_marginTop="16dp" />
 
+        <!-- Position slider -->
         <com.google.android.material.slider.Slider
             android:id="@+id/popupHeightSlider"
             android:layout_width="0dp"
@@ -75,21 +57,43 @@
             android:valueTo="100"
             android:stepSize="1"
             android:contentDescription="@string/popup_position"
-            app:layout_constraintTop_toBottomOf="@id/delayDescription"
+            app:layout_constraintTop_toBottomOf="@id/heightDescription"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
-            android:layout_marginTop="16dp" />
+            android:layout_marginTop="8dp" />
 
+        <!-- Animation label -->
         <TextView
-            android:id="@+id/heightDescription"
+            android:id="@+id/popupEffectLabel"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:text="@string/popup_position"
+            android:text="@string/popup_effect_label"
             android:textSize="12sp"
             app:layout_constraintTop_toBottomOf="@id/popupHeightSlider"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
-            android:layout_marginTop="4dp" />
+            android:layout_marginTop="16dp" />
+
+        <!-- Animation dropdown -->
+        <Spinner
+            android:id="@+id/popupEffectSpinner"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:layout_constraintTop_toBottomOf="@id/popupEffectLabel"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            android:layout_marginTop="8dp" />
+
+        <!-- Test button -->
+        <Button
+            android:id="@+id/popupPreview"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/test"
+            app:layout_constraintTop_toBottomOf="@id/popupEffectSpinner"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            android:layout_marginTop="16dp" />
 
     </androidx.constraintlayout.widget.ConstraintLayout>
 </ScrollView>
diff --git a/app/src/main/res/layout/fragment_service_settings.xml b/app/src/main/res/layout/fragment_service_settings.xml
index a5dce49..03da59f 100644
--- a/app/src/main/res/layout/fragment_service_settings.xml
+++ b/app/src/main/res/layout/fragment_service_settings.xml
@@ -6,23 +6,25 @@
     android:layout_height="match_parent"
     android:padding="16dp">
 
-    <TextView
-        android:id="@+id/serviceHeader"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/service_settings_title"
-        android:textSize="18sp"
-        android:textStyle="bold"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        android:layout_marginBottom="8dp" />
-
     <androidx.recyclerview.widget.RecyclerView
         android:id="@+id/serviceRecycler"
         android:layout_width="0dp"
         android:layout_height="0dp"
         android:scrollbars="vertical"
-        app:layout_constraintTop_toBottomOf="@id/serviceHeader"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toTopOf="@id/serviceHeader"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent" />
+
+    <TextView
+        android:id="@+id/serviceHeader"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:text="@string/services_desc"
+        android:textSize="12sp"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="8dp"
+        app:layout_constraintTop_toBottomOf="@id/serviceRecycler"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent" />
diff --git a/app/src/main/res/layout/popup.xml b/app/src/main/res/layout/popup.xml
index 1031757..1d401d5 100644
--- a/app/src/main/res/layout/popup.xml
+++ b/app/src/main/res/layout/popup.xml
@@ -5,8 +5,11 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:clipChildren="false"
+    android:clipToPadding="false"
     app:cardCornerRadius="24dp"
     app:cardElevation="4dp"
+    android:padding="24dp"
     app:cardBackgroundColor="?attr/colorSurface">
 
     <LinearLayout
diff --git a/app/src/main/res/layout/switch_item.xml b/app/src/main/res/layout/switch_item.xml
new file mode 100644
index 0000000..ece0273
--- /dev/null
+++ b/app/src/main/res/layout/switch_item.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.google.android.material.switchmaterial.SwitchMaterial xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/globalPopupToggle"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:textSize="12sp"
+    android:checked="true" />
diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml
index 8cd0dd4..eb960d5 100644
--- a/app/src/main/res/menu/main_menu.xml
+++ b/app/src/main/res/menu/main_menu.xml
@@ -4,32 +4,32 @@
     <!-- Settings section -->
     <item
         android:id="@+id/section_settings"
-        android:title="Settings"
+        android:title="@string/settings_name"
         android:enabled="false" />
     <item
         android:id="@+id/action_contacts"
-        android:title="Contacts"
+        android:title="@string/whitelist_name"
         android:icon="@drawable/group_24px"
         app:showAsAction="never" />
     <item
         android:id="@+id/action_popup_settings"
-        android:title="Popup"
+        android:title="@string/popup_name"
         android:icon="@drawable/tooltip_24px"
         app:showAsAction="never" />
     <item
         android:id="@+id/action_services"
-        android:title="Services"
+        android:title="@string/services_name"
         android:icon="@drawable/services_24"
         app:showAsAction="never" />
 
     <!-- About section -->
     <item
         android:id="@+id/section_about"
-        android:title="About"
+        android:title="@string/about_name"
         android:enabled="false" />
     <item
         android:id="@+id/action_about"
-        android:title="About"
+        android:title="@string/about_name"
         android:icon="@drawable/info_24px"
         app:showAsAction="never" />
 </menu>
diff --git a/app/src/main/res/menu/topbar_toggle.xml b/app/src/main/res/menu/topbar_toggle.xml
new file mode 100644
index 0000000..157a5d9
--- /dev/null
+++ b/app/src/main/res/menu/topbar_toggle.xml
@@ -0,0 +1,7 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+      xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item
+        android:id="@+id/globalPopupToggle"
+        app:actionLayout="@layout/switch_item"
+        app:showAsAction="always" />
+</menu>
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 4caa5d3..ba94153 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -9,5 +9,4 @@
     <string name="destination_whatsapp">WhatsApp</string>
     <string name="redirection_delay_description">Задержка до того, как звонок будет перенаправлен.</string>
     <string name="popup_position">Позиция всплывающего окна</string>
-    <string name="fallback">Обратная совместимость</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2fdb72e..e5e8e6c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -3,21 +3,36 @@
     <string name="app_name">Pulse</string>
     <string name="description">Redirects outgoing calls to E2EE apps if available.</string>
     <string name="popup">Redirecting to %1$s</string>
+    <string name="settings_name">Settings</string>
+    <string name="popup_name">Popup</string>
+    <string name="services_name">Services</string>
+    <string name="whitelist_name">Allowlist</string>
+    <string name="tools_name">Tools</string>
+    <string name="about_name">About</string>
+    <string name="donate_name">Donate</string>
     <string name="destination_signal">Signal</string>
     <string name="destination_telegram">Telegram</string>
     <string name="destination_threema">Threema</string>
     <string name="destination_whatsapp">WhatsApp</string>
     <string name="redirection_delay_description">The delay before a call will be redirected.</string>
+    <string name="services_desc">Here you can enable or disable redirection to individual services and change their priority by dragging them. Redirection will be handled in order from top to bottom.</string>
     <string name="popup_position">Popup position</string>
-    <string name="fallback">Fallback</string>
     <string name="activate_description">To start, grant the required permissions by tapping the Activate button.</string>
-    <string name="service_settings_title">Service Preferences</string>
     <string name="activate">Activate</string>
     <string name="navigation_drawer_open">Open menu</string>
-    <string name="navigation_drawer_close">Close menu</string>
-    <string name="popup_settings_description">Configure popup behavior, position, and delay.</string>
-    <string name="popup_enabled">Popup enabled</string>
     <string name="test">Test</string>
     <string name="source_code">Source Code</string>
     <string name="license">License</string>
+
+    <string name="popup_effect_label">Popup Animation</string>
+    <string-array name="popup_effects">
+        <item>None</item>
+        <item>Fade</item>
+        <item>Scale</item>
+        <item>Bounce</item>
+        <item>Flop</item>
+        <item>Matrix</item>
+        <item>Random</item>
+    </string-array>
+
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index eabcdff..1464804 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -4,4 +4,7 @@
         <item name="cornerFamily">rounded</item>
         <item name="cornerSize">100%</item>
     </style>
+    <style name="Toolbar.Title.Small" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
+        <item name="android:textSize">16sp</item>
+    </style>
 </resources>