diff --git a/Cargo.lock b/Cargo.lock
index a0fad2ad34..35352aed85 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -841,7 +841,6 @@ name = "cap"
 version = "0.1.0"
 dependencies = [
  "cap-camera",
- "cap-displays",
  "cap-editor",
  "cap-export",
  "cap-flags",
@@ -853,6 +852,7 @@ dependencies = [
  "clap",
  "ffmpeg-next",
  "flume",
+ "scap-targets",
  "serde",
  "serde_json",
  "tokio",
@@ -959,9 +959,9 @@ dependencies = [
 name = "cap-cursor-capture"
 version = "0.1.0"
 dependencies = [
- "cap-displays",
  "core-graphics 0.24.0",
  "device_query",
+ "scap-targets",
 ]
 
 [[package]]
@@ -988,7 +988,6 @@ dependencies = [
  "bytemuck",
  "cap-audio",
  "cap-camera",
- "cap-displays",
  "cap-editor",
  "cap-export",
  "cap-fail",
@@ -1029,6 +1028,7 @@ dependencies = [
  "reqwest",
  "rodio",
  "scap",
+ "scap-targets",
  "sentry",
  "serde",
  "serde_json",
@@ -1070,22 +1070,6 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
-[[package]]
-name = "cap-displays"
-version = "0.1.0"
-dependencies = [
- "cidre 0.11.0",
- "cocoa 0.26.1",
- "core-foundation 0.10.1",
- "core-graphics 0.24.0",
- "image 0.24.9",
- "objc",
- "serde",
- "specta",
- "tracing",
- "windows 0.60.0",
-]
-
 [[package]]
 name = "cap-editor"
 version = "0.1.0"
@@ -1168,7 +1152,6 @@ dependencies = [
  "cap-camera-ffmpeg",
  "cap-camera-windows",
  "cap-cpal-ffmpeg",
- "cap-displays",
  "cap-fail",
  "cap-flags",
  "cap-media-encoders",
@@ -1196,6 +1179,7 @@ dependencies = [
  "scap-direct3d",
  "scap-ffmpeg",
  "scap-screencapturekit",
+ "scap-targets",
  "screencapturekit",
  "serde",
  "specta",
@@ -1260,7 +1244,6 @@ dependencies = [
  "cap-camera-ffmpeg",
  "cap-cursor-capture",
  "cap-cursor-info",
- "cap-displays",
  "cap-fail",
  "cap-flags",
  "cap-media",
@@ -1291,6 +1274,7 @@ dependencies = [
  "scap-direct3d",
  "scap-ffmpeg",
  "scap-screencapturekit",
+ "scap-targets",
  "screencapturekit",
  "serde",
  "serde_json",
@@ -6994,8 +6978,8 @@ dependencies = [
 name = "scap-direct3d"
 version = "0.1.0"
 dependencies = [
- "cap-displays",
  "scap-ffmpeg",
+ "scap-targets",
  "thiserror 1.0.69",
  "windows 0.60.0",
 ]
@@ -7004,7 +6988,6 @@ dependencies = [
 name = "scap-ffmpeg"
 version = "0.1.0"
 dependencies = [
- "cap-displays",
  "cidre 0.11.0",
  "cpal 0.16.0",
  "ffmpeg-next",
@@ -7012,6 +6995,7 @@ dependencies = [
  "scap-cpal",
  "scap-direct3d",
  "scap-screencapturekit",
+ "scap-targets",
  "tokio",
  "windows 0.60.0",
 ]
@@ -7020,7 +7004,6 @@ dependencies = [
 name = "scap-screencapturekit"
 version = "0.1.0"
 dependencies = [
- "cap-displays",
  "cidre 0.11.0",
  "clap",
  "futures",
@@ -7028,9 +7011,26 @@ dependencies = [
  "objc2 0.6.1",
  "objc2-app-kit",
  "objc2-foundation 0.3.1",
+ "scap-targets",
  "tracing",
 ]
 
+[[package]]
+name = "scap-targets"
+version = "0.1.0"
+dependencies = [
+ "cidre 0.11.0",
+ "cocoa 0.26.1",
+ "core-foundation 0.10.1",
+ "core-graphics 0.24.0",
+ "image 0.24.9",
+ "objc",
+ "serde",
+ "specta",
+ "tracing",
+ "windows 0.60.0",
+]
+
 [[package]]
 name = "schannel"
 version = "0.1.27"
diff --git a/apps/cli/Cargo.toml b/apps/cli/Cargo.toml
index 6a9a6aeac0..18d52a2634 100644
--- a/apps/cli/Cargo.toml
+++ b/apps/cli/Cargo.toml
@@ -14,7 +14,7 @@ cap-flags = { path = "../../crates/flags" }
 cap-recording = { path = "../../crates/recording" }
 cap-export = { path = "../../crates/export" }
 cap-camera = { path = "../../crates/camera" }
-cap-displays = { path = "../../crates/displays" }
+scap-targets = { path = "../../crates/scap-targets" }
 serde = { workspace = true }
 serde_json = "1.0.133"
 tokio.workspace = true
diff --git a/apps/cli/src/record.rs b/apps/cli/src/record.rs
index aed946e096..5aa545a64f 100644
--- a/apps/cli/src/record.rs
+++ b/apps/cli/src/record.rs
@@ -1,7 +1,7 @@
 use cap_camera::ModelID;
-use cap_displays::{DisplayId, WindowId};
 use cap_recording::screen_capture::ScreenCaptureTarget;
 use clap::Args;
+use scap_targets::{DisplayId, WindowId};
 use std::{env::current_dir, path::PathBuf, sync::Arc};
 use tokio::{io::AsyncBufReadExt, sync::Mutex};
 use uuid::Uuid;
diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml
index 7c49e88664..bf349ef10c 100644
--- a/apps/desktop/src-tauri/Cargo.toml
+++ b/apps/desktop/src-tauri/Cargo.toml
@@ -88,7 +88,7 @@ cap-media = { path = "../../../crates/media" }
 cap-flags = { path = "../../../crates/flags" }
 cap-recording = { path = "../../../crates/recording" }
 cap-export = { path = "../../../crates/export" }
-cap-displays = { path = "../../../crates/displays" }
+scap-targets = { path = "../../../crates/scap-targets" }
 
 flume.workspace = true
 tracing-subscriber = "0.3.19"
diff --git a/apps/desktop/src-tauri/src/fake_window.rs b/apps/desktop/src-tauri/src/fake_window.rs
index ce273e45b4..b474b57268 100644
--- a/apps/desktop/src-tauri/src/fake_window.rs
+++ b/apps/desktop/src-tauri/src/fake_window.rs
@@ -1,4 +1,4 @@
-use cap_displays::bounds::LogicalBounds;
+use scap_targets::bounds::LogicalBounds;
 use std::{collections::HashMap, sync::Arc, time::Duration};
 use tauri::{AppHandle, Manager, WebviewWindow};
 use tokio::{sync::RwLock, time::sleep};
diff --git a/apps/desktop/src-tauri/src/general_settings.rs b/apps/desktop/src-tauri/src/general_settings.rs
index 280d4302e1..f8e6b4725c 100644
--- a/apps/desktop/src-tauri/src/general_settings.rs
+++ b/apps/desktop/src-tauri/src/general_settings.rs
@@ -105,8 +105,7 @@ fn default_enable_native_camera_preview() -> bool {
 }
 
 fn default_enable_new_recording_flow() -> bool {
-    false
-    // cfg!(debug_assertions)
+    cfg!(debug_assertions)
 }
 
 fn no(_: &bool) -> bool {
diff --git a/apps/desktop/src-tauri/src/hotkeys.rs b/apps/desktop/src-tauri/src/hotkeys.rs
index d59cab3f3c..6d16f9afa3 100644
--- a/apps/desktop/src-tauri/src/hotkeys.rs
+++ b/apps/desktop/src-tauri/src/hotkeys.rs
@@ -101,7 +101,7 @@ pub fn init(app: &AppHandle) {
     )
     .unwrap();
 
-    let mut store = match HotkeysStore::get(app) {
+    let store = match HotkeysStore::get(app) {
         Ok(Some(s)) => s,
         Ok(None) => HotkeysStore::default(),
         Err(e) => {
diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs
index 38c15d50ea..053c6a3ead 100644
--- a/apps/desktop/src-tauri/src/lib.rs
+++ b/apps/desktop/src-tauri/src/lib.rs
@@ -26,13 +26,13 @@ mod windows;
 use audio::AppSounds;
 use auth::{AuthStore, AuthenticationInvalid, Plan};
 use camera::{CameraPreview, CameraWindowState};
-use cap_displays::{DisplayId, WindowId, bounds::LogicalBounds};
 use cap_editor::{EditorInstance, EditorState};
 use cap_project::{
     ProjectConfiguration, RecordingMeta, RecordingMetaInner, SharingMeta, StudioRecordingMeta, XY,
     ZoomSegment,
 };
 use cap_recording::{
+    RecordingMode,
     feeds::{
         self, CameraFeed, DeviceOrModelID, RawCameraFrame,
         microphone::{self, MicrophoneFeed},
@@ -54,6 +54,7 @@ use scap::{
     capturer::Capturer,
     frame::{Frame, VideoFrame},
 };
+use scap_targets::{DisplayId, WindowId, bounds::LogicalBounds};
 use serde::{Deserialize, Serialize};
 use serde_json::json;
 use specta::Type;
@@ -91,7 +92,10 @@ use crate::upload::build_video_meta;
 #[allow(clippy::large_enum_variant)]
 pub enum RecordingState {
     None,
-    Pending,
+    Pending {
+        mode: RecordingMode,
+        target: ScreenCaptureTarget,
+    },
     Active(InProgressRecording),
 }
 
@@ -148,8 +152,8 @@ pub struct VideoUploadInfo {
 }
 
 impl App {
-    pub fn set_pending_recording(&mut self) {
-        self.recording_state = RecordingState::Pending;
+    pub fn set_pending_recording(&mut self, mode: RecordingMode, target: ScreenCaptureTarget) {
+        self.recording_state = RecordingState::Pending { mode, target };
         CurrentRecordingChanged.emit(&self.handle).ok();
     }
 
@@ -445,7 +449,7 @@ enum CurrentRecordingTarget {
 #[serde(rename_all = "camelCase")]
 struct CurrentRecording {
     target: CurrentRecordingTarget,
-    r#type: RecordingType,
+    mode: RecordingMode,
 }
 
 #[tauri::command]
@@ -454,37 +458,29 @@ async fn get_current_recording(
     state: MutableState<'_, App>,
 ) -> Result<JsonValue<Option<CurrentRecording>>, ()> {
     let state = state.read().await;
-    Ok(JsonValue::new(
-        &state
-            .current_recording()
-            .map(|r| {
-                let target = match r.capture_target() {
-                    ScreenCaptureTarget::Display { id } => {
-                        CurrentRecordingTarget::Screen { id: id.clone() }
-                    }
-                    ScreenCaptureTarget::Window { id } => CurrentRecordingTarget::Window {
-                        id: id.clone(),
-                        bounds: cap_displays::Window::from_id(id)
-                            .ok_or(())?
-                            .display_relative_logical_bounds()
-                            .ok_or(())?,
-                    },
-                    ScreenCaptureTarget::Area { screen, bounds } => CurrentRecordingTarget::Area {
-                        screen: screen.clone(),
-                        bounds: bounds.clone(),
-                    },
-                };
 
-                Ok(CurrentRecording {
-                    target,
-                    r#type: match r {
-                        InProgressRecording::Instant { .. } => RecordingType::Instant,
-                        InProgressRecording::Studio { .. } => RecordingType::Studio,
-                    },
-                })
-            })
-            .transpose()?,
-    ))
+    let (mode, capture_target) = match &state.recording_state {
+        RecordingState::None => return Ok(JsonValue::new(&None)),
+        RecordingState::Pending { mode, target } => (*mode, target),
+        RecordingState::Active(inner) => (inner.mode(), inner.capture_target()),
+    };
+
+    let target = match capture_target {
+        ScreenCaptureTarget::Display { id } => CurrentRecordingTarget::Screen { id: id.clone() },
+        ScreenCaptureTarget::Window { id } => CurrentRecordingTarget::Window {
+            id: id.clone(),
+            bounds: scap_targets::Window::from_id(&id)
+                .ok_or(())?
+                .display_relative_logical_bounds()
+                .ok_or(())?,
+        },
+        ScreenCaptureTarget::Area { screen, bounds } => CurrentRecordingTarget::Area {
+            screen: screen.clone(),
+            bounds: bounds.clone(),
+        },
+    };
+
+    Ok(JsonValue::new(&Some(CurrentRecording { target, mode })))
 }
 
 #[derive(Serialize, Type, tauri_specta::Event, Clone)]
@@ -1465,31 +1461,24 @@ async fn save_file_dialog(
 }
 
 #[derive(Serialize, specta::Type)]
-pub struct RecordingMetaWithType {
+pub struct RecordingMetaWithMode {
     #[serde(flatten)]
     pub inner: RecordingMeta,
-    pub r#type: RecordingType,
+    pub mode: RecordingMode,
 }
 
-impl RecordingMetaWithType {
+impl RecordingMetaWithMode {
     fn new(inner: RecordingMeta) -> Self {
         Self {
-            r#type: match &inner.inner {
-                RecordingMetaInner::Studio(_) => RecordingType::Studio,
-                RecordingMetaInner::Instant(_) => RecordingType::Instant,
+            mode: match &inner.inner {
+                RecordingMetaInner::Studio(_) => RecordingMode::Studio,
+                RecordingMetaInner::Instant(_) => RecordingMode::Instant,
             },
             inner,
         }
     }
 }
 
-#[derive(Serialize, specta::Type)]
-#[serde(rename_all = "camelCase")]
-pub enum RecordingType {
-    Studio,
-    Instant,
-}
-
 #[derive(Debug, Clone, Serialize, Deserialize, Type, PartialEq, Eq)]
 #[serde(rename_all = "lowercase")]
 pub enum FileType {
@@ -1502,15 +1491,15 @@ pub enum FileType {
 fn get_recording_meta(
     path: PathBuf,
     _file_type: FileType,
-) -> Result<RecordingMetaWithType, String> {
+) -> Result<RecordingMetaWithMode, String> {
     RecordingMeta::load_for_project(&path)
-        .map(RecordingMetaWithType::new)
+        .map(RecordingMetaWithMode::new)
         .map_err(|e| format!("Failed to load recording meta: {e}"))
 }
 
 #[tauri::command]
 #[specta::specta]
-fn list_recordings(app: AppHandle) -> Result<Vec<(PathBuf, RecordingMetaWithType)>, String> {
+fn list_recordings(app: AppHandle) -> Result<Vec<(PathBuf, RecordingMetaWithMode)>, String> {
     let recordings_dir = recordings_path(&app);
 
     if !recordings_dir.exists() {
@@ -1972,6 +1961,8 @@ pub async fn run(recording_logging_handle: LoggingHandle) {
             captions::export_captions_srt,
             target_select_overlay::open_target_select_overlays,
             target_select_overlay::close_target_select_overlays,
+            target_select_overlay::display_information,
+            target_select_overlay::get_window_icon,
         ])
         .events(tauri_specta::collect_events![
             RecordingOptionsChanged,
@@ -2241,8 +2232,16 @@ pub async fn run(recording_logging_handle: LoggingHandle) {
                             CapWindowId::Settings
                             | CapWindowId::Upgrade
                             | CapWindowId::ModeSelect => {
-                                if let Some(window) = CapWindowId::Main.get(app) {
-                                    let _ = window.show();
+                                for (label, window) in app.webview_windows() {
+                                    if let Ok(id) = CapWindowId::from_str(&label)
+                                        && matches!(
+                                            id,
+                                            CapWindowId::TargetSelectOverlay { .. }
+                                                | CapWindowId::Main
+                                        )
+                                    {
+                                        let _ = window.show();
+                                    }
                                 }
                                 return;
                             }
diff --git a/apps/desktop/src-tauri/src/recording.rs b/apps/desktop/src-tauri/src/recording.rs
index b9892b217f..aeb8fad368 100644
--- a/apps/desktop/src-tauri/src/recording.rs
+++ b/apps/desktop/src-tauri/src/recording.rs
@@ -14,15 +14,15 @@ use cap_rendering::ProjectRecordingsMeta;
 use cap_utils::{ensure_dir, spawn_actor};
 use serde::Deserialize;
 use specta::Type;
-use std::{path::PathBuf, sync::Arc, time::Duration};
+use std::{path::PathBuf, str::FromStr, sync::Arc, time::Duration};
 use tauri::{AppHandle, Manager};
 use tauri_plugin_dialog::{DialogExt, MessageDialogBuilder};
 use tauri_specta::Event;
 use tracing::{error, info};
 
 use crate::{
-    App, CurrentRecordingChanged, MutableState, NewStudioRecordingAdded, RecordingStarted,
-    RecordingStopped, VideoUploadInfo,
+    App, CurrentRecordingChanged, MutableState, NewStudioRecordingAdded, RecordingStopped,
+    VideoUploadInfo,
     audio::AppSounds,
     auth::AuthStore,
     create_screenshot,
@@ -121,6 +121,13 @@ impl InProgressRecording {
             Self::Studio { handle, .. } => handle.cancel().await,
         }
     }
+
+    pub fn mode(&self) -> RecordingMode {
+        match self {
+            Self::Instant { .. } => RecordingMode::Instant,
+            Self::Studio { .. } => RecordingMode::Studio,
+        }
+    }
 }
 
 pub enum CompletedRecording {
@@ -300,16 +307,32 @@ pub async fn start_recording(
     }
 
     // Set pending state BEFORE closing main window and starting countdown
-    {
-        let mut state = state_mtx.write().await;
-        state.set_pending_recording();
-    }
+    state_mtx
+        .write()
+        .await
+        .set_pending_recording(inputs.mode, inputs.capture_target.clone());
 
     let countdown = general_settings.and_then(|v| v.recording_countdown);
+    for (id, win) in app
+        .webview_windows()
+        .iter()
+        .filter_map(|(label, win)| CapWindowId::from_str(label).ok().map(|id| (id, win)))
+    {
+        if matches!(id, CapWindowId::TargetSelectOverlay { .. }) {
+            win.close().ok();
+        }
+    }
     let _ = ShowCapWindow::InProgressRecording { countdown }
         .show(&app)
         .await;
 
+    if let Some(window) = CapWindowId::Main.get(&app) {
+        let _ = general_settings
+            .map(|v| v.main_window_recording_start_behaviour)
+            .unwrap_or_default()
+            .perform(&window);
+    }
+
     if let Some(countdown) = countdown {
         for t in 0..countdown {
             let _ = RecordingEvent::Countdown {
@@ -336,13 +359,6 @@ pub async fn start_recording(
 
     println!("spawning actor");
 
-    if let Some(window) = CapWindowId::Main.get(&app) {
-        let _ = general_settings
-            .map(|v| v.main_window_recording_start_behaviour)
-            .unwrap_or_default()
-            .perform(&window);
-    }
-
     // done in spawn to catch panics just in case
     let spawn_actor_res = async {
         spawn_actor({
@@ -503,8 +519,6 @@ pub async fn start_recording(
 
     AppSounds::StartRecording.play();
 
-    RecordingStarted.emit(&app).ok();
-
     Ok(())
 }
 
diff --git a/apps/desktop/src-tauri/src/target_select_overlay.rs b/apps/desktop/src-tauri/src/target_select_overlay.rs
index 75165c955b..5cec112106 100644
--- a/apps/desktop/src-tauri/src/target_select_overlay.rs
+++ b/apps/desktop/src-tauri/src/target_select_overlay.rs
@@ -8,8 +8,8 @@ use std::{
 use base64::prelude::*;
 
 use crate::windows::{CapWindowId, ShowCapWindow};
-use cap_displays::{
-    DisplayId, WindowId,
+use scap_targets::{
+    Display, DisplayId, Window, WindowId,
     bounds::{LogicalBounds, PhysicalSize},
 };
 use serde::Serialize;
@@ -24,7 +24,6 @@ use tracing::error;
 pub struct TargetUnderCursor {
     display_id: Option<DisplayId>,
     window: Option<WindowUnderCursor>,
-    screen: Option<ScreenUnderCursor>,
 }
 
 #[derive(Serialize, Type, Clone)]
@@ -32,13 +31,12 @@ pub struct WindowUnderCursor {
     id: WindowId,
     app_name: String,
     bounds: LogicalBounds,
-    icon: Option<String>,
 }
 
 #[derive(Serialize, Type, Clone)]
-pub struct ScreenUnderCursor {
-    name: String,
-    physical_size: PhysicalSize,
+pub struct DisplayInformation {
+    name: Option<String>,
+    physical_size: Option<PhysicalSize>,
     refresh_rate: String,
 }
 
@@ -48,7 +46,7 @@ pub async fn open_target_select_overlays(
     app: AppHandle,
     state: tauri::State<'_, WindowFocusManager>,
 ) -> Result<(), String> {
-    let displays = cap_displays::Display::list()
+    let displays = scap_targets::Display::list()
         .into_iter()
         .map(|d| d.id())
         .collect::<Vec<_>>();
@@ -62,30 +60,22 @@ pub async fn open_target_select_overlays(
         let app = app.clone();
         async move {
             loop {
-                let display = cap_displays::Display::get_containing_cursor();
-                let window = cap_displays::Window::get_topmost_at_cursor();
-
-                let _ = TargetUnderCursor {
-                    display_id: display.map(|d| d.id()),
-                    window: window.and_then(|w| {
-                        Some(WindowUnderCursor {
-                            id: w.id(),
-                            bounds: w.display_relative_logical_bounds()?,
-                            app_name: w.owner_name()?,
-                            icon: w.app_icon().map(|bytes| {
-                                format!("data:image/png;base64,{}", BASE64_STANDARD.encode(&bytes))
-                            }),
-                        })
-                    }),
-                    screen: display.and_then(|d| {
-                        Some(ScreenUnderCursor {
-                            name: d.name().unwrap_or_default(),
-                            physical_size: d.physical_size()?,
-                            refresh_rate: d.refresh_rate().to_string(),
-                        })
-                    }),
+                {
+                    let display = scap_targets::Display::get_containing_cursor();
+                    let window = scap_targets::Window::get_topmost_at_cursor();
+
+                    let _ = TargetUnderCursor {
+                        display_id: display.map(|d| d.id()),
+                        window: window.and_then(|w| {
+                            Some(WindowUnderCursor {
+                                id: w.id(),
+                                bounds: w.display_relative_logical_bounds()?,
+                                app_name: w.owner_name()?,
+                            })
+                        }),
+                    }
+                    .emit(&app);
                 }
-                .emit(&app);
 
                 tokio::time::sleep(Duration::from_millis(50)).await;
             }
@@ -112,10 +102,7 @@ pub async fn open_target_select_overlays(
 
 #[specta::specta]
 #[tauri::command]
-pub async fn close_target_select_overlays(
-    app: AppHandle,
-    // state: tauri::State<'_, WindowFocusManager>,
-) -> Result<(), String> {
+pub async fn close_target_select_overlays(app: AppHandle) -> Result<(), String> {
     for (id, window) in app.webview_windows() {
         if let Ok(CapWindowId::TargetSelectOverlay { .. }) = CapWindowId::from_str(&id) {
             let _ = window.close();
@@ -125,6 +112,34 @@ pub async fn close_target_select_overlays(
     Ok(())
 }
 
+#[specta::specta]
+#[tauri::command]
+pub async fn get_window_icon(window_id: &str) -> Result<Option<String>, String> {
+    let window_id = window_id
+        .parse::<WindowId>()
+        .map_err(|err| format!("Invalid window ID: {}", err))?;
+
+    Ok(Window::from_id(&window_id)
+        .ok_or("Window not found")?
+        .app_icon()
+        .map(|bytes| format!("data:image/png;base64,{}", BASE64_STANDARD.encode(&bytes))))
+}
+
+#[specta::specta]
+#[tauri::command]
+pub async fn display_information(display_id: &str) -> Result<DisplayInformation, String> {
+    let display_id = display_id
+        .parse::<DisplayId>()
+        .map_err(|err| format!("Invalid display ID: {}", err))?;
+    let display = Display::from_id(&display_id).ok_or("Display not found")?;
+
+    Ok(DisplayInformation {
+        name: display.name(),
+        physical_size: display.physical_size(),
+        refresh_rate: display.refresh_rate().to_string(),
+    })
+}
+
 // Windows doesn't have a proper concept of window z-index's so we implement them in userspace :(
 #[derive(Default)]
 pub struct WindowFocusManager {
@@ -141,25 +156,25 @@ impl WindowFocusManager {
             tokio::spawn(async move {
                 let app = window.app_handle();
                 loop {
-                    let Some(cap_main) = CapWindowId::Main.get(app) else {
-                        window.close().ok();
-                        break;
-                    };
-
-                    // If the main window is minimized or not visible, close the overlay
-                    //
-                    // This is a workaround for the fact that the Cap main window
-                    // is minimized when opening settings, etc instead of it being
-                    // closed.
-                    if cap_main.is_minimized().ok().unwrap_or_default()
-                        || cap_main.is_visible().map(|v| !v).ok().unwrap_or_default()
-                    {
-                        window.close().ok();
+                    let cap_main = CapWindowId::Main.get(app);
+                    let cap_settings = CapWindowId::Settings.get(app);
+
+                    let has_cap_main = cap_main
+                        .as_ref()
+                        .and_then(|v| Some(v.is_minimized().ok()? || !v.is_visible().ok()?))
+                        .unwrap_or(true);
+                    let has_cap_settings = cap_settings
+                        .and_then(|v| Some(v.is_minimized().ok()? || !v.is_visible().ok()?))
+                        .unwrap_or(true);
+
+                    // Close the overlay if the cap main and settings are not available.
+                    if has_cap_main && has_cap_settings {
+                        window.hide().ok();
                         break;
                     }
 
                     #[cfg(windows)]
-                    {
+                    if let Some(cap_main) = cap_main {
                         let should_refocus = cap_main.is_focused().ok().unwrap_or_default()
                             || window.is_focused().unwrap_or_default();
 
@@ -170,7 +185,7 @@ impl WindowFocusManager {
                         }
                     }
 
-                    tokio::time::sleep(std::time::Duration::from_millis(300)).await;
+                    tokio::time::sleep(std::time::Duration::from_millis(400)).await;
                 }
             }),
         );
diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs
index d059271b68..6d818b153f 100644
--- a/apps/desktop/src-tauri/src/windows.rs
+++ b/apps/desktop/src-tauri/src/windows.rs
@@ -1,8 +1,8 @@
 #![allow(unused_mut)]
 #![allow(unused_imports)]
 
-use cap_displays::{Display, DisplayId};
 use futures::pin_mut;
+use scap_targets::{Display, DisplayId};
 use serde::Deserialize;
 use specta::Type;
 use std::{
@@ -235,6 +235,7 @@ impl ShowCapWindow {
                         .resizable(false)
                         .maximized(false)
                         .maximizable(false)
+                        .minimizable(false)
                         .always_on_top(true)
                         .visible_on_all_workspaces(true)
                         .content_protected(true)
@@ -252,20 +253,10 @@ impl ShowCapWindow {
                 }
             }
             Self::TargetSelectOverlay { display_id } => {
-                let Some(display) = cap_displays::Display::from_id(display_id) else {
+                let Some(display) = scap_targets::Display::from_id(display_id) else {
                     return Err(tauri::Error::WindowNotFound);
                 };
 
-                #[cfg(target_os = "macos")]
-                let position = display.raw_handle().logical_position();
-                #[cfg(target_os = "macos")]
-                let size = display.logical_size().unwrap();
-
-                #[cfg(windows)]
-                let position = display.raw_handle().physical_position().unwrap();
-                #[cfg(windows)]
-                let size = display.physical_size().unwrap();
-
                 let mut window_builder = self
                     .window_builder(
                         app,
@@ -275,15 +266,52 @@ impl ShowCapWindow {
                     .resizable(false)
                     .fullscreen(false)
                     .shadow(false)
-                    .always_on_top(cfg!(target_os = "macos"))
+                    .content_protected(true)
+                    .always_on_top(true)
                     .visible_on_all_workspaces(true)
                     .skip_taskbar(true)
-                    .inner_size(size.width(), size.height())
-                    .position(position.x(), position.y())
                     .transparent(true);
 
+                #[cfg(target_os = "macos")]
+                {
+                    let position = display.raw_handle().logical_position();
+                    let size = display.logical_size().unwrap();
+
+                    window_builder = window_builder
+                        .inner_size(size.width(), size.height())
+                        .position(position.x(), position.y());
+                }
+
+                #[cfg(windows)]
+                {
+                    window_builder = window_builder.inner_size(100.0, 100.0).position(0.0, 0.0);
+                }
+
                 let window = window_builder.build()?;
 
+                #[cfg(windows)]
+                {
+                    let position = display.raw_handle().physical_position().unwrap();
+                    let logical_size = display.logical_size().unwrap();
+                    let physical_size = display.physical_size().unwrap();
+                    use tauri::{LogicalSize, PhysicalPosition, PhysicalSize};
+                    let _ = window.set_size(LogicalSize::new(
+                        logical_size.width(),
+                        logical_size.height(),
+                    ));
+                    let _ = window.set_position(PhysicalPosition::new(position.x(), position.y()));
+                    tokio::time::sleep(std::time::Duration::from_millis(5)).await;
+
+                    let actual_physical_size = window.inner_size().unwrap();
+                    // this third time makes it work when the resulting size is wrong, god knows why
+                    if physical_size.width() != actual_physical_size.width as f64 {
+                        let _ = window.set_size(LogicalSize::new(
+                            logical_size.width(),
+                            logical_size.height(),
+                        ));
+                    }
+                }
+
                 app.state::<WindowFocusManager>()
                     .spawn(display_id, window.clone());
 
@@ -295,9 +323,16 @@ impl ShowCapWindow {
                 window
             }
             Self::Settings { page } => {
-                // Hide main window when settings window opens
-                if let Some(main) = CapWindowId::Main.get(app) {
-                    let _ = main.hide();
+                // Hide main window and target select overlays when settings window opens
+                for (label, window) in app.webview_windows() {
+                    if let Ok(id) = CapWindowId::from_str(&label)
+                        && matches!(
+                            id,
+                            CapWindowId::TargetSelectOverlay { .. } | CapWindowId::Main
+                        )
+                    {
+                        let _ = window.hide();
+                    }
                 }
 
                 self.window_builder(
diff --git a/apps/desktop/src/assets/illustrations/display.png b/apps/desktop/src/assets/illustrations/display.png
new file mode 100644
index 0000000000..1bab32779f
Binary files /dev/null and b/apps/desktop/src/assets/illustrations/display.png differ
diff --git a/apps/desktop/src/routes/(window-chrome).tsx b/apps/desktop/src/routes/(window-chrome).tsx
index 19a831b155..6483767acb 100644
--- a/apps/desktop/src/routes/(window-chrome).tsx
+++ b/apps/desktop/src/routes/(window-chrome).tsx
@@ -81,7 +81,7 @@ function Header() {
 		<header
 			class={cx(
 				"flex items-center space-x-1 h-9 select-none shrink-0 bg-gray-2",
-				isWindows ? "flex-row" : "flex-row-reverse pl-[5rem]",
+				isWindows ? "flex-row" : "flex-row-reverse pl-[4.2rem]",
 			)}
 			data-tauri-drag-region
 		>
diff --git a/apps/desktop/src/routes/(window-chrome)/(main).tsx b/apps/desktop/src/routes/(window-chrome)/(main).tsx
index f250974dfe..de8c35011d 100644
--- a/apps/desktop/src/routes/(window-chrome)/(main).tsx
+++ b/apps/desktop/src/routes/(window-chrome)/(main).tsx
@@ -477,13 +477,11 @@ function Page() {
 			<SystemAudio />
 			<div class="flex items-center space-x-1 w-full">
 				{rawOptions.mode === "instant" && !auth.data ? (
-					<>
-						<SignInButton>
-							Sign In for{" "}
-							<IconCapInstant class="invert-0 dark:invert size-[0.8rem] mx-1" />
-							Instant Mode
-						</SignInButton>
-					</>
+					<SignInButton>
+						Sign In for{" "}
+						<IconCapInstant class="invert-0 dark:invert size-[0.8rem] mx-1" />
+						Instant Mode
+					</SignInButton>
 				) : (
 					<Button
 						disabled={toggleRecording.isPending}
diff --git a/apps/desktop/src/routes/(window-chrome)/callback.template.ts b/apps/desktop/src/routes/(window-chrome)/callback.template.ts
deleted file mode 100644
index 28eeecbff8..0000000000
--- a/apps/desktop/src/routes/(window-chrome)/callback.template.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-export default `
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  <meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate">
-  <meta http-equiv="Pragma" content="no-cache">
-  <title>Cap Auth</title>
-  <style>
-    html, body {
-      width: 100%;
-      height: 100%;
-      margin: 0;
-      padding: 0;
-      font-weight: 400;
-    }
-    body {
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      font-family: sans-serif;
-      text-align: center;
-      background-color: #f8f9fa;
-    }
-    .container {
-      padding: 30px;
-      width: 100%;
-      max-width: 400px;
-      margin: 0 auto;
-    }
-    .logo {
-      width: 130px;
-      height: auto;
-      margin-bottom: 20px;
-    }
-    p {
-      font-size: 21px;
-      line-height: 26px;
-      color: #12161F;
-      margin: 0;
-    }
-    .error {
-      color: #dc2626;
-      margin-top: 12px;
-      font-size: 16px;
-    }
-  </style>
-</head>
-<body>
-  <div class="container">
-    <svg class="logo" viewBox="0 0 103 40" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect x="0.25" y="0.25" width="39.5" height="39.5" rx="7.75" fill="white"/> <rect x="0.25" y="0.25" width="39.5" height="39.5" rx="7.75" stroke="#E7EAF0" stroke-width="0.5"/> <path d="M20 36C28.8365 36 36 28.8365 36 20C36 11.1635 28.8365 4 20 4C11.1635 4 4 11.1635 4 20C4 28.8365 11.1635 36 20 36Z" fill="#4785FF"/> <path d="M20.0001 33C27.1797 33 33 27.1797 33 20.0001C33 12.8203 27.1797 7 20.0001 7C12.8203 7 7 12.8204 7 20.0001C7 27.1797 12.8204 33 20.0001 33Z" fill="#ADC9FF"/> <path d="M20.0001 30.0002C25.5229 30.0002 30.0002 25.5229 30.0002 20.0001C30.0002 14.4773 25.5229 10.0002 20.0001 10.0002C14.4773 10.0002 10.0002 14.4773 10.0002 20.0001C10.0002 25.5229 14.4773 30.0002 20.0001 30.0002Z" fill="white"/> <path d="M58.416 30.448C53.012 30.448 49.204 26.584 49.204 20.088C49.204 13.704 52.872 9.672 58.472 9.672C63.54 9.672 66.256 12.332 67.096 16.84L63.288 17.036C62.812 14.432 61.216 12.836 58.472 12.836C55.084 12.836 52.984 15.664 52.984 20.088C52.984 24.568 55.14 27.284 58.444 27.284C61.384 27.284 62.952 25.576 63.4 22.72L67.208 22.916C66.424 27.592 63.456 30.448 58.416 30.448ZM74.6451 30.336C71.5091 30.336 69.4371 28.852 69.4371 26.248C69.4371 23.672 71.0331 22.3 74.3091 21.656L79.2651 20.676C79.2651 18.576 78.2851 17.484 76.4091 17.484C74.6451 17.484 73.6931 18.296 73.3571 19.808L69.6891 19.64C70.2771 16.504 72.6851 14.712 76.4091 14.712C80.6651 14.712 82.8491 16.952 82.8491 20.928V26.36C82.8491 27.172 83.1291 27.396 83.6891 27.396H84.1651V30C83.9411 30.056 83.3531 30.112 82.8771 30.112C81.2531 30.112 80.0491 29.524 79.7411 27.676C79.0131 29.272 77.1091 30.336 74.6451 30.336ZM75.3731 27.732C77.7531 27.732 79.2651 26.22 79.2651 23.952V23.112L75.4011 23.896C73.8051 24.204 73.1611 24.876 73.1611 25.912C73.1611 27.088 73.9451 27.732 75.3731 27.732ZM86.8741 34.2V15.048H90.3181L90.3741 17.26C91.2421 15.608 92.8941 14.712 94.8541 14.712C99.1101 14.712 101.21 18.212 101.21 22.524C101.21 26.836 99.0821 30.336 94.8261 30.336C92.9221 30.336 91.2701 29.412 90.4581 27.956V34.2H86.8741ZM93.9861 27.424C96.1701 27.424 97.4861 25.604 97.4861 22.524C97.4861 19.444 96.1701 17.624 93.9861 17.624C91.8021 17.624 90.4581 19.276 90.4581 22.524C90.4581 25.772 91.7741 27.424 93.9861 27.424Z" fill="#12161F"/> </svg>
-    <p id="message">You are now signed in. Please re-open the Cap desktop app to continue.</p>
-    <div id="error-container"></div>
-  </div>
-</body>
-</html>
-`;
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main.tsx b/apps/desktop/src/routes/(window-chrome)/new-main.tsx
deleted file mode 100644
index b1ac198683..0000000000
--- a/apps/desktop/src/routes/(window-chrome)/new-main.tsx
+++ /dev/null
@@ -1,763 +0,0 @@
-import { useNavigate } from "@solidjs/router";
-import {
-	createMutation,
-	createQuery,
-	useQueryClient,
-} from "@tanstack/solid-query";
-import { getVersion } from "@tauri-apps/api/app";
-import {
-	getCurrentWindow,
-	LogicalSize,
-	primaryMonitor,
-	Window,
-} from "@tauri-apps/api/window";
-import { cx } from "cva";
-import {
-	type ComponentProps,
-	createEffect,
-	createResource,
-	createSignal,
-	onCleanup,
-	onMount,
-	Show,
-} from "solid-js";
-import { createStore, reconcile } from "solid-js/store";
-
-import Tooltip from "~/components/Tooltip";
-import { trackEvent } from "~/utils/analytics";
-import {
-	createCameraMutation,
-	createCurrentRecordingQuery,
-	createLicenseQuery,
-	getPermissions,
-	listAudioDevices,
-	listScreens,
-	listVideoDevices,
-	listWindows,
-} from "~/utils/queries";
-import {
-	type CameraInfo,
-	commands,
-	type DeviceOrModelID,
-	events,
-	type ScreenCaptureTarget,
-} from "~/utils/tauri";
-
-function getWindowSize() {
-	return {
-		width: 270,
-		height: 255,
-	};
-}
-
-const findCamera = (cameras: CameraInfo[], id: DeviceOrModelID) => {
-	return cameras.find((c) => {
-		if (!id) return false;
-		return "DeviceID" in id
-			? id.DeviceID === c.device_id
-			: id.ModelID === c.model_id;
-	});
-};
-
-export default function () {
-	const generalSettings = generalSettingsStore.createQuery();
-
-	// We do this on focus so the window doesn't get revealed when toggling the setting
-	const navigate = useNavigate();
-	createEventListener(window, "focus", () => {
-		if (generalSettings.data?.enableNewRecordingFlow === false) navigate("/");
-	});
-
-	return (
-		<RecordingOptionsProvider>
-			<Page />
-		</RecordingOptionsProvider>
-	);
-}
-
-function Page() {
-	const { rawOptions, setOptions } = useRecordingOptions();
-
-	const license = createLicenseQuery();
-
-	createUpdateCheck();
-
-	onMount(async () => {
-		// Enforce window size with multiple safeguards
-		const currentWindow = getCurrentWindow();
-
-		// We resize the window on mount as the user could be switching to the new recording flow
-		// which has a differently sized window.
-		const size = getWindowSize();
-		currentWindow.setSize(new LogicalSize(size.width, size.height));
-
-		// Check size when app regains focus
-		const unlistenFocus = currentWindow.onFocusChanged(
-			({ payload: focused }) => {
-				if (focused) {
-					const size = getWindowSize();
-
-					currentWindow.setSize(new LogicalSize(size.width, size.height));
-				}
-			},
-		);
-
-		// Listen for resize events
-		const unlistenResize = currentWindow.onResized(() => {
-			const size = getWindowSize();
-
-			currentWindow.setSize(new LogicalSize(size.width, size.height));
-		});
-
-		onCleanup(async () => {
-			(await unlistenFocus)?.();
-			(await unlistenResize)?.();
-		});
-
-		const monitor = await primaryMonitor();
-		if (!monitor) return;
-	});
-
-	createEffect(() => {
-		if (rawOptions.targetMode) commands.openTargetSelectOverlays();
-		else commands.closeTargetSelectOverlays();
-	});
-
-	const screens = createQuery(() => listScreens);
-	const windows = createQuery(() => listWindows);
-	const cameras = createQuery(() => listVideoDevices);
-	const mics = createQuery(() => listAudioDevices);
-
-	cameras.promise.then((cameras) => {
-		if (rawOptions.cameraID && findCamera(cameras, rawOptions.cameraID)) {
-			setOptions("cameraLabel", null);
-		}
-	});
-
-	mics.promise.then((mics) => {
-		if (rawOptions.micName && !mics.includes(rawOptions.micName)) {
-			setOptions("micName", null);
-		}
-	});
-
-	// these options take the raw config values and combine them with the available options,
-	// allowing us to define fallbacks if the selected options aren't actually available
-	const options = {
-		screen: () => {
-			let screen;
-
-			if (rawOptions.captureTarget.variant === "display") {
-				const screenId = rawOptions.captureTarget.id;
-				screen =
-					screens.data?.find((s) => s.id === screenId) ?? screens.data?.[0];
-			} else if (rawOptions.captureTarget.variant === "area") {
-				const screenId = rawOptions.captureTarget.screen;
-				screen =
-					screens.data?.find((s) => s.id === screenId) ?? screens.data?.[0];
-			}
-
-			return screen;
-		},
-		window: () => {
-			let win;
-
-			if (rawOptions.captureTarget.variant === "window") {
-				const windowId = rawOptions.captureTarget.id;
-				win = windows.data?.find((s) => s.id === windowId) ?? windows.data?.[0];
-			}
-
-			return win;
-		},
-		camera: () => {
-			if (!rawOptions.cameraID) return undefined;
-			return findCamera(cameras.data || [], rawOptions.cameraID);
-		},
-		micName: () => mics.data?.find((name) => name === rawOptions.micName),
-		target: (): ScreenCaptureTarget | undefined => {
-			switch (rawOptions.captureTarget.variant) {
-				case "display": {
-					const screen = options.screen();
-					if (!screen) return;
-					return { variant: "display", id: screen.id };
-				}
-				case "window": {
-					const window = options.window();
-					if (!window) return;
-					return { variant: "window", id: window.id };
-				}
-				case "area": {
-					const screen = options.screen();
-					if (!screen) return;
-					return {
-						variant: "area",
-						bounds: rawOptions.captureTarget.bounds,
-						screen: screen.id,
-					};
-				}
-			}
-		},
-	};
-
-	// if target is window and no windows are available, switch to screen capture
-	createEffect(() => {
-		const target = options.target();
-		if (!target) return;
-		const screen = options.screen();
-		if (!screen) return;
-
-		if (target.variant === "window" && windows.data?.length === 0) {
-			setOptions(
-				"captureTarget",
-				reconcile({ variant: "display", id: screen.id }),
-			);
-		}
-	});
-
-	const setMicInput = createMutation(() => ({
-		mutationFn: async (name: string | null) => {
-			await commands.setMicInput(name);
-			setOptions("micName", name);
-		},
-	}));
-
-	const setCamera = createCameraMutation();
-
-	onMount(() => {
-		if (rawOptions.cameraID && "ModelID" in rawOptions.cameraID)
-			setCamera.mutate({ ModelID: rawOptions.cameraID.ModelID });
-		else if (rawOptions.cameraID && "DeviceID" in rawOptions.cameraID)
-			setCamera.mutate({ DeviceID: rawOptions.cameraID.DeviceID });
-		else setCamera.mutate(null);
-	});
-
-	return (
-		<div class="flex justify-center flex-col p-[0.75rem] gap-[0.75rem] text-[0.875rem] font-[400] h-full text-[--text-primary]">
-			<WindowChromeHeader hideMaximize>
-				<div
-					dir={ostype() === "windows" ? "rtl" : "rtl"}
-					class="flex gap-1 items-center mx-2"
-				>
-					<Tooltip content={<span>Settings</span>}>
-						<button
-							type="button"
-							onClick={async () => {
-								await commands.showWindow({ Settings: { page: "general" } });
-								getCurrentWindow().hide();
-							}}
-							class="flex items-center justify-center w-5 h-5 -ml-[1.5px]"
-						>
-							<IconCapSettings class="text-gray-11 size-5 hover:text-gray-12" />
-						</button>
-					</Tooltip>
-					<Tooltip content={<span>Previous Recordings</span>}>
-						<button
-							type="button"
-							onClick={async () => {
-								await commands.showWindow({ Settings: { page: "recordings" } });
-								getCurrentWindow().hide();
-							}}
-							class="flex justify-center items-center w-5 h-5"
-						>
-							<IconLucideSquarePlay class="text-gray-11 size-5 hover:text-gray-12" />
-						</button>
-					</Tooltip>
-
-					<ChangelogButton />
-
-					<Show when={!license.isLoading && license.data?.type === "personal"}>
-						<button
-							type="button"
-							onClick={() => commands.showWindow("Upgrade")}
-							class="flex relative justify-center items-center w-5 h-5"
-						>
-							<IconLucideGift class="text-gray-11 size-5 hover:text-gray-12" />
-							<div
-								style={{ "background-color": "#FF4747" }}
-								class="block z-10 absolute top-0 right-0 size-1.5 rounded-full animate-bounce"
-							/>
-						</button>
-					</Show>
-
-					{import.meta.env.DEV && (
-						<button
-							type="button"
-							onClick={() => {
-								new WebviewWindow("debug", { url: "/debug" });
-							}}
-							class="flex justify-center items-center w-5 h-5"
-						>
-							<IconLucideBug class="text-gray-11 size-5 hover:text-gray-12" />
-						</button>
-					)}
-				</div>
-			</WindowChromeHeader>
-			<div class="flex flex-row items-stretch gap-1.5 w-full text-xs text-gray-11">
-				<TargetTypeButton
-					selected={rawOptions.targetMode === "display"}
-					Component={IconMdiMonitor}
-					onClick={() =>
-						setOptions("targetMode", (v) =>
-							v === "display" ? null : "display",
-						)
-					}
-					name="Display"
-				/>
-				<TargetTypeButton
-					selected={rawOptions.targetMode === "window"}
-					Component={IconLucideAppWindowMac}
-					onClick={() =>
-						setOptions("targetMode", (v) => (v === "window" ? null : "window"))
-					}
-					name="Window"
-				/>
-				<TargetTypeButton
-					selected={rawOptions.targetMode === "area"}
-					Component={IconMaterialSymbolsScreenshotFrame2Rounded}
-					onClick={() =>
-						setOptions("targetMode", (v) => (v === "area" ? null : "area"))
-					}
-					name="Area"
-				/>
-			</div>
-			<CameraSelect
-				disabled={cameras.isPending}
-				options={cameras.data ?? []}
-				value={options.camera() ?? null}
-				onChange={(c) => {
-					if (!c) setCamera.mutate(null);
-					else if (c.model_id) setCamera.mutate({ ModelID: c.model_id });
-					else setCamera.mutate({ DeviceID: c.device_id });
-				}}
-			/>
-			<MicrophoneSelect
-				disabled={mics.isPending}
-				options={mics.isPending ? [] : (mics.data ?? [])}
-				// this prevents options.micName() from suspending on initial load
-				value={
-					mics.isPending ? rawOptions.micName : (options.micName() ?? null)
-				}
-				onChange={(v) => setMicInput.mutate(v)}
-			/>
-			<SystemAudio />
-		</div>
-	);
-}
-
-function useRequestPermission() {
-	const queryClient = useQueryClient();
-
-	async function requestPermission(type: "camera" | "microphone") {
-		try {
-			if (type === "camera") {
-				await commands.resetCameraPermissions();
-			} else if (type === "microphone") {
-				await commands.resetMicrophonePermissions();
-			}
-			await commands.requestPermission(type);
-			await queryClient.refetchQueries(getPermissions);
-		} catch (error) {
-			console.error(`Failed to get ${type} permission:`, error);
-		}
-	}
-
-	return requestPermission;
-}
-
-import { createEventListener } from "@solid-primitives/event-listener";
-import { makePersisted } from "@solid-primitives/storage";
-import { CheckMenuItem, Menu, PredefinedMenuItem } from "@tauri-apps/api/menu";
-import { WebviewWindow } from "@tauri-apps/api/webviewWindow";
-import * as dialog from "@tauri-apps/plugin-dialog";
-import { type as ostype } from "@tauri-apps/plugin-os";
-import * as updater from "@tauri-apps/plugin-updater";
-import type { Component } from "solid-js";
-import { generalSettingsStore } from "~/store";
-import { apiClient } from "~/utils/web-api";
-import { WindowChromeHeader } from "./Context";
-import {
-	RecordingOptionsProvider,
-	useRecordingOptions,
-} from "./OptionsContext";
-
-let hasChecked = false;
-function createUpdateCheck() {
-	if (import.meta.env.DEV) return;
-
-	const navigate = useNavigate();
-
-	onMount(async () => {
-		if (hasChecked) return;
-		hasChecked = true;
-
-		await new Promise((res) => setTimeout(res, 1000));
-
-		const update = await updater.check();
-		if (!update) return;
-
-		const shouldUpdate = await dialog.confirm(
-			`Version ${update.version} of Cap is available, would you like to install it?`,
-			{ title: "Update Cap", okLabel: "Update", cancelLabel: "Ignore" },
-		);
-
-		if (!shouldUpdate) return;
-		navigate("/update");
-	});
-}
-
-const NO_CAMERA = "No Camera";
-
-function CameraSelect(props: {
-	disabled?: boolean;
-	options: CameraInfo[];
-	value: CameraInfo | null;
-	onChange: (camera: CameraInfo | null) => void;
-}) {
-	const currentRecording = createCurrentRecordingQuery();
-	const permissions = createQuery(() => getPermissions);
-	const requestPermission = useRequestPermission();
-
-	const permissionGranted = () =>
-		permissions?.data?.camera === "granted" ||
-		permissions?.data?.camera === "notNeeded";
-
-	const onChange = (cameraLabel: CameraInfo | null) => {
-		if (!cameraLabel && permissions?.data?.camera !== "granted")
-			return requestPermission("camera");
-
-		props.onChange(cameraLabel);
-
-		trackEvent("camera_selected", {
-			camera_name: cameraLabel?.display_name ?? null,
-			enabled: !!cameraLabel,
-		});
-	};
-
-	return (
-		<div class="flex flex-col gap-[0.25rem] items-stretch text-[--text-primary]">
-			<button
-				disabled={!!currentRecording.data || props.disabled}
-				class="flex flex-row items-center h-[2rem] px-[0.375rem] gap-[0.375rem] border rounded-lg border-gray-3 w-full disabled:text-gray-11 transition-colors KSelect"
-				onClick={() => {
-					Promise.all([
-						CheckMenuItem.new({
-							text: NO_CAMERA,
-							checked: props.value === null,
-							action: () => onChange(null),
-						}),
-						PredefinedMenuItem.new({ item: "Separator" }),
-						...props.options.map((o) =>
-							CheckMenuItem.new({
-								text: o.display_name,
-								checked: o === props.value,
-								action: () => onChange(o),
-							}),
-						),
-					])
-						.then((items) => Menu.new({ items }))
-						.then((m) => {
-							m.popup();
-						});
-				}}
-			>
-				<IconCapCamera class="text-gray-11 size-[1.25rem]" />
-				<span class="flex-1 text-left truncate">
-					{props.value?.display_name ?? NO_CAMERA}
-				</span>
-				<TargetSelectInfoPill
-					value={props.value}
-					permissionGranted={permissionGranted()}
-					requestPermission={() => requestPermission("camera")}
-					onClick={(e) => {
-						if (!props.options) return;
-						if (props.value !== null) {
-							e.stopPropagation();
-							props.onChange(null);
-						}
-					}}
-				/>
-			</button>
-		</div>
-	);
-}
-
-const NO_MICROPHONE = "No Microphone";
-
-function MicrophoneSelect(props: {
-	disabled?: boolean;
-	options: string[];
-	value: string | null;
-	onChange: (micName: string | null) => void;
-}) {
-	const DB_SCALE = 40;
-
-	const permissions = createQuery(() => getPermissions);
-	const currentRecording = createCurrentRecordingQuery();
-
-	const [dbs, setDbs] = createSignal<number | undefined>();
-	const [isInitialized, setIsInitialized] = createSignal(false);
-
-	const requestPermission = useRequestPermission();
-
-	const permissionGranted = () =>
-		permissions?.data?.microphone === "granted" ||
-		permissions?.data?.microphone === "notNeeded";
-
-	type Option = { name: string };
-
-	const handleMicrophoneChange = async (item: Option | null) => {
-		if (!props.options) return;
-		props.onChange(item ? item.name : null);
-		if (!item) setDbs();
-
-		trackEvent("microphone_selected", {
-			microphone_name: item?.name ?? null,
-			enabled: !!item,
-		});
-	};
-
-	const result = events.audioInputLevelChange.listen((dbs) => {
-		if (!props.value) setDbs();
-		else setDbs(dbs.payload);
-	});
-
-	onCleanup(() => result.then((unsub) => unsub()));
-
-	// visual audio level from 0 -> 1
-	const audioLevel = () =>
-		(1 - Math.max((dbs() ?? 0) + DB_SCALE, 0) / DB_SCALE) ** 0.5;
-
-	// Initialize audio input if needed - only once when component mounts
-	onMount(() => {
-		if (!props.value || !permissionGranted() || isInitialized()) return;
-
-		setIsInitialized(true);
-	});
-
-	return (
-		<div class="flex flex-col gap-[0.25rem] items-stretch text-[--text-primary]">
-			<button
-				disabled={!!currentRecording.data || props.disabled}
-				class="relative flex flex-row items-center h-[2rem] px-[0.375rem] gap-[0.375rem] border rounded-lg border-gray-3 w-full disabled:text-gray-11 transition-colors KSelect overflow-hidden z-10"
-				onClick={() => {
-					Promise.all([
-						CheckMenuItem.new({
-							text: NO_MICROPHONE,
-							checked: props.value === null,
-							action: () => handleMicrophoneChange(null),
-						}),
-						PredefinedMenuItem.new({ item: "Separator" }),
-						...(props.options ?? []).map((name) =>
-							CheckMenuItem.new({
-								text: name,
-								checked: name === props.value,
-								action: () => handleMicrophoneChange({ name: name }),
-							}),
-						),
-					])
-						.then((items) => Menu.new({ items }))
-						.then((m) => {
-							m.popup();
-						});
-				}}
-			>
-				<Show when={dbs()}>
-					{(_) => (
-						<div
-							class="bg-blue-100 opacity-50 left-0 inset-y-0 absolute -z-10 transition-[right] duration-100"
-							style={{
-								right: `${audioLevel() * 100}%`,
-							}}
-						/>
-					)}
-				</Show>
-				<IconCapMicrophone class="text-gray-11 size-[1.25rem]" />
-				<span class="flex-1 text-left truncate">
-					{props.value ?? NO_MICROPHONE}
-				</span>
-				<TargetSelectInfoPill
-					value={props.value}
-					permissionGranted={permissionGranted()}
-					requestPermission={() => requestPermission("microphone")}
-					onClick={(e) => {
-						if (props.value !== null) {
-							e.stopPropagation();
-							props.onChange(null);
-						}
-					}}
-				/>
-			</button>
-		</div>
-	);
-}
-
-function SystemAudio() {
-	const { rawOptions, setOptions } = useRecordingOptions();
-	const currentRecording = createCurrentRecordingQuery();
-
-	return (
-		<button
-			onClick={() => {
-				if (!rawOptions) return;
-				setOptions({ captureSystemAudio: !rawOptions.captureSystemAudio });
-			}}
-			disabled={!!currentRecording.data}
-			class="relative flex flex-row items-center h-[2rem] px-[0.375rem] gap-[0.375rem] border rounded-lg border-gray-3 w-full disabled:text-gray-11 transition-colors KSelect overflow-hidden z-10"
-		>
-			<div class="size-[1.25rem] flex items-center justify-center">
-				<IconPhMonitorBold class="text-gray-11 stroke-2 size-[1.2rem]" />
-			</div>
-			<span class="flex-1 text-left truncate">
-				{rawOptions.captureSystemAudio
-					? "Record System Audio"
-					: "No System Audio"}
-			</span>
-			<InfoPill variant={rawOptions.captureSystemAudio ? "blue" : "red"}>
-				{rawOptions.captureSystemAudio ? "On" : "Off"}
-			</InfoPill>
-		</button>
-	);
-}
-
-function TargetSelectInfoPill<T>(props: {
-	value: T | null;
-	permissionGranted: boolean;
-	requestPermission: () => void;
-	onClick: (e: MouseEvent) => void;
-}) {
-	return (
-		<InfoPill
-			variant={props.value !== null && props.permissionGranted ? "blue" : "red"}
-			onPointerDown={(e) => {
-				if (!props.permissionGranted || props.value === null) return;
-
-				e.stopPropagation();
-			}}
-			onClick={(e) => {
-				if (!props.permissionGranted) {
-					props.requestPermission();
-					return;
-				}
-
-				props.onClick(e);
-			}}
-		>
-			{!props.permissionGranted
-				? "Request Permission"
-				: props.value !== null
-					? "On"
-					: "Off"}
-		</InfoPill>
-	);
-}
-
-function InfoPill(
-	props: ComponentProps<"button"> & { variant: "blue" | "red" },
-) {
-	return (
-		<button
-			{...props}
-			type="button"
-			class={cx(
-				"px-[0.375rem] rounded-full text-[0.75rem]",
-				props.variant === "blue"
-					? "bg-blue-3 text-blue-9"
-					: "bg-red-3 text-red-9",
-			)}
-		/>
-	);
-}
-
-function ChangelogButton() {
-	const [changelogState, setChangelogState] = makePersisted(
-		createStore({
-			hasUpdate: false,
-			lastOpenedVersion: "",
-			changelogClicked: false,
-		}),
-		{ name: "changelogState" },
-	);
-
-	const [currentVersion] = createResource(() => getVersion());
-
-	const [changelogStatus] = createResource(
-		() => currentVersion(),
-		async (version) => {
-			if (!version) {
-				return { hasUpdate: false };
-			}
-			const response = await apiClient.desktop.getChangelogStatus({
-				query: { version },
-			});
-			if (response.status === 200) return response.body;
-			return null;
-		},
-	);
-
-	const handleChangelogClick = () => {
-		commands.showWindow({ Settings: { page: "changelog" } });
-		getCurrentWindow().hide();
-		const version = currentVersion();
-		if (version) {
-			setChangelogState({
-				hasUpdate: false,
-				lastOpenedVersion: version,
-				changelogClicked: true,
-			});
-		}
-	};
-
-	createEffect(() => {
-		if (changelogStatus.state === "ready" && currentVersion()) {
-			const hasUpdate = changelogStatus()?.hasUpdate || false;
-			if (
-				hasUpdate === true &&
-				changelogState.lastOpenedVersion !== currentVersion()
-			) {
-				setChangelogState({
-					hasUpdate: true,
-					lastOpenedVersion: currentVersion(),
-					changelogClicked: false,
-				});
-			}
-		}
-	});
-
-	return (
-		<Tooltip openDelay={0} content="Changelog">
-			<button
-				type="button"
-				onClick={handleChangelogClick}
-				class="flex relative justify-center items-center w-5 h-5"
-			>
-				<IconLucideBell class="text-gray-11 size-5 hover:text-gray-12" />
-				{changelogState.hasUpdate && (
-					<div
-						style={{ "background-color": "#FF4747" }}
-						class="block z-10 absolute top-0 right-0 size-1.5 rounded-full animate-bounce"
-					/>
-				)}
-			</button>
-		</Tooltip>
-	);
-}
-
-function TargetTypeButton(
-	props: {
-		selected: boolean;
-		Component: Component<ComponentProps<"svg">>;
-		name: string;
-	} & ComponentProps<"div">,
-) {
-	return (
-		<div
-			{...props}
-			class={cx(
-				"flex-1 text-center flex flex-col items-center justify-end gap-1 py-1.5 rounded-lg transition-colors duration-100",
-				props.selected && "bg-gray-3 text-white",
-			)}
-		>
-			<props.Component class="size-6" />
-			<span>{props.name}</span>
-		</div>
-	);
-}
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx
new file mode 100644
index 0000000000..5b0676b83e
--- /dev/null
+++ b/apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx
@@ -0,0 +1,83 @@
+import { createQuery } from "@tanstack/solid-query";
+import { CheckMenuItem, Menu, PredefinedMenuItem } from "@tauri-apps/api/menu";
+import { trackEvent } from "~/utils/analytics";
+import { createCurrentRecordingQuery, getPermissions } from "~/utils/queries";
+import type { CameraInfo } from "~/utils/tauri";
+import TargetSelectInfoPill from "./TargetSelectInfoPill";
+import useRequestPermission from "./useRequestPermission";
+
+const NO_CAMERA = "No Camera";
+
+export default function CameraSelect(props: {
+	disabled?: boolean;
+	options: CameraInfo[];
+	value: CameraInfo | null;
+	onChange: (camera: CameraInfo | null) => void;
+}) {
+	const currentRecording = createCurrentRecordingQuery();
+	const permissions = createQuery(() => getPermissions);
+	const requestPermission = useRequestPermission();
+
+	const permissionGranted = () =>
+		permissions?.data?.camera === "granted" ||
+		permissions?.data?.camera === "notNeeded";
+
+	const onChange = (cameraLabel: CameraInfo | null) => {
+		if (!cameraLabel && permissions?.data?.camera !== "granted")
+			return requestPermission("camera");
+
+		props.onChange(cameraLabel);
+
+		trackEvent("camera_selected", {
+			camera_name: cameraLabel?.display_name ?? null,
+			enabled: !!cameraLabel,
+		});
+	};
+
+	return (
+		<div class="flex flex-col gap-[0.25rem] items-stretch text-[--text-primary]">
+			<button
+				disabled={!!currentRecording.data || props.disabled}
+				class="cursor-default flex flex-row gap-2 items-center px-2 w-full h-9 rounded-lg transition-colors bg-gray-3 disabled:text-gray-11 KSelect"
+				onClick={() => {
+					Promise.all([
+						CheckMenuItem.new({
+							text: NO_CAMERA,
+							checked: props.value === null,
+							action: () => onChange(null),
+						}),
+						PredefinedMenuItem.new({ item: "Separator" }),
+						...props.options.map((o) =>
+							CheckMenuItem.new({
+								text: o.display_name,
+								checked: o === props.value,
+								action: () => onChange(o),
+							}),
+						),
+					])
+						.then((items) => Menu.new({ items }))
+						.then((m) => {
+							m.popup();
+						});
+				}}
+			>
+				<IconCapCamera class="text-gray-10 size-4" />
+				<p class="flex-1 text-sm text-left truncate">
+					{props.value?.display_name ?? NO_CAMERA}
+				</p>
+				<TargetSelectInfoPill
+					value={props.value}
+					permissionGranted={permissionGranted()}
+					requestPermission={() => requestPermission("camera")}
+					onClick={(e) => {
+						if (!props.options) return;
+						if (props.value !== null) {
+							e.stopPropagation();
+							props.onChange(null);
+						}
+					}}
+				/>
+			</button>
+		</div>
+	);
+}
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/ChangeLogButton.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/ChangeLogButton.tsx
new file mode 100644
index 0000000000..755e749c5c
--- /dev/null
+++ b/apps/desktop/src/routes/(window-chrome)/new-main/ChangeLogButton.tsx
@@ -0,0 +1,84 @@
+import { makePersisted } from "@solid-primitives/storage";
+import { getVersion } from "@tauri-apps/api/app";
+import { getCurrentWindow } from "@tauri-apps/api/window";
+import { createEffect, createResource } from "solid-js";
+import { createStore } from "solid-js/store";
+import Tooltip from "~/components/Tooltip";
+import { commands } from "~/utils/tauri";
+import { apiClient } from "~/utils/web-api";
+
+const ChangelogButton = () => {
+	const [changelogState, setChangelogState] = makePersisted(
+		createStore({
+			hasUpdate: false,
+			lastOpenedVersion: "",
+			changelogClicked: false,
+		}),
+		{ name: "changelogState" },
+	);
+
+	const [currentVersion] = createResource(() => getVersion());
+
+	const [changelogStatus] = createResource(
+		() => currentVersion(),
+		async (version) => {
+			if (!version) {
+				return { hasUpdate: false };
+			}
+			const response = await apiClient.desktop.getChangelogStatus({
+				query: { version },
+			});
+			if (response.status === 200) return response.body;
+			return null;
+		},
+	);
+
+	const handleChangelogClick = () => {
+		commands.showWindow({ Settings: { page: "changelog" } });
+		getCurrentWindow().hide();
+		const version = currentVersion();
+		if (version) {
+			setChangelogState({
+				hasUpdate: false,
+				lastOpenedVersion: version,
+				changelogClicked: true,
+			});
+		}
+	};
+
+	createEffect(() => {
+		if (changelogStatus.state === "ready" && currentVersion()) {
+			const hasUpdate = changelogStatus()?.hasUpdate || false;
+			if (
+				hasUpdate === true &&
+				changelogState.lastOpenedVersion !== currentVersion()
+			) {
+				setChangelogState({
+					hasUpdate: true,
+					lastOpenedVersion: currentVersion(),
+					changelogClicked: false,
+				});
+			}
+		}
+	});
+
+	return (
+		<Tooltip openDelay={0} content="Changelog">
+			<button
+				type="button"
+				onClick={handleChangelogClick}
+				class="flex relative justify-center items-center size-5"
+			>
+				<IconLucideBell class="transition-colors text-gray-11 size-4 hover:text-gray-12" />
+				{changelogState.hasUpdate && (
+					<div
+						style={{ "background-color": "#FF4747" }}
+						class="block z-10 absolute top-0 right-0 size-1.5 rounded-full animate-bounce"
+					/>
+				)}
+			</button>
+		</Tooltip>
+	);
+};
+
+export default ChangelogButton;
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/InfoPill.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/InfoPill.tsx
new file mode 100644
index 0000000000..f6ab0811c2
--- /dev/null
+++ b/apps/desktop/src/routes/(window-chrome)/new-main/InfoPill.tsx
@@ -0,0 +1,17 @@
+import { cx } from "cva";
+import type { ComponentProps } from "solid-js";
+
+export default function InfoPill(
+	props: ComponentProps<"button"> & { variant: "blue" | "red" },
+) {
+	return (
+		<button
+			{...props}
+			type="button"
+			class={cx(
+				"px-2 py-0.5 rounded-full text-white text-[11px]",
+				props.variant === "blue" ? "bg-blue-9" : "bg-red-9",
+			)}
+		/>
+	);
+}
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/MicrophoneSelect.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/MicrophoneSelect.tsx
new file mode 100644
index 0000000000..33a6794f00
--- /dev/null
+++ b/apps/desktop/src/routes/(window-chrome)/new-main/MicrophoneSelect.tsx
@@ -0,0 +1,120 @@
+import { createQuery } from "@tanstack/solid-query";
+import { CheckMenuItem, Menu, PredefinedMenuItem } from "@tauri-apps/api/menu";
+import { createSignal, onCleanup, onMount, Show } from "solid-js";
+import { trackEvent } from "~/utils/analytics";
+import { createCurrentRecordingQuery, getPermissions } from "~/utils/queries";
+import { events } from "~/utils/tauri";
+import TargetSelectInfoPill from "./TargetSelectInfoPill";
+import useRequestPermission from "./useRequestPermission";
+
+const NO_MICROPHONE = "No Microphone";
+
+export default function MicrophoneSelect(props: {
+	disabled?: boolean;
+	options: string[];
+	value: string | null;
+	onChange: (micName: string | null) => void;
+}) {
+	const DB_SCALE = 40;
+
+	const permissions = createQuery(() => getPermissions);
+	const currentRecording = createCurrentRecordingQuery();
+
+	const [dbs, setDbs] = createSignal<number | undefined>();
+	const [isInitialized, setIsInitialized] = createSignal(false);
+
+	const requestPermission = useRequestPermission();
+
+	const permissionGranted = () =>
+		permissions?.data?.microphone === "granted" ||
+		permissions?.data?.microphone === "notNeeded";
+
+	type Option = { name: string };
+
+	const handleMicrophoneChange = async (item: Option | null) => {
+		if (!props.options) return;
+		props.onChange(item ? item.name : null);
+		if (!item) setDbs();
+
+		trackEvent("microphone_selected", {
+			microphone_name: item?.name ?? null,
+			enabled: !!item,
+		});
+	};
+
+	const result = events.audioInputLevelChange.listen((dbs) => {
+		if (!props.value) setDbs();
+		else setDbs(dbs.payload);
+	});
+
+	onCleanup(() => result.then((unsub) => unsub()));
+
+	// visual audio level from 0 -> 1
+	const audioLevel = () =>
+		(1 - Math.max((dbs() ?? 0) + DB_SCALE, 0) / DB_SCALE) ** 0.5;
+
+	// Initialize audio input if needed - only once when component mounts
+	onMount(() => {
+		if (!props.value || !permissionGranted() || isInitialized()) return;
+
+		setIsInitialized(true);
+		// Ensure the selected microphone is activated so levels flow in
+		void handleMicrophoneChange({ name: props.value });
+	});
+
+	return (
+		<div class="flex flex-col gap-[0.25rem] items-stretch text-[--text-primary]">
+			<button
+				disabled={!!currentRecording.data || props.disabled}
+				class="z-10 relative cursor-default flex flex-row gap-2 items-center px-2 w-full h-9 rounded-lg overflow-hidden transition-colors bg-gray-3 disabled:text-gray-11 KSelect"
+				onClick={() => {
+					Promise.all([
+						CheckMenuItem.new({
+							text: NO_MICROPHONE,
+							checked: props.value === null,
+							action: () => handleMicrophoneChange(null),
+						}),
+						PredefinedMenuItem.new({ item: "Separator" }),
+						...(props.options ?? []).map((name) =>
+							CheckMenuItem.new({
+								text: name,
+								checked: name === props.value,
+								action: () => handleMicrophoneChange({ name: name }),
+							}),
+						),
+					])
+						.then((items) => Menu.new({ items }))
+						.then((m) => {
+							m.popup();
+						});
+				}}
+			>
+				<Show when={props.value !== null && dbs()}>
+					{(_) => (
+						<div
+							class="bg-blue-7 opacity-50 left-0 inset-y-0 absolute transition-[right] duration-100 -z-10"
+							style={{
+								right: `${audioLevel() * 100}%`,
+							}}
+						/>
+					)}
+				</Show>
+				<IconCapMicrophone class="text-gray-10 size-4" />
+				<p class="flex-1 text-sm text-left truncate">
+					{props.value ?? NO_MICROPHONE}
+				</p>
+				<TargetSelectInfoPill
+					value={props.value}
+					permissionGranted={permissionGranted()}
+					requestPermission={() => requestPermission("microphone")}
+					onClick={(e) => {
+						if (props.value !== null) {
+							e.stopPropagation();
+							props.onChange(null);
+						}
+					}}
+				/>
+			</button>
+		</div>
+	);
+}
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/SystemAudio.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/SystemAudio.tsx
new file mode 100644
index 0000000000..b7b948f359
--- /dev/null
+++ b/apps/desktop/src/routes/(window-chrome)/new-main/SystemAudio.tsx
@@ -0,0 +1,29 @@
+import { createCurrentRecordingQuery } from "~/utils/queries";
+import { useRecordingOptions } from "../OptionsContext";
+import InfoPill from "./InfoPill";
+
+export default function SystemAudio() {
+	const { rawOptions, setOptions } = useRecordingOptions();
+	const currentRecording = createCurrentRecordingQuery();
+
+	return (
+		<button
+			onClick={() => {
+				if (!rawOptions) return;
+				setOptions({ captureSystemAudio: !rawOptions.captureSystemAudio });
+			}}
+			disabled={!!currentRecording.data}
+			class="curosr-default flex flex-row gap-2 items-center px-2 w-full h-9 rounded-lg transition-colors bg-gray-3 disabled:text-gray-11 KSelect"
+		>
+			<IconPhMonitorBold class="text-gray-10 size-4" />
+			<p class="flex-1 text-sm text-left truncate">
+				{rawOptions.captureSystemAudio
+					? "Record System Audio"
+					: "No System Audio"}
+			</p>
+			<InfoPill variant={rawOptions.captureSystemAudio ? "blue" : "red"}>
+				{rawOptions.captureSystemAudio ? "On" : "Off"}
+			</InfoPill>
+		</button>
+	);
+}
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/TargetSelectInfoPill.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/TargetSelectInfoPill.tsx
new file mode 100644
index 0000000000..55aceee4e1
--- /dev/null
+++ b/apps/desktop/src/routes/(window-chrome)/new-main/TargetSelectInfoPill.tsx
@@ -0,0 +1,33 @@
+import InfoPill from "./InfoPill";
+
+export default function TargetSelectInfoPill<T>(props: {
+	value: T | null;
+	permissionGranted: boolean;
+	requestPermission: () => void;
+	onClick: (e: MouseEvent) => void;
+}) {
+	return (
+		<InfoPill
+			variant={props.value !== null && props.permissionGranted ? "blue" : "red"}
+			onPointerDown={(e) => {
+				if (!props.permissionGranted || props.value === null) return;
+
+				e.stopPropagation();
+			}}
+			onClick={(e) => {
+				if (!props.permissionGranted) {
+					props.requestPermission();
+					return;
+				}
+
+				props.onClick(e);
+			}}
+		>
+			{!props.permissionGranted
+				? "Request Permission"
+				: props.value !== null
+					? "On"
+					: "Off"}
+		</InfoPill>
+	);
+}
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/TargetTypeButton.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/TargetTypeButton.tsx
new file mode 100644
index 0000000000..a7c4e2ac30
--- /dev/null
+++ b/apps/desktop/src/routes/(window-chrome)/new-main/TargetTypeButton.tsx
@@ -0,0 +1,32 @@
+import { cx } from "cva";
+import type { Component, ComponentProps } from "solid-js";
+
+function TargetTypeButton(
+	props: {
+		selected: boolean;
+		Component: Component<ComponentProps<"svg">>;
+		name: string;
+	} & ComponentProps<"div">,
+) {
+	return (
+		<div
+			{...props}
+			class={cx(
+				"flex-1 text-center hover:bg-gray-4 bg-gray-3 flex flex-col ring-offset-gray-1 ring-offset-2 items-center justify-end gap-2 py-1.5 rounded-lg transition-all",
+				props.selected
+					? "bg-gray-3 text-white ring-blue-9 ring-1"
+					: "ring-transparent ring-0",
+			)}
+		>
+			<props.Component
+				class={cx(
+					"size-6 transition-colors",
+					props.selected ? "text-gray-12" : "text-gray-9",
+				)}
+			/>
+			<p class="text-xs text-gray-12">{props.name}</p>
+		</div>
+	);
+}
+
+export default TargetTypeButton;
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/index.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/index.tsx
new file mode 100644
index 0000000000..f16a7f4f8d
--- /dev/null
+++ b/apps/desktop/src/routes/(window-chrome)/new-main/index.tsx
@@ -0,0 +1,436 @@
+import { Button } from "@cap/ui-solid";
+import { createEventListener } from "@solid-primitives/event-listener";
+import { useNavigate } from "@solidjs/router";
+import { createMutation, useQuery } from "@tanstack/solid-query";
+import { listen } from "@tauri-apps/api/event";
+import {
+	getAllWebviewWindows,
+	WebviewWindow,
+} from "@tauri-apps/api/webviewWindow";
+import {
+	getCurrentWindow,
+	LogicalSize,
+	primaryMonitor,
+} from "@tauri-apps/api/window";
+import * as dialog from "@tauri-apps/plugin-dialog";
+import { type as ostype } from "@tauri-apps/plugin-os";
+import * as updater from "@tauri-apps/plugin-updater";
+import { cx } from "cva";
+import {
+	createEffect,
+	ErrorBoundary,
+	onCleanup,
+	onMount,
+	Show,
+	Suspense,
+} from "solid-js";
+import { reconcile } from "solid-js/store";
+import { addEventListener } from "solid-js/web";
+import Tooltip from "~/components/Tooltip";
+import { generalSettingsStore } from "~/store";
+import { createSignInMutation } from "~/utils/auth";
+import {
+	createCameraMutation,
+	createLicenseQuery,
+	listAudioDevices,
+	listScreens,
+	listVideoDevices,
+	listWindows,
+} from "~/utils/queries";
+import {
+	type CameraInfo,
+	commands,
+	type DeviceOrModelID,
+	type ScreenCaptureTarget,
+} from "~/utils/tauri";
+import { WindowChromeHeader } from "../Context";
+import {
+	RecordingOptionsProvider,
+	useRecordingOptions,
+} from "../OptionsContext";
+import CameraSelect from "./CameraSelect";
+import ChangelogButton from "./ChangeLogButton";
+import MicrophoneSelect from "./MicrophoneSelect";
+import SystemAudio from "./SystemAudio";
+import TargetTypeButton from "./TargetTypeButton";
+
+function getWindowSize() {
+	return {
+		width: 270,
+		height: 256,
+	};
+}
+
+const findCamera = (cameras: CameraInfo[], id: DeviceOrModelID) => {
+	return cameras.find((c) => {
+		if (!id) return false;
+		return "DeviceID" in id
+			? id.DeviceID === c.device_id
+			: id.ModelID === c.model_id;
+	});
+};
+
+export default function () {
+	const generalSettings = generalSettingsStore.createQuery();
+
+	// We do this on focus so the window doesn't get revealed when toggling the setting
+	const navigate = useNavigate();
+	createEventListener(window, "focus", () => {
+		if (generalSettings.data?.enableNewRecordingFlow === false) navigate("/");
+	});
+
+	return (
+		<RecordingOptionsProvider>
+			<Page />
+		</RecordingOptionsProvider>
+	);
+}
+
+let hasChecked = false;
+function createUpdateCheck() {
+	if (import.meta.env.DEV) return;
+
+	const navigate = useNavigate();
+
+	onMount(async () => {
+		if (hasChecked) return;
+		hasChecked = true;
+
+		await new Promise((res) => setTimeout(res, 1000));
+
+		const update = await updater.check();
+		if (!update) return;
+
+		const shouldUpdate = await dialog.confirm(
+			`Version ${update.version} of Cap is available, would you like to install it?`,
+			{ title: "Update Cap", okLabel: "Update", cancelLabel: "Ignore" },
+		);
+
+		if (!shouldUpdate) return;
+		navigate("/update");
+	});
+}
+
+function Page() {
+	const { rawOptions, setOptions } = useRecordingOptions();
+
+	createUpdateCheck();
+
+	onMount(async () => {
+		// We don't want the target select overlay on launch
+		setOptions({ targetMode: null });
+
+		// Enforce window size with multiple safeguards
+		const currentWindow = getCurrentWindow();
+
+		// We resize the window on mount as the user could be switching to the new recording flow
+		// which has a differently sized window.
+		const size = getWindowSize();
+		currentWindow.setSize(new LogicalSize(size.width, size.height));
+
+		// Check size when app regains focus
+		const unlistenFocus = currentWindow.onFocusChanged(
+			({ payload: focused }) => {
+				if (focused) {
+					const size = getWindowSize();
+
+					currentWindow.setSize(new LogicalSize(size.width, size.height));
+				}
+			},
+		);
+
+		// Listen for resize events
+		const unlistenResize = currentWindow.onResized(() => {
+			const size = getWindowSize();
+
+			currentWindow.setSize(new LogicalSize(size.width, size.height));
+		});
+
+		onCleanup(async () => {
+			(await unlistenFocus)?.();
+			(await unlistenResize)?.();
+		});
+
+		const monitor = await primaryMonitor();
+		if (!monitor) return;
+	});
+
+	createEffect(() => {
+		if (rawOptions.targetMode) commands.openTargetSelectOverlays();
+		else commands.closeTargetSelectOverlays();
+	});
+
+	const screens = useQuery(() => listScreens);
+	const windows = useQuery(() => listWindows);
+	const cameras = useQuery(() => listVideoDevices);
+	const mics = useQuery(() => listAudioDevices);
+
+	cameras.promise.then((cameras) => {
+		if (rawOptions.cameraID && findCamera(cameras, rawOptions.cameraID)) {
+			setOptions("cameraLabel", null);
+		}
+	});
+
+	mics.promise.then((mics) => {
+		if (rawOptions.micName && !mics.includes(rawOptions.micName)) {
+			setOptions("micName", null);
+		}
+	});
+
+	// these options take the raw config values and combine them with the available options,
+	// allowing us to define fallbacks if the selected options aren't actually available
+	const options = {
+		screen: () => {
+			let screen;
+
+			if (rawOptions.captureTarget.variant === "display") {
+				const screenId = rawOptions.captureTarget.id;
+				screen =
+					screens.data?.find((s) => s.id === screenId) ?? screens.data?.[0];
+			} else if (rawOptions.captureTarget.variant === "area") {
+				const screenId = rawOptions.captureTarget.screen;
+				screen =
+					screens.data?.find((s) => s.id === screenId) ?? screens.data?.[0];
+			}
+
+			return screen;
+		},
+		window: () => {
+			let win;
+
+			if (rawOptions.captureTarget.variant === "window") {
+				const windowId = rawOptions.captureTarget.id;
+				win = windows.data?.find((s) => s.id === windowId) ?? windows.data?.[0];
+			}
+
+			return win;
+		},
+		camera: () => {
+			if (!rawOptions.cameraID) return undefined;
+			return findCamera(cameras.data || [], rawOptions.cameraID);
+		},
+		micName: () => mics.data?.find((name) => name === rawOptions.micName),
+		target: (): ScreenCaptureTarget | undefined => {
+			switch (rawOptions.captureTarget.variant) {
+				case "display": {
+					const screen = options.screen();
+					if (!screen) return;
+					return { variant: "display", id: screen.id };
+				}
+				case "window": {
+					const window = options.window();
+					if (!window) return;
+					return { variant: "window", id: window.id };
+				}
+				case "area": {
+					const screen = options.screen();
+					if (!screen) return;
+					return {
+						variant: "area",
+						bounds: rawOptions.captureTarget.bounds,
+						screen: screen.id,
+					};
+				}
+			}
+		},
+	};
+
+	// if target is window and no windows are available, switch to screen capture
+	createEffect(() => {
+		const target = options.target();
+		if (!target) return;
+		const screen = options.screen();
+		if (!screen) return;
+
+		if (target.variant === "window" && windows.data?.length === 0) {
+			setOptions(
+				"captureTarget",
+				reconcile({ variant: "display", id: screen.id }),
+			);
+		}
+	});
+
+	const setMicInput = createMutation(() => ({
+		mutationFn: async (name: string | null) => {
+			await commands.setMicInput(name);
+			setOptions("micName", name);
+		},
+	}));
+
+	const setCamera = createCameraMutation();
+
+	onMount(() => {
+		if (rawOptions.cameraID && "ModelID" in rawOptions.cameraID)
+			setCamera.mutate({ ModelID: rawOptions.cameraID.ModelID });
+		else if (rawOptions.cameraID && "DeviceID" in rawOptions.cameraID)
+			setCamera.mutate({ DeviceID: rawOptions.cameraID.DeviceID });
+		else setCamera.mutate(null);
+	});
+
+	const license = createLicenseQuery();
+
+	const signIn = createSignInMutation();
+
+	const startSignInCleanup = listen("start-sign-in", async () => {
+		const abort = new AbortController();
+		for (const win of await getAllWebviewWindows()) {
+			if (win.label.startsWith("target-select-overlay")) {
+				await win.hide();
+			}
+		}
+
+		await signIn.mutateAsync(abort).catch(() => {});
+
+		for (const win of await getAllWebviewWindows()) {
+			if (win.label.startsWith("target-select-overlay")) {
+				await win.show();
+			}
+		}
+	});
+	onCleanup(() => startSignInCleanup.then((cb) => cb()));
+
+	return (
+		<div class="flex relative justify-center flex-col px-3 gap-2 h-full text-[--text-primary]">
+			<WindowChromeHeader hideMaximize>
+				<div
+					dir={ostype() === "windows" ? "rtl" : "rtl"}
+					class="flex gap-1 items-center mx-2 w-full"
+					data-tauri-drag-region
+				>
+					<div class="flex gap-1 items-center" data-tauri-drag-region>
+						<Tooltip content={<span>Settings</span>}>
+							<button
+								type="button"
+								onClick={async () => {
+									await commands.showWindow({ Settings: { page: "general" } });
+									getCurrentWindow().hide();
+								}}
+								class="flex items-center justify-center size-5 -ml-[1.5px]"
+							>
+								<IconCapSettings class="transition-colors text-gray-11 size-4 hover:text-gray-12" />
+							</button>
+						</Tooltip>
+						<Tooltip content={<span>Previous Recordings</span>}>
+							<button
+								type="button"
+								onClick={async () => {
+									await commands.showWindow({
+										Settings: { page: "recordings" },
+									});
+									getCurrentWindow().hide();
+								}}
+								class="flex justify-center items-center size-5"
+							>
+								<IconLucideSquarePlay class="transition-colors text-gray-11 size-4 hover:text-gray-12" />
+							</button>
+						</Tooltip>
+						<ChangelogButton />
+						{import.meta.env.DEV && (
+							<button
+								type="button"
+								onClick={() => {
+									new WebviewWindow("debug", { url: "/debug" });
+								}}
+								class="flex justify-center items-center"
+							>
+								<IconLucideBug class="transition-colors text-gray-11 size-4 hover:text-gray-12" />
+							</button>
+						)}
+					</div>
+					<div class="flex-1" data-tauri-drag-region />
+					<ErrorBoundary fallback={<></>}>
+						<Suspense>
+							<span
+								onClick={async () => {
+									if (license.data?.type !== "pro") {
+										await commands.showWindow("Upgrade");
+									}
+								}}
+								class={cx(
+									"text-[0.6rem] rounded-full px-1.5 py-0.5",
+									license.data?.type === "pro"
+										? "bg-[--blue-300] text-gray-1 dark:text-gray-12"
+										: "bg-gray-4 cursor-pointer hover:bg-gray-5",
+								)}
+							>
+								{license.data?.type === "commercial"
+									? "Commercial"
+									: license.data?.type === "pro"
+										? "Pro"
+										: "Personal"}
+							</span>
+						</Suspense>
+					</ErrorBoundary>
+				</div>
+			</WindowChromeHeader>
+			<Show when={signIn.isPending}>
+				<div class="bg-gray-1 absolute inset-0 flex items-center justify-center animate-in fade-in">
+					<div class="flex flex-col items-center justify-center gap-4">
+						<span>Singning In...</span>
+
+						<Button
+							onClick={() => {
+								signIn.variables?.abort();
+								signIn.reset();
+							}}
+							variant="secondary"
+							class="w-full"
+						>
+							Cancel Sign In
+						</Button>
+					</div>
+				</div>
+			</Show>
+			<div class="flex flex-row gap-2 items-stretch w-full text-xs text-gray-11">
+				<TargetTypeButton
+					selected={rawOptions.targetMode === "display"}
+					Component={IconMdiMonitor}
+					onClick={() =>
+						setOptions("targetMode", (v) =>
+							v === "display" ? null : "display",
+						)
+					}
+					name="Display"
+				/>
+				<TargetTypeButton
+					selected={rawOptions.targetMode === "window"}
+					Component={IconLucideAppWindowMac}
+					onClick={() =>
+						setOptions("targetMode", (v) => (v === "window" ? null : "window"))
+					}
+					name="Window"
+				/>
+				<TargetTypeButton
+					selected={rawOptions.targetMode === "area"}
+					Component={IconMaterialSymbolsScreenshotFrame2Rounded}
+					onClick={() =>
+						setOptions("targetMode", (v) => (v === "area" ? null : "area"))
+					}
+					name="Area"
+				/>
+			</div>
+			<div class="space-y-2">
+				<CameraSelect
+					disabled={cameras.isPending}
+					options={cameras.data ?? []}
+					value={options.camera() ?? null}
+					onChange={(c) => {
+						if (!c) setCamera.mutate(null);
+						else if (c.model_id) setCamera.mutate({ ModelID: c.model_id });
+						else setCamera.mutate({ DeviceID: c.device_id });
+					}}
+				/>
+				<MicrophoneSelect
+					disabled={mics.isPending}
+					options={mics.isPending ? [] : (mics.data ?? [])}
+					// this prevents options.micName() from suspending on initial load
+					value={
+						mics.isPending ? rawOptions.micName : (options.micName() ?? null)
+					}
+					onChange={(v) => setMicInput.mutate(v)}
+				/>
+				<SystemAudio />
+			</div>
+		</div>
+	);
+}
diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/useRequestPermission.ts b/apps/desktop/src/routes/(window-chrome)/new-main/useRequestPermission.ts
new file mode 100644
index 0000000000..b970e1ab29
--- /dev/null
+++ b/apps/desktop/src/routes/(window-chrome)/new-main/useRequestPermission.ts
@@ -0,0 +1,23 @@
+import { useQueryClient } from "@tanstack/solid-query";
+import { getPermissions } from "~/utils/queries";
+import { commands } from "~/utils/tauri";
+
+export default function useRequestPermission() {
+	const queryClient = useQueryClient();
+
+	async function requestPermission(type: "camera" | "microphone") {
+		try {
+			if (type === "camera") {
+				await commands.resetCameraPermissions();
+			} else if (type === "microphone") {
+				await commands.resetMicrophonePermissions();
+			}
+			await commands.requestPermission(type);
+			await queryClient.refetchQueries(getPermissions);
+		} catch (error) {
+			console.error(`Failed to get ${type} permission:`, error);
+		}
+	}
+
+	return requestPermission;
+}
diff --git a/apps/desktop/src/routes/(window-chrome)/settings/experimental.tsx b/apps/desktop/src/routes/(window-chrome)/settings/experimental.tsx
index fd7c12571b..d12b1d8b32 100644
--- a/apps/desktop/src/routes/(window-chrome)/settings/experimental.tsx
+++ b/apps/desktop/src/routes/(window-chrome)/settings/experimental.tsx
@@ -25,7 +25,7 @@ function Inner(props: { initialStore: GeneralSettingsStore | null }) {
 			enableNativeCameraPreview: false,
 			enableNewRecordingFlow: false,
 			autoZoomOnClicks: false,
-			customCursorCapture2: true,
+			custom_cursor_capture2: true,
 		},
 	);
 
@@ -58,9 +58,9 @@ function Inner(props: { initialStore: GeneralSettingsStore | null }) {
 							<ToggleSetting
 								label="Custom cursor capture in Studio Mode"
 								description="Studio Mode recordings will capture cursor state separately for customisation (size, smoothing) in the editor. Currently experimental as cursor events may not be captured accurately."
-								value={!!settings.customCursorCapture2}
+								value={!!settings.custom_cursor_capture2}
 								onChange={(value) =>
-									handleChange("customCursorCapture2", value)
+									handleChange("custom_cursor_capture2", value)
 								}
 							/>
 							<ToggleSetting
@@ -84,21 +84,19 @@ function Inner(props: { initialStore: GeneralSettingsStore | null }) {
 									);
 								}}
 							/>
-							{import.meta.env.DEV && (
-								<ToggleSetting
-									label="New recording flow"
-									description="New and improved flow for starting a recording! You may need to restart the app for this to take effect."
-									value={!!settings.enableNewRecordingFlow}
-									onChange={(value) => {
-										handleChange("enableNewRecordingFlow", value);
-										// This is bad code, but I just want the UI to not jank and can't seem to find the issue.
-										setTimeout(
-											() => window.scrollTo({ top: 0, behavior: "instant" }),
-											5,
-										);
-									}}
-								/>
-							)}
+							<ToggleSetting
+								label="New recording flow"
+								description="New and improved flow for starting a recording! You may need to restart the app for this to take effect."
+								value={!!settings.enableNewRecordingFlow}
+								onChange={(value) => {
+									handleChange("enableNewRecordingFlow", value);
+									// This is bad code, but I just want the UI to not jank and can't seem to find the issue.
+									setTimeout(
+										() => window.scrollTo({ top: 0, behavior: "instant" }),
+										5,
+									);
+								}}
+							/>
 						</div>
 					</div>
 				</div>
diff --git a/apps/desktop/src/routes/(window-chrome)/settings/general.tsx b/apps/desktop/src/routes/(window-chrome)/settings/general.tsx
index b3c691803e..1b07be1c39 100644
--- a/apps/desktop/src/routes/(window-chrome)/settings/general.tsx
+++ b/apps/desktop/src/routes/(window-chrome)/settings/general.tsx
@@ -117,7 +117,7 @@ function Inner(props: { initialStore: GeneralSettingsStore | null }) {
 			enableNativeCameraPreview: false,
 			enableNewRecordingFlow: false,
 			autoZoomOnClicks: false,
-			customCursorCapture2: true,
+			custom_cursor_capture2: true,
 		},
 	);
 
diff --git a/apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx b/apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx
index 1d423c1508..ef7690c25c 100644
--- a/apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx
+++ b/apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx
@@ -16,17 +16,16 @@ import {
 	createSignal,
 	For,
 	type JSX,
-	onCleanup,
 	type ParentProps,
 	Show,
 } from "solid-js";
 
 import { trackEvent } from "~/utils/analytics";
 import { createTauriEventListener } from "~/utils/createEventListener";
-import { commands, events, type RecordingMetaWithType } from "~/utils/tauri";
+import { commands, events, type RecordingMetaWithMode } from "~/utils/tauri";
 
 type Recording = {
-	meta: RecordingMetaWithType;
+	meta: RecordingMetaWithMode;
 	path: string;
 	prettyName: string;
 	thumbnailPath: string;
@@ -87,7 +86,7 @@ export default function Recordings() {
 			return recordings.data;
 		}
 		return recordings.data.filter(
-			(recording) => recording.meta.type === activeTab(),
+			(recording) => recording.meta.mode === activeTab(),
 		);
 	});
 
@@ -178,9 +177,9 @@ function RecordingItem(props: {
 	onCopyVideoToClipboard: () => void;
 }) {
 	const [imageExists, setImageExists] = createSignal(true);
-	const type = () => props.recording.meta.type;
+	const mode = () => props.recording.meta.mode;
 	const firstLetterUpperCase = () =>
-		type().charAt(0).toUpperCase() + type().slice(1);
+		mode().charAt(0).toUpperCase() + mode().slice(1);
 
 	const queryClient = useQueryClient();
 
@@ -205,10 +204,10 @@ function RecordingItem(props: {
 					<div
 						class={cx(
 							"px-2 py-0.5 flex items-center gap-1.5 font-medium text-[11px] text-gray-12 rounded-full w-fit",
-							type() === "instant" ? "bg-blue-100" : "bg-gray-3",
+							mode() === "instant" ? "bg-blue-100" : "bg-gray-3",
 						)}
 					>
-						{type() === "instant" ? (
+						{mode() === "instant" ? (
 							<IconCapInstant class="invert size-2.5 dark:invert-0" />
 						) : (
 							<IconCapFilmCut class="invert size-2.5 dark:invert-0" />
@@ -218,7 +217,7 @@ function RecordingItem(props: {
 				</div>
 			</div>
 			<div class="flex gap-2 items-center">
-				<Show when={type() === "studio"}>
+				<Show when={mode() === "studio"}>
 					<Show when={props.recording.meta.sharing}>
 						{(sharing) => (
 							<TooltipIconButton
@@ -236,7 +235,7 @@ function RecordingItem(props: {
 						<IconLucideEdit class="size-4" />
 					</TooltipIconButton>
 				</Show>
-				<Show when={type() === "instant"}>
+				<Show when={mode() === "instant"}>
 					{(_) => {
 						const reupload = createMutation(() => ({
 							mutationFn: () => {
diff --git a/apps/desktop/src/routes/editor/ConfigSidebar.tsx b/apps/desktop/src/routes/editor/ConfigSidebar.tsx
index 31dab706b7..4ba780823e 100644
--- a/apps/desktop/src/routes/editor/ConfigSidebar.tsx
+++ b/apps/desktop/src/routes/editor/ConfigSidebar.tsx
@@ -1992,7 +1992,7 @@ function ZoomSegmentConfig(props: {
 						<KTabs.Trigger
 							value="auto"
 							class="z-10 flex-1 py-2.5 text-gray-11 transition-colors duration-100 outline-none ui-selected:text-gray-12 peer"
-							disabled={!generalSettings.data?.customCursorCapture2}
+							disabled={!generalSettings.data?.custom_cursor_capture2}
 						>
 							Auto
 						</KTabs.Trigger>
diff --git a/apps/desktop/src/routes/in-progress-recording.tsx b/apps/desktop/src/routes/in-progress-recording.tsx
index f9028062a0..2bae70d878 100644
--- a/apps/desktop/src/routes/in-progress-recording.tsx
+++ b/apps/desktop/src/routes/in-progress-recording.tsx
@@ -222,7 +222,7 @@ export default function () {
 						)}
 					</div>
 
-					{(currentRecording.data?.type === "studio" ||
+					{(currentRecording.data?.mode === "studio" ||
 						ostype() === "macos") && (
 						<ActionButton
 							disabled={togglePause.isPending}
diff --git a/apps/desktop/src/routes/target-select-overlay.tsx b/apps/desktop/src/routes/target-select-overlay.tsx
index 9d5be794a9..9c841f32e8 100644
--- a/apps/desktop/src/routes/target-select-overlay.tsx
+++ b/apps/desktop/src/routes/target-select-overlay.tsx
@@ -4,7 +4,9 @@ import {
 	createEventListenerMap,
 } from "@solid-primitives/event-listener";
 import { useSearchParams } from "@solidjs/router";
-import { getCurrentWindow } from "@tauri-apps/api/window";
+import { createQuery } from "@tanstack/solid-query";
+import { emit } from "@tauri-apps/api/event";
+import { CheckMenuItem, Menu, Submenu } from "@tauri-apps/api/menu";
 import { cx } from "cva";
 import {
 	type ComponentProps,
@@ -15,15 +17,16 @@ import {
 	Match,
 	onCleanup,
 	Show,
+	Suspense,
 	Switch,
 } from "solid-js";
 import { createStore, reconcile } from "solid-js/store";
+import { authStore, generalSettingsStore } from "~/store";
 import { createOptionsQuery } from "~/utils/queries";
 import {
 	commands,
 	type DisplayId,
 	events,
-	type LogicalBounds,
 	type ScreenCaptureTarget,
 	type TargetUnderCursor,
 } from "~/utils/tauri";
@@ -36,7 +39,6 @@ export default function () {
 		createStore<TargetUnderCursor>({
 			display_id: null,
 			window: null,
-			screen: null,
 		});
 
 	const unsubTargetUnderCursor = events.targetUnderCursor.listen((event) => {
@@ -44,24 +46,64 @@ export default function () {
 	});
 	onCleanup(() => unsubTargetUnderCursor.then((unsub) => unsub()));
 
-	const [bounds, _setBounds] = createStore<LogicalBounds>({
+	const windowIcon = createQuery(() => ({
+		queryKey: ["windowIcon", targetUnderCursor.window?.id],
+		queryFn: async () => {
+			if (!targetUnderCursor.window?.id) return null;
+			return await commands.getWindowIcon(
+				targetUnderCursor.window.id.toString(),
+			);
+		},
+		enabled: !!targetUnderCursor.window?.id,
+		staleTime: 5 * 60 * 1000, // Cache for 5 minutes
+	}));
+
+	const displayInformation = createQuery(() => ({
+		queryKey: ["displayId", params.displayId],
+		queryFn: async () => {
+			if (!params.displayId) return null;
+			try {
+				const info = await commands.displayInformation(params.displayId);
+				return info;
+			} catch (error) {
+				console.error("Failed to fetch screen information:", error);
+				return null;
+			}
+		},
+		enabled:
+			params.displayId !== undefined && rawOptions.targetMode === "display",
+	}));
+
+	const [bounds, _setBounds] = createStore({
 		position: { x: 0, y: 0 },
 		size: { width: 400, height: 300 },
 	});
 
 	const setBounds = (newBounds: typeof bounds) => {
-		newBounds.position.x = Math.max(0, newBounds.position.x);
-		newBounds.position.y = Math.max(0, newBounds.position.y);
-		newBounds.size.width = Math.min(
-			window.innerWidth - newBounds.position.x,
-			newBounds.size.width,
-		);
-		newBounds.size.height = Math.min(
-			window.innerHeight - newBounds.position.y,
-			newBounds.size.height,
-		);
-
-		_setBounds(newBounds);
+		const clampedBounds = {
+			position: {
+				x: Math.max(0, newBounds.position.x),
+				y: Math.max(0, newBounds.position.y),
+			},
+			size: {
+				width: Math.max(
+					150,
+					Math.min(
+						window.innerWidth - Math.max(0, newBounds.position.x),
+						newBounds.size.width,
+					),
+				),
+				height: Math.max(
+					150,
+					Math.min(
+						window.innerHeight - Math.max(0, newBounds.position.y),
+						newBounds.size.height,
+					),
+				),
+			},
+		};
+
+		_setBounds(clampedBounds);
 	};
 
 	// We do this so any Cap window, (or external in the case of a bug) that are focused can trigger the close shortcut
@@ -70,10 +112,6 @@ export default function () {
 	);
 	onCleanup(() => unsubOnEscapePress.then((f) => f()));
 
-	createEffect(() => {
-		if (rawOptions.captureTarget === undefined) getCurrentWindow().close();
-	});
-
 	// This prevents browser keyboard shortcuts from firing.
 	// Eg. on Windows Ctrl+P would open the print dialog without this
 	createEventListener(document, "keydown", (e) => e.preventDefault());
@@ -82,25 +120,32 @@ export default function () {
 		<Switch>
 			<Match when={rawOptions.targetMode === "display"}>
 				{(_) => (
-					<Show when={targetUnderCursor.screen} keyed>
-						{(screenUnderCursor) => (
-							<div
-								data-over={targetUnderCursor.display_id === params.displayId}
-								class="w-screen h-screen flex flex-col items-center justify-center bg-black/50 data-[over='true']:bg-blue-600/40 transition-colors"
-							>
-								<span class="text-3xl font-semibold mb-2">
-									{screenUnderCursor.name}
-								</span>
-								<span class="text-xs mb-2">
-									{`${screenUnderCursor.physical_size.width}x${screenUnderCursor.physical_size.height} · ${screenUnderCursor.refresh_rate}FPS`}
-								</span>
-
-								<RecordingControls
-									target={{ variant: "display", id: params.displayId! }}
-								/>
-							</div>
-						)}
-					</Show>
+					<div
+						data-over={targetUnderCursor.display_id === params.displayId}
+						class="relative w-screen h-screen flex flex-col items-center justify-center data-[over='true']:bg-blue-600/40 transition-colors"
+					>
+						<div class="absolute inset-0 bg-black/50 -z-10" />
+						<Show when={displayInformation.data} keyed>
+							{(display) => (
+								<>
+									<span class="text-3xl font-semibold mb-2 text-white">
+										{display.name || "Monitor"}
+									</span>
+									<Show when={display.physical_size}>
+										{(size) => (
+											<span class="text-xs mb-2 text-white">
+												{`${size().width}x${size().height} · ${display.refresh_rate}FPS`}
+											</span>
+										)}
+									</Show>
+								</>
+							)}
+						</Show>
+
+						<RecordingControls
+							target={{ variant: "display", id: params.displayId! }}
+						/>
+					</div>
 				)}
 			</Match>
 			<Match
@@ -113,10 +158,10 @@ export default function () {
 					{(windowUnderCursor) => (
 						<div
 							data-over={targetUnderCursor.display_id === params.displayId}
-							class="w-screen h-screen bg-black/50 relative"
+							class="relative w-screen h-screen bg-black/50"
 						>
 							<div
-								class="bg-blue-600/40 absolute flex flex-col items-center justify-center"
+								class="flex absolute flex-col justify-center items-center bg-blue-600/40"
 								style={{
 									width: `${windowUnderCursor.bounds.size.width}px`,
 									height: `${windowUnderCursor.bounds.size.height}px`,
@@ -124,20 +169,24 @@ export default function () {
 									top: `${windowUnderCursor.bounds.position.y}px`,
 								}}
 							>
-								<div class="flex flex-col items-center justify-center">
-									<Show when={windowUnderCursor.icon}>
-										{(icon) => (
-											<img
-												src={icon()}
-												alt={`${windowUnderCursor.app_name} icon`}
-												class="w-32 h-32 mb-3 rounded-lg"
-											/>
-										)}
-									</Show>
-									<span class="text-3xl font-semibold mb-2">
+								<div class="flex flex-col justify-center items-center text-white">
+									<div class="w-32 h-32">
+										<Suspense>
+											<Show when={windowIcon.data}>
+												{(icon) => (
+													<img
+														src={icon()}
+														alt={`${windowUnderCursor.app_name} icon`}
+														class="mb-3 w-full h-full rounded-lg animate-in fade-in"
+													/>
+												)}
+											</Show>
+										</Suspense>
+									</div>
+									<span class="mb-2 text-3xl font-semibold">
 										{windowUnderCursor.app_name}
 									</span>
-									<span class="text-xs mb-2">
+									<span class="mb-2 text-xs">
 										{`${windowUnderCursor.bounds.size.width}x${windowUnderCursor.bounds.size.height}`}
 									</span>
 								</div>
@@ -151,7 +200,6 @@ export default function () {
 								<Button
 									variant="primary"
 									size="sm"
-									class="mt-4"
 									onClick={() => {
 										setBounds(windowUnderCursor.bounds);
 										setOptions({
@@ -167,407 +215,565 @@ export default function () {
 				</Show>
 			</Match>
 			<Match when={rawOptions.targetMode === "area"}>
-				{(_) => {
-					const [dragging, setDragging] = createSignal(false);
-
-					function createOnMouseDown(
-						onDrag: (
-							startBounds: typeof bounds,
-							delta: { x: number; y: number },
-						) => void,
-					) {
-						return (downEvent: MouseEvent) => {
-							const startBounds = {
-								position: { ...bounds.position },
-								size: { ...bounds.size },
-							};
+				{(_) => (
+					<Show
+						when={targetUnderCursor.display_id === params.displayId}
+						fallback={
+							<div class="w-screen h-screen flex flex-col items-center justify-center data-[over='true']:bg-blue-600/40 transition-colors relative cursor-crosshair bg-black/50" />
+						}
+					>
+						{(_) => {
+							const [dragging, setDragging] = createSignal(false);
+							// Track whether the controls should be placed above the selection to avoid window bottom overflow
+							const [placeControlsAbove, setPlaceControlsAbove] =
+								createSignal(false);
+							let controlsEl: HTMLDivElement | undefined;
+
+							// Recompute placement when bounds change or window resizes
+							createEffect(() => {
+								// Read reactive dependencies
+								const top = bounds.position.y;
+								const height = bounds.size.height;
+								// Measure controls height (fallback to 64px if not yet mounted)
+								const ctrlH = controlsEl?.offsetHeight ?? 64;
+								const margin = 16;
+
+								const wouldOverflow =
+									top + height + margin + ctrlH > window.innerHeight;
+								setPlaceControlsAbove(wouldOverflow);
+							});
 
+							// Handle window resize to keep placement responsive
 							createRoot((dispose) => {
-								createEventListenerMap(window, {
-									mouseup: () => dispose(),
-									mousemove: (moveEvent) => {
-										onDrag(startBounds, {
-											x: Math.max(
-												-startBounds.position.x,
-												moveEvent.clientX - downEvent.clientX,
-											),
-											y: Math.max(
-												-startBounds.position.y,
-												moveEvent.clientY - downEvent.clientY,
-											),
-										});
-									},
+								const onResize = () => {
+									const ctrlH = controlsEl?.offsetHeight ?? 64;
+									const margin = 16;
+									const wouldOverflow =
+										bounds.position.y + bounds.size.height + margin + ctrlH >
+										window.innerHeight;
+									setPlaceControlsAbove(wouldOverflow);
+								};
+								window.addEventListener("resize", onResize);
+								onCleanup(() => {
+									window.removeEventListener("resize", onResize);
+									dispose();
 								});
 							});
-						};
-					}
 
-					function ResizeHandles() {
-						return (
-							<>
-								{/* Top Left Button */}
-								<ResizeHandle
-									class="cursor-nw-resize"
-									style={{
-										left: `${bounds.position.x + 1}px`,
-										top: `${bounds.position.y + 1}px`,
-									}}
-									onMouseDown={createOnMouseDown((startBounds, delta) => {
-										const width = startBounds.size.width - delta.x;
-										const limitedWidth = Math.max(width, 150);
-
-										const height = startBounds.size.height - delta.y;
-										const limitedHeight = Math.max(height, 150);
-
-										setBounds({
-											position: {
-												x:
-													startBounds.position.x +
-													delta.x -
-													(limitedWidth - width),
-												y:
-													startBounds.position.y +
-													delta.y -
-													(limitedHeight - height),
-											},
-											size: {
-												width: limitedWidth,
-												height: limitedHeight,
-											},
-										});
-									})}
-								/>
+							function createOnMouseDown(
+								onDrag: (
+									startBounds: typeof bounds,
+									delta: { x: number; y: number },
+								) => void,
+							) {
+								return (downEvent: MouseEvent) => {
+									const startBounds = {
+										position: { ...bounds.position },
+										size: { ...bounds.size },
+									};
 
-								{/* Top Right Button */}
-								<ResizeHandle
-									class="cursor-ne-resize"
-									style={{
-										left: `${bounds.position.x + bounds.size.width - 1}px`,
-										top: `${bounds.position.y + 1}px`,
-									}}
-									onMouseDown={createOnMouseDown((startBounds, delta) => {
-										const width = startBounds.size.width + delta.x;
-										const limitedWidth = Math.max(width, 150);
-
-										const height = startBounds.size.height - delta.y;
-										const limitedHeight = Math.max(height, 150);
-
-										setBounds({
-											position: {
-												x: startBounds.position.x,
-												y:
-													startBounds.position.y +
-													delta.y -
-													(limitedHeight - height),
-											},
-											size: {
-												width: limitedWidth,
-												height: limitedHeight,
-											},
-										});
-									})}
-								/>
-
-								{/* Bottom Left Button */}
-								<ResizeHandle
-									class="cursor-sw-resize"
-									style={{
-										left: `${bounds.position.x + 1}px`,
-										top: `${bounds.position.y + bounds.size.height - 1}px`,
-									}}
-									onMouseDown={createOnMouseDown((startBounds, delta) => {
-										const width = startBounds.size.width - delta.x;
-										const limitedWidth = Math.max(width, 150);
-
-										const height = startBounds.size.height + delta.y;
-										const limitedHeight = Math.max(height, 150);
-
-										setBounds({
-											position: {
-												x:
-													startBounds.position.x +
-													delta.x -
-													(limitedWidth - width),
-												y: startBounds.position.y,
-											},
-											size: {
-												width: limitedWidth,
-												height: limitedHeight,
-											},
-										});
-									})}
-								/>
-
-								{/* Bottom Right Button */}
-								<ResizeHandle
-									class="cursor-se-resize"
-									style={{
-										left: `${bounds.position.x + bounds.size.width - 1}px`,
-										top: `${bounds.position.y + bounds.size.height - 1}px`,
-									}}
-									onMouseDown={createOnMouseDown((startBounds, delta) => {
-										const width = startBounds.size.width + delta.x;
-										const limitedWidth = Math.max(width, 150);
-
-										const height = startBounds.size.height + delta.y;
-										const limitedHeight = Math.max(height, 150);
-
-										setBounds({
-											position: {
-												x: startBounds.position.x,
-												y: startBounds.position.y,
-											},
-											size: {
-												width: limitedWidth,
-												height: limitedHeight,
-											},
-										});
-									})}
-								/>
-
-								{/* Top Edge Button */}
-								<ResizeHandle
-									class="cursor-n-resize"
-									style={{
-										left: `${bounds.position.x + bounds.size.width / 2}px`,
-										top: `${bounds.position.y + 1}px`,
-									}}
-									onMouseDown={createOnMouseDown((startBounds, delta) => {
-										const height = startBounds.size.height - delta.y;
-										const limitedHeight = Math.max(height, 150);
-
-										setBounds({
-											position: {
-												x: startBounds.position.x,
-												y:
-													startBounds.position.y +
-													delta.y -
-													(limitedHeight - height),
-											},
-											size: {
-												width: startBounds.size.width,
-												height: limitedHeight,
-											},
-										});
-									})}
-								/>
-
-								{/* Right Edge Button */}
-								<ResizeHandle
-									class="cursor-e-resize"
-									style={{
-										left: `${bounds.position.x + bounds.size.width - 1}px`,
-										top: `${bounds.position.y + bounds.size.height / 2}px`,
-									}}
-									onMouseDown={createOnMouseDown((startBounds, delta) => {
-										setBounds({
-											position: {
-												x: startBounds.position.x,
-												y: startBounds.position.y,
-											},
-											size: {
-												width: Math.max(150, startBounds.size.width + delta.x),
-												height: startBounds.size.height,
-											},
-										});
-									})}
-								/>
-
-								{/* Bottom Edge Button */}
-								<ResizeHandle
-									class="cursor-s-resize"
-									style={{
-										left: `${bounds.position.x + bounds.size.width / 2}px`,
-										top: `${bounds.position.y + bounds.size.height - 1}px`,
-									}}
-									onMouseDown={createOnMouseDown((startBounds, delta) => {
-										setBounds({
-											position: {
-												x: startBounds.position.x,
-												y: startBounds.position.y,
-											},
-											size: {
-												width: startBounds.size.width,
-												height: Math.max(
-													150,
-													startBounds.size.height + delta.y,
-												),
-											},
-										});
-									})}
-								/>
-
-								{/* Left Edge Button */}
-								<ResizeHandle
-									class="cursor-w-resize"
-									style={{
-										left: `${bounds.position.x + 1}px`,
-										top: `${bounds.position.y + bounds.size.height / 2}px`,
-									}}
-									onMouseDown={createOnMouseDown((startBounds, delta) => {
-										const width = startBounds.size.width - delta.x;
-										const limitedWidth = Math.max(150, width);
-
-										setBounds({
-											position: {
-												x:
-													startBounds.position.x +
-													delta.x -
-													(limitedWidth - width),
-												y: startBounds.position.y,
-											},
-											size: {
-												width: limitedWidth,
-												height: startBounds.size.height,
-											},
-										});
-									})}
-								/>
-							</>
-						);
-					}
-
-					function Occluders() {
-						return (
-							<>
-								{/* Left */}
-								<div
-									class="bg-black/50 absolute top-0 left-0 bottom-0"
-									style={{ width: `${bounds.position.x}px` }}
-								/>
-								{/* Right */}
-								<div
-									class="bg-black/50 absolute top-0 right-0 bottom-0"
-									style={{
-										width: `${
-											window.innerWidth -
-											(bounds.size.width + bounds.position.x)
-										}px`,
-									}}
-								/>
-								{/* Top center */}
-								<div
-									class="bg-black/50 absolute top-0"
-									style={{
-										left: `${bounds.position.x}px`,
-										width: `${bounds.size.width}px`,
-										height: `${bounds.position.y}px`,
-									}}
-								/>
-								{/* Bottom center */}
-								<div
-									class="bg-black/50 absolute bottom-0"
-									style={{
-										left: `${bounds.position.x}px`,
-										width: `${bounds.size.width}px`,
-										height: `${
-											window.innerHeight -
-											(bounds.size.height + bounds.position.y)
-										}px`,
-									}}
-								/>
-							</>
-						);
-					}
-
-					return (
-						<div class="w-screen h-screen flex flex-col items-center justify-center data-[over='true']:bg-blue-600/40 transition-colors relative cursor-crosshair">
-							<Occluders />
-
-							<div
-								class={cx(
-									"absolute flex flex-col items-center",
-									dragging() ? "cursor-grabbing" : "cursor-grab",
-								)}
-								style={{
-									width: `${bounds.size.width}px`,
-									height: `${bounds.size.height}px`,
-									left: `${bounds.position.x}px`,
-									top: `${bounds.position.y}px`,
-								}}
-								onMouseDown={(downEvent) => {
-									setDragging(true);
-									const startPosition = { ...bounds.position };
+									let animationFrame: number | null = null;
 
 									createRoot((dispose) => {
 										createEventListenerMap(window, {
-											mousemove: (moveEvent) => {
-												const newPosition = {
-													x:
-														startPosition.x +
-														moveEvent.clientX -
-														downEvent.clientX,
-													y:
-														startPosition.y +
-														moveEvent.clientY -
-														downEvent.clientY,
-												};
-
-												if (newPosition.x < 0) newPosition.x = 0;
-												if (newPosition.y < 0) newPosition.y = 0;
-												if (
-													newPosition.x + bounds.size.width >
-													window.innerWidth
-												)
-													newPosition.x = window.innerWidth - bounds.size.width;
-												if (
-													newPosition.y + bounds.size.height >
-													window.innerHeight
-												)
-													newPosition.y =
-														window.innerHeight - bounds.size.height;
-
-												_setBounds("position", newPosition);
-											},
 											mouseup: () => {
-												setDragging(false);
+												if (animationFrame)
+													cancelAnimationFrame(animationFrame);
 												dispose();
 											},
+											mousemove: (moveEvent) => {
+												if (animationFrame)
+													cancelAnimationFrame(animationFrame);
+
+												animationFrame = requestAnimationFrame(() => {
+													onDrag(startBounds, {
+														x: moveEvent.clientX - downEvent.clientX, // Remove Math.max constraint
+														y: moveEvent.clientY - downEvent.clientY, // Remove Math.max constraint
+													});
+												});
+											},
 										});
 									});
-								}}
-							>
-								<div
-									class="absolute top-full flex flex-col items-center m-2"
-									style={{ width: `${bounds.size.width}px` }}
-								>
-									<RecordingControls
-										target={{
-											variant: "area",
-											screen: params.displayId!,
-											bounds,
+								};
+							}
+
+							function ResizeHandles() {
+								return (
+									<>
+										{/* Top Left Button */}
+										<ResizeHandle
+											class="cursor-nw-resize"
+											style={{
+												left: `${bounds.position.x + 1}px`,
+												top: `${bounds.position.y + 1}px`,
+											}}
+											onMouseDown={createOnMouseDown((startBounds, delta) => {
+												const width = startBounds.size.width - delta.x;
+												const limitedWidth = Math.max(width, 150);
+
+												const height = startBounds.size.height - delta.y;
+												const limitedHeight = Math.max(height, 150);
+
+												setBounds({
+													position: {
+														x:
+															startBounds.position.x +
+															delta.x -
+															(limitedWidth - width),
+														y:
+															startBounds.position.y +
+															delta.y -
+															(limitedHeight - height),
+													},
+													size: {
+														width: limitedWidth,
+														height: limitedHeight,
+													},
+												});
+											})}
+										/>
+
+										{/* Top Right Button */}
+										<ResizeHandle
+											class="cursor-ne-resize"
+											style={{
+												left: `${bounds.position.x + bounds.size.width - 1}px`,
+												top: `${bounds.position.y + 1}px`,
+											}}
+											onMouseDown={createOnMouseDown((startBounds, delta) => {
+												const width = startBounds.size.width + delta.x;
+												const limitedWidth = Math.max(width, 150);
+
+												const height = startBounds.size.height - delta.y;
+												const limitedHeight = Math.max(height, 150);
+
+												setBounds({
+													position: {
+														x: startBounds.position.x,
+														y:
+															startBounds.position.y +
+															delta.y -
+															(limitedHeight - height),
+													},
+													size: {
+														width: limitedWidth,
+														height: limitedHeight,
+													},
+												});
+											})}
+										/>
+
+										{/* Bottom Left Button */}
+										<ResizeHandle
+											class="cursor-sw-resize"
+											style={{
+												left: `${bounds.position.x + 1}px`,
+												top: `${bounds.position.y + bounds.size.height - 1}px`,
+											}}
+											onMouseDown={createOnMouseDown((startBounds, delta) => {
+												const width = startBounds.size.width - delta.x;
+												const limitedWidth = Math.max(width, 150);
+
+												const height = startBounds.size.height + delta.y;
+												const limitedHeight = Math.max(height, 150);
+
+												setBounds({
+													position: {
+														x:
+															startBounds.position.x +
+															delta.x -
+															(limitedWidth - width),
+														y: startBounds.position.y,
+													},
+													size: {
+														width: limitedWidth,
+														height: limitedHeight,
+													},
+												});
+											})}
+										/>
+
+										{/* Bottom Right Button */}
+										<ResizeHandle
+											class="cursor-se-resize"
+											style={{
+												left: `${bounds.position.x + bounds.size.width - 1}px`,
+												top: `${bounds.position.y + bounds.size.height - 1}px`,
+											}}
+											onMouseDown={createOnMouseDown((startBounds, delta) => {
+												const width = startBounds.size.width + delta.x;
+												const limitedWidth = Math.max(width, 150);
+
+												const height = startBounds.size.height + delta.y;
+												const limitedHeight = Math.max(height, 150);
+
+												setBounds({
+													position: {
+														x: startBounds.position.x,
+														y: startBounds.position.y,
+													},
+													size: {
+														width: limitedWidth,
+														height: limitedHeight,
+													},
+												});
+											})}
+										/>
+
+										{/* Top Edge Button */}
+										<ResizeHandle
+											class="cursor-n-resize"
+											style={{
+												left: `${bounds.position.x + bounds.size.width / 2}px`,
+												top: `${bounds.position.y + 1}px`,
+											}}
+											onMouseDown={createOnMouseDown((startBounds, delta) => {
+												const height = startBounds.size.height - delta.y;
+												const limitedHeight = Math.max(height, 150);
+
+												setBounds({
+													position: {
+														x: startBounds.position.x,
+														y:
+															startBounds.position.y +
+															delta.y -
+															(limitedHeight - height),
+													},
+													size: {
+														width: startBounds.size.width,
+														height: limitedHeight,
+													},
+												});
+											})}
+										/>
+
+										{/* Right Edge Button */}
+										<ResizeHandle
+											class="cursor-e-resize"
+											style={{
+												left: `${bounds.position.x + bounds.size.width - 1}px`,
+												top: `${bounds.position.y + bounds.size.height / 2}px`,
+											}}
+											onMouseDown={createOnMouseDown((startBounds, delta) => {
+												setBounds({
+													position: {
+														x: startBounds.position.x,
+														y: startBounds.position.y,
+													},
+													size: {
+														width: Math.max(
+															150,
+															startBounds.size.width + delta.x,
+														),
+														height: startBounds.size.height,
+													},
+												});
+											})}
+										/>
+
+										{/* Bottom Edge Button */}
+										<ResizeHandle
+											class="cursor-s-resize"
+											style={{
+												left: `${bounds.position.x + bounds.size.width / 2}px`,
+												top: `${bounds.position.y + bounds.size.height - 1}px`,
+											}}
+											onMouseDown={createOnMouseDown((startBounds, delta) => {
+												setBounds({
+													position: {
+														x: startBounds.position.x,
+														y: startBounds.position.y,
+													},
+													size: {
+														width: startBounds.size.width,
+														height: Math.max(
+															150,
+															startBounds.size.height + delta.y,
+														),
+													},
+												});
+											})}
+										/>
+
+										{/* Left Edge Button */}
+										<ResizeHandle
+											class="cursor-w-resize"
+											style={{
+												left: `${bounds.position.x + 1}px`,
+												top: `${bounds.position.y + bounds.size.height / 2}px`,
+											}}
+											onMouseDown={createOnMouseDown((startBounds, delta) => {
+												const width = startBounds.size.width - delta.x;
+												const limitedWidth = Math.max(150, width);
+
+												setBounds({
+													position: {
+														x:
+															startBounds.position.x +
+															delta.x -
+															(limitedWidth - width),
+														y: startBounds.position.y,
+													},
+													size: {
+														width: limitedWidth,
+														height: startBounds.size.height,
+													},
+												});
+											})}
+										/>
+									</>
+								);
+							}
+
+							function Occluders() {
+								return (
+									<>
+										{/* Left */}
+										<div
+											class="absolute top-0 bottom-0 left-0 bg-black/50"
+											style={{ width: `${bounds.position.x}px` }}
+										/>
+										{/* Right */}
+										<div
+											class="absolute top-0 right-0 bottom-0 bg-black/50"
+											style={{
+												width: `${
+													window.innerWidth -
+													(bounds.size.width + bounds.position.x)
+												}px`,
+											}}
+										/>
+										{/* Top center */}
+										<div
+											class="absolute top-0 bg-black/50"
+											style={{
+												left: `${bounds.position.x}px`,
+												width: `${bounds.size.width}px`,
+												height: `${bounds.position.y}px`,
+											}}
+										/>
+										{/* Bottom center */}
+										<div
+											class="absolute bottom-0 bg-black/50"
+											style={{
+												left: `${bounds.position.x}px`,
+												width: `${bounds.size.width}px`,
+												height: `${
+													window.innerHeight -
+													(bounds.size.height + bounds.position.y)
+												}px`,
+											}}
+										/>
+									</>
+								);
+							}
+
+							return (
+								<div class="w-screen h-screen flex flex-col items-center justify-center data-[over='true']:bg-blue-600/40 transition-colors relative cursor-crosshair">
+									<Occluders />
+
+									<div
+										class={cx(
+											"flex absolute flex-col items-center",
+											dragging() ? "cursor-grabbing" : "cursor-grab",
+										)}
+										style={{
+											width: `${bounds.size.width}px`,
+											height: `${bounds.size.height}px`,
+											left: `${bounds.position.x}px`,
+											top: `${bounds.position.y}px`,
 										}}
-									/>
-								</div>
-							</div>
+										onMouseDown={(downEvent) => {
+											setDragging(true);
+											const startPosition = { ...bounds.position };
+
+											createRoot((dispose) => {
+												createEventListenerMap(window, {
+													mousemove: (moveEvent) => {
+														const newPosition = {
+															x:
+																startPosition.x +
+																moveEvent.clientX -
+																downEvent.clientX,
+															y:
+																startPosition.y +
+																moveEvent.clientY -
+																downEvent.clientY,
+														};
+
+														if (newPosition.x < 0) newPosition.x = 0;
+														if (newPosition.y < 0) newPosition.y = 0;
+														if (
+															newPosition.x + bounds.size.width >
+															window.innerWidth
+														)
+															newPosition.x =
+																window.innerWidth - bounds.size.width;
+														if (
+															newPosition.y + bounds.size.height >
+															window.innerHeight
+														)
+															newPosition.y =
+																window.innerHeight - bounds.size.height;
+
+														_setBounds("position", newPosition);
+													},
+													mouseup: () => {
+														setDragging(false);
+														dispose();
+													},
+												});
+											});
+										}}
+									>
+										<div
+											ref={controlsEl}
+											class={cx(
+												"flex absolute flex-col items-center m-2",
+												placeControlsAbove() ? "bottom-full" : "top-full",
+											)}
+											style={{ width: `${bounds.size.width}px` }}
+										>
+											<RecordingControls
+												target={{
+													variant: "area",
+													screen: params.displayId!,
+													bounds,
+												}}
+											/>
+										</div>
+									</div>
 
-							<ResizeHandles />
+									<ResizeHandles />
 
-							<span class="text-xl z-10">Click and drag area to record</span>
-						</div>
-					);
-				}}
+									<p class="z-10 text-xl">Click and drag area to record</p>
+								</div>
+							);
+						}}
+					</Show>
+				)}
 			</Match>
 		</Switch>
 	);
 }
 
 function RecordingControls(props: { target: ScreenCaptureTarget }) {
-	const { rawOptions } = createOptionsQuery();
+	const auth = authStore.createQuery();
+	const { rawOptions, setOptions } = createOptionsQuery();
+
+	const generalSetings = generalSettingsStore.createQuery();
+
+	const capitalize = (str: string) => {
+		return str.charAt(0).toUpperCase() + str.slice(1);
+	};
+
+	const menuModes = async () =>
+		await Menu.new({
+			items: [
+				await CheckMenuItem.new({
+					text: "Studio Mode",
+					action: () => {
+						setOptions("mode", "studio");
+					},
+					checked: rawOptions.mode === "studio",
+				}),
+				await CheckMenuItem.new({
+					text: "Instant Mode",
+					action: () => {
+						setOptions("mode", "instant");
+					},
+					checked: rawOptions.mode === "instant",
+				}),
+			],
+		});
+
+	const countdownMenu = async () =>
+		await Submenu.new({
+			text: "Recording Countdown",
+			items: [
+				await CheckMenuItem.new({
+					text: "3 seconds",
+					action: () => generalSettingsStore.set({ recordingCountdown: 3 }),
+					checked: generalSetings.data?.recordingCountdown === 3,
+				}),
+				await CheckMenuItem.new({
+					text: "5 seconds",
+					action: () => generalSettingsStore.set({ recordingCountdown: 5 }),
+					checked: generalSetings.data?.recordingCountdown === 5,
+				}),
+				await CheckMenuItem.new({
+					text: "10 seconds",
+					action: () => generalSettingsStore.set({ recordingCountdown: 10 }),
+					checked: generalSetings.data?.recordingCountdown === 10,
+				}),
+			],
+		});
+
+	const preRecordingMenu = async () => {
+		return await Menu.new({ items: [await countdownMenu()] });
+	};
 
 	return (
-		<Button
-			size="lg"
-			onClick={() => {
-				commands.startRecording({
-					capture_target: props.target,
-					mode: rawOptions.mode,
-					capture_system_audio: rawOptions.captureSystemAudio,
-				});
-			}}
-		>
-			Start Recording
-		</Button>
+		<div class="flex gap-2.5 items-center p-2.5 my-2.5 rounded-xl border min-w-fit w-fit bg-gray-2 border-gray-4">
+			<div
+				onClick={() => setOptions("targetMode", null)}
+				class="flex justify-center items-center bg-white rounded-full transition-opacity size-9 hover:opacity-80"
+			>
+				<IconCapX class="will-change-transform size-3" />
+			</div>
+			<div
+				data-inactive={rawOptions.mode === "instant" && !auth.data}
+				class="flex flex-row rounded-full bg-blue-9 overflow-hidden group h-11"
+				onClick={() => {
+					if (rawOptions.mode === "instant" && !auth.data) {
+						emit("start-sign-in");
+						return;
+					}
+
+					commands.startRecording({
+						capture_target: props.target,
+						mode: rawOptions.mode,
+						capture_system_audio: rawOptions.captureSystemAudio,
+					});
+				}}
+			>
+				<div class="flex items-center pl-4 py-1 hover:bg-blue-10 transition-colors">
+					{rawOptions.mode === "studio" ? (
+						<IconCapFilmCut class="size-4" />
+					) : (
+						<IconCapInstant class="size-4" />
+					)}
+					<div class="flex flex-col ml-3 mr-2">
+						<span class="text-sm text-white font-medium text-nowrap">
+							{rawOptions.mode === "instant" && !auth.data
+								? "Sign In To Use"
+								: "Start Recording"}
+						</span>
+						<span class="text-xs text-nowrap text-white font-light -mt-0.5 opacity-90">
+							{`${capitalize(rawOptions.mode)} Mode`}
+						</span>
+					</div>
+				</div>
+				<div
+					class="pl-2.5 group-hover:bg-blue-10 transition-colors pr-3 py-1.5 flex items-center"
+					onClick={(e) => {
+						e.stopPropagation();
+						menuModes().then((menu) => menu.popup());
+					}}
+				>
+					<IconCapCaretDown class="focus:rotate-90" />
+				</div>
+			</div>
+			<div
+				onClick={(e) => {
+					e.stopPropagation();
+					preRecordingMenu().then((menu) => menu.popup());
+				}}
+				class="flex justify-center items-center rounded-full border transition-opacity bg-gray-6 text-gray-12 size-9 hover:opacity-80"
+			>
+				<IconCapGear class="will-change-transform size-5" />
+			</div>
+		</div>
 	);
 }
 
diff --git a/apps/desktop/src/routes/window-capture-occluder.tsx b/apps/desktop/src/routes/window-capture-occluder.tsx
index a3ae4a02a9..d1ecc3575b 100644
--- a/apps/desktop/src/routes/window-capture-occluder.tsx
+++ b/apps/desktop/src/routes/window-capture-occluder.tsx
@@ -1,7 +1,5 @@
-import { getAllWindows, getCurrentWindow } from "@tauri-apps/api/window";
-import { getCurrent } from "@tauri-apps/plugin-deep-link";
-import { type as ostype } from "@tauri-apps/plugin-os";
-import { createResource, Show, Suspense } from "solid-js";
+import { getAllWindows } from "@tauri-apps/api/window";
+import { Show, Suspense } from "solid-js";
 import CropAreaRenderer from "~/components/CropAreaRenderer";
 import { createCurrentRecordingQuery } from "~/utils/queries";
 
diff --git a/apps/desktop/src/utils/auth.ts b/apps/desktop/src/utils/auth.ts
index 38d6e8d7aa..85001ed619 100644
--- a/apps/desktop/src/utils/auth.ts
+++ b/apps/desktop/src/utils/auth.ts
@@ -23,7 +23,8 @@ export function createSignInMutation() {
 
 			await shell.open(session.url.toString());
 
-			await processAuthData(await session.complete());
+			const res = await session.complete();
+			if (res) await processAuthData(res);
 
 			getCurrentWindow().setFocus();
 		},
@@ -67,7 +68,8 @@ async function createLocalServerSession(signal: AbortSignal) {
 		invoke("plugin:oauth|stop").catch(() => {});
 	};
 
-	let res: (url: URL) => void;
+	let res: (url: URL | null) => void;
+
 	const stopListening = await listen(
 		"oauth://url",
 		(data: { payload: string }) => {
@@ -83,16 +85,19 @@ async function createLocalServerSession(signal: AbortSignal) {
 		},
 	);
 
+	signal.onabort = (e: Event) => {
+		res(null);
+	};
+
 	return {
 		url: await createSessionRequestUrl(port, "web"),
 		complete: async () => {
-			const url = await new Promise<URL>((r) => {
-				res = r;
+			const url = await new Promise<URL | null>((_res) => {
+				res = _res;
 			});
 
-			console.log(url);
 			stopListening();
-
+			if (!url) return null;
 			if (signal.aborted) throw new Error("Sign in aborted");
 
 			const a = [...url.searchParams].reduce((acc, [k, v]) => {
diff --git a/apps/desktop/src/utils/tauri.ts b/apps/desktop/src/utils/tauri.ts
index cd7ad47057..1c0aaf2eea 100644
--- a/apps/desktop/src/utils/tauri.ts
+++ b/apps/desktop/src/utils/tauri.ts
@@ -142,7 +142,7 @@ export const commands = {
 	async getRecordingMeta(
 		path: string,
 		fileType: FileType,
-	): Promise<RecordingMetaWithType> {
+	): Promise<RecordingMetaWithMode> {
 		return await TAURI_INVOKE("get_recording_meta", { path, fileType });
 	},
 	async saveFileDialog(
@@ -151,7 +151,7 @@ export const commands = {
 	): Promise<string | null> {
 		return await TAURI_INVOKE("save_file_dialog", { fileName, fileType });
 	},
-	async listRecordings(): Promise<[string, RecordingMetaWithType][]> {
+	async listRecordings(): Promise<[string, RecordingMetaWithMode][]> {
 		return await TAURI_INVOKE("list_recordings");
 	},
 	async listScreenshots(): Promise<[string, RecordingMeta][]> {
@@ -302,6 +302,12 @@ export const commands = {
 	async closeTargetSelectOverlays(): Promise<null> {
 		return await TAURI_INVOKE("close_target_select_overlays");
 	},
+	async displayInformation(displayId: string): Promise<DisplayInformation> {
+		return await TAURI_INVOKE("display_information", { displayId });
+	},
+	async getWindowIcon(windowId: string): Promise<string | null> {
+		return await TAURI_INVOKE("get_window_icon", { windowId });
+	},
 };
 
 /** user-defined events **/
@@ -483,7 +489,7 @@ export type CommercialLicense = {
 export type Crop = { position: XY<number>; size: XY<number> };
 export type CurrentRecording = {
 	target: CurrentRecordingTarget;
-	type: RecordingType;
+	mode: RecordingMode;
 };
 export type CurrentRecordingChanged = null;
 export type CurrentRecordingTarget =
@@ -515,6 +521,11 @@ export type Cursors =
 	| { [key in string]: CursorMeta };
 export type DeviceOrModelID = { DeviceID: string } | { ModelID: ModelIDType };
 export type DisplayId = string;
+export type DisplayInformation = {
+	name: string | null;
+	physical_size: PhysicalSize | null;
+	refresh_rate: string;
+};
 export type DownloadProgress = { progress: number; message: string };
 export type EditorStateChanged = { playhead_position: number };
 export type ExportCompression = "Minimal" | "Social" | "Web" | "Potato";
@@ -548,7 +559,7 @@ export type GeneralSettingsStore = {
 	windowTransparency?: boolean;
 	postStudioRecordingBehaviour?: PostStudioRecordingBehaviour;
 	mainWindowRecordingStartBehaviour?: MainWindowRecordingStartBehaviour;
-	customCursorCapture2?: boolean;
+	custom_cursor_capture2?: boolean;
 	serverUrl?: string;
 	recordingCountdown?: number | null;
 	enableNativeCameraPreview: boolean;
@@ -660,19 +671,18 @@ export type RecordingMeta = (StudioRecordingMeta | InstantRecordingMeta) & {
 	pretty_name: string;
 	sharing?: SharingMeta | null;
 };
-export type RecordingMetaWithType = ((
+export type RecordingMetaWithMode = ((
 	| StudioRecordingMeta
 	| InstantRecordingMeta
 ) & {
 	platform?: Platform | null;
 	pretty_name: string;
 	sharing?: SharingMeta | null;
-}) & { type: RecordingType };
+}) & { mode: RecordingMode };
 export type RecordingMode = "studio" | "instant";
 export type RecordingOptionsChanged = null;
 export type RecordingStarted = null;
 export type RecordingStopped = null;
-export type RecordingType = "studio" | "instant";
 export type RenderFrameEvent = {
 	frame_number: number;
 	fps: number;
@@ -686,11 +696,6 @@ export type ScreenCaptureTarget =
 	| { variant: "window"; id: WindowId }
 	| { variant: "display"; id: DisplayId }
 	| { variant: "area"; screen: DisplayId; bounds: LogicalBounds };
-export type ScreenUnderCursor = {
-	name: string;
-	physical_size: PhysicalSize;
-	refresh_rate: string;
-};
 export type SegmentRecordings = {
 	display: Video;
 	camera: Video | null;
@@ -741,7 +746,6 @@ export type StudioRecordingMeta =
 export type TargetUnderCursor = {
 	display_id: DisplayId | null;
 	window: WindowUnderCursor | null;
-	screen: ScreenUnderCursor | null;
 };
 export type TimelineConfiguration = {
 	segments: TimelineSegment[];
@@ -789,7 +793,6 @@ export type WindowUnderCursor = {
 	id: WindowId;
 	app_name: string;
 	bounds: LogicalBounds;
-	icon: string | null;
 };
 export type XY<T> = { x: T; y: T };
 export type ZoomMode = "auto" | { manual: { x: number; y: number } };
diff --git a/crates/cursor-capture/Cargo.toml b/crates/cursor-capture/Cargo.toml
index 8705eea0ab..5cf9754778 100644
--- a/crates/cursor-capture/Cargo.toml
+++ b/crates/cursor-capture/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2024"
 workspace = true
 
 [dependencies]
-cap-displays = { path = "../displays" }
+scap-targets = { path = "../scap-targets" }
 
 device_query = "4.0.1"
 
diff --git a/crates/cursor-capture/src/main.rs b/crates/cursor-capture/src/main.rs
index 9131818717..3e0e4960ff 100644
--- a/crates/cursor-capture/src/main.rs
+++ b/crates/cursor-capture/src/main.rs
@@ -1,5 +1,5 @@
 use cap_cursor_capture::RawCursorPosition;
-use cap_displays::Display;
+use scap_targets::Display;
 
 fn main() {
     loop {
diff --git a/crates/cursor-capture/src/position.rs b/crates/cursor-capture/src/position.rs
index b41248784c..133f4a4563 100644
--- a/crates/cursor-capture/src/position.rs
+++ b/crates/cursor-capture/src/position.rs
@@ -1,5 +1,5 @@
-use cap_displays::{Display, bounds::*};
 use device_query::{DeviceQuery, DeviceState};
+use scap_targets::{Display, bounds::*};
 
 // Physical on Windows, Logical on macOS
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -208,7 +208,7 @@ impl std::fmt::Debug for NormalizedCursorPosition {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use cap_displays::Display;
+    use scap_targets::Display;
 
     // Helper function to create a mock Display for testing
     fn mock_display() -> Display {
diff --git a/crates/media/Cargo.toml b/crates/media/Cargo.toml
index 80951311d9..99728c5224 100644
--- a/crates/media/Cargo.toml
+++ b/crates/media/Cargo.toml
@@ -18,7 +18,6 @@ cap-audio = { path = "../audio" }
 cap-camera = { path = "../camera", features = ["specta", "serde"] }
 cap-camera-ffmpeg = { path = "../camera-ffmpeg" }
 cap-cpal-ffmpeg = { path = "../cpal-ffmpeg" }
-cap-displays = { path = "../displays" }
 cap-fail = { path = "../fail" }
 cap-media-encoders = { path = "../media-encoders" }
 cap-media-info = { path = "../media-info" }
@@ -43,6 +42,7 @@ kameo = "0.17.2"
 scap = { workspace = true }
 sync_wrapper = "1.0.2"
 scap-ffmpeg = { path = "../scap-ffmpeg" }
+scap-targets = { path = "../scap-targets" }
 
 [target.'cfg(target_os = "macos")'.dependencies]
 cidre = { workspace = true }
diff --git a/crates/recording/Cargo.toml b/crates/recording/Cargo.toml
index 6ac1308461..95388d5611 100644
--- a/crates/recording/Cargo.toml
+++ b/crates/recording/Cargo.toml
@@ -13,7 +13,7 @@ cap-project = { path = "../project" }
 cap-media = { path = "../media" }
 cap-flags = { path = "../flags" }
 cap-utils = { path = "../utils" }
-cap-displays = { path = "../displays" }
+scap-targets = { path = "../scap-targets" }
 cap-cursor-capture = { path = "../cursor-capture" }
 cap-media-encoders = { path = "../media-encoders" }
 cap-media-info = { path = "../media-info" }
diff --git a/crates/recording/examples/recording-cli.rs b/crates/recording/examples/recording-cli.rs
index 7cd7dff9e2..be69e6082d 100644
--- a/crates/recording/examples/recording-cli.rs
+++ b/crates/recording/examples/recording-cli.rs
@@ -1,7 +1,7 @@
 use std::time::Duration;
 
-use cap_displays::Display;
 use cap_recording::{RecordingBaseInputs, screen_capture::ScreenCaptureTarget};
+use scap_targets::Display;
 
 #[tokio::main]
 pub async fn main() {
diff --git a/crates/recording/examples/screen_capture.rs b/crates/recording/examples/screen_capture.rs
index 409fbb8875..b8f0ecf9df 100644
--- a/crates/recording/examples/screen_capture.rs
+++ b/crates/recording/examples/screen_capture.rs
@@ -1,8 +1,8 @@
-use cap_displays::Window;
 use cap_recording::{
     pipeline::{control::PipelineControlSignal, task::PipelineSourceTask},
     sources::{CMSampleBufferCapture, ScreenCaptureSource, ScreenCaptureTarget},
 };
+use scap_targets::Window;
 use std::time::SystemTime;
 
 #[tokio::main]
diff --git a/crates/recording/src/cursor.rs b/crates/recording/src/cursor.rs
index 4bc817c5ed..7c42933dbf 100644
--- a/crates/recording/src/cursor.rs
+++ b/crates/recording/src/cursor.rs
@@ -37,7 +37,7 @@ impl CursorActor {
 #[tracing::instrument(name = "cursor", skip_all)]
 pub fn spawn_cursor_recorder(
     crop_bounds: CursorCropBounds,
-    display: cap_displays::Display,
+    display: scap_targets::Display,
     cursors_dir: PathBuf,
     prev_cursors: Cursors,
     next_cursor_id: u32,
diff --git a/crates/recording/src/feeds/microphone.rs b/crates/recording/src/feeds/microphone.rs
index 07f20ceec8..75ba267327 100644
--- a/crates/recording/src/feeds/microphone.rs
+++ b/crates/recording/src/feeds/microphone.rs
@@ -72,6 +72,7 @@ struct ConnectingState {
 }
 
 struct AttachedState {
+    #[allow(dead_code)]
     id: u32,
     config: SupportedStreamConfig,
     done_tx: mpsc::SyncSender<()>,
diff --git a/crates/recording/src/lib.rs b/crates/recording/src/lib.rs
index 8ed6604fd0..9403fc7bd3 100644
--- a/crates/recording/src/lib.rs
+++ b/crates/recording/src/lib.rs
@@ -11,9 +11,9 @@ pub use studio_recording::{
     CompletedStudioRecording, StudioRecordingHandle, spawn_studio_recording_actor,
 };
 
-use cap_displays::bounds::LogicalBounds;
 use cap_media::MediaError;
 use feeds::microphone::MicrophoneFeedLock;
+use scap_targets::bounds::LogicalBounds;
 use serde::{Deserialize, Serialize};
 use sources::*;
 use std::sync::Arc;
diff --git a/crates/recording/src/sources/screen_capture/mod.rs b/crates/recording/src/sources/screen_capture/mod.rs
index 34a1a66d41..bf6ee04120 100644
--- a/crates/recording/src/sources/screen_capture/mod.rs
+++ b/crates/recording/src/sources/screen_capture/mod.rs
@@ -1,8 +1,8 @@
 use cap_cursor_capture::CursorCropBounds;
-use cap_displays::{Display, DisplayId, Window, WindowId, bounds::*};
 use cap_media_info::{AudioInfo, VideoInfo};
 use ffmpeg::sys::AV_TIME_BASE_Q;
 use flume::Sender;
+use scap_targets::{Display, DisplayId, Window, WindowId, bounds::*};
 use serde::{Deserialize, Serialize};
 use specta::Type;
 use std::time::SystemTime;
@@ -402,7 +402,7 @@ impl<TCaptureFormat: ScreenCaptureFormat> ScreenCaptureSource<TCaptureFormat> {
 }
 
 pub fn list_displays() -> Vec<(CaptureDisplay, Display)> {
-    cap_displays::Display::list()
+    scap_targets::Display::list()
         .into_iter()
         .filter_map(|display| {
             Some((
@@ -418,7 +418,7 @@ pub fn list_displays() -> Vec<(CaptureDisplay, Display)> {
 }
 
 pub fn list_windows() -> Vec<(CaptureWindow, Window)> {
-    cap_displays::Window::list()
+    scap_targets::Window::list()
         .into_iter()
         .flat_map(|v| {
             let name = v.name()?;
diff --git a/crates/scap-direct3d/Cargo.toml b/crates/scap-direct3d/Cargo.toml
index 1684ecab6f..b835f19b77 100644
--- a/crates/scap-direct3d/Cargo.toml
+++ b/crates/scap-direct3d/Cargo.toml
@@ -22,7 +22,7 @@ windows = { workspace = true, features = [
 ] }
 
 [dev-dependencies]
-cap-displays = { path = "../displays" }
+scap-targets = { path = "../scap-targets" }
 scap-ffmpeg = { path = "../scap-ffmpeg" }
 
 [lints]
diff --git a/crates/scap-direct3d/examples/cli.rs b/crates/scap-direct3d/examples/cli.rs
index 0103a2eea0..5f5414024c 100644
--- a/crates/scap-direct3d/examples/cli.rs
+++ b/crates/scap-direct3d/examples/cli.rs
@@ -5,9 +5,9 @@ fn main() {
 
 #[cfg(windows)]
 mod windows {
-    use cap_displays::*;
     use scap_direct3d::{Capturer, PixelFormat, Settings};
     use scap_ffmpeg::*;
+    use scap_targets::*;
     use std::time::Duration;
     use windows::Win32::Graphics::Direct3D11::D3D11_BOX;
 
diff --git a/crates/scap-ffmpeg/Cargo.toml b/crates/scap-ffmpeg/Cargo.toml
index a318010cde..a9ec90ece5 100644
--- a/crates/scap-ffmpeg/Cargo.toml
+++ b/crates/scap-ffmpeg/Cargo.toml
@@ -21,7 +21,7 @@ cidre = { workspace = true }
 [dev-dependencies]
 futures = { workspace = true }
 tokio = { workspace = true }
-cap-displays = { path = "../displays" }
+scap-targets = { path = "../scap-targets" }
 
 [lints]
 workspace = true
diff --git a/crates/scap-ffmpeg/examples/cli.rs b/crates/scap-ffmpeg/examples/cli.rs
index 878abf3421..dc3dc57061 100644
--- a/crates/scap-ffmpeg/examples/cli.rs
+++ b/crates/scap-ffmpeg/examples/cli.rs
@@ -1,5 +1,5 @@
-use cap_displays::*;
 use scap_ffmpeg::*;
+use scap_targets::*;
 use std::time::Duration;
 
 #[tokio::main]
diff --git a/crates/scap-screencapturekit/Cargo.toml b/crates/scap-screencapturekit/Cargo.toml
index 32d74b4611..7a0ee12a32 100644
--- a/crates/scap-screencapturekit/Cargo.toml
+++ b/crates/scap-screencapturekit/Cargo.toml
@@ -20,4 +20,4 @@ workspace = true
 [dev-dependencies]
 clap = { version = "4.5.40", features = ["derive"] }
 inquire = "0.7.5"
-cap-displays = { path = "../displays" }
+scap-targets = { path = "../scap-targets" }
diff --git a/crates/scap-screencapturekit/examples/cli.rs b/crates/scap-screencapturekit/examples/cli.rs
index c1bd13416d..f0b3e78c5b 100644
--- a/crates/scap-screencapturekit/examples/cli.rs
+++ b/crates/scap-screencapturekit/examples/cli.rs
@@ -1,4 +1,4 @@
-use cap_displays::Display;
+use scap_targets::Display;
 use std::time::Duration;
 
 use futures::executor::block_on;
diff --git a/crates/displays/Cargo.toml b/crates/scap-targets/Cargo.toml
similarity index 70%
rename from crates/displays/Cargo.toml
rename to crates/scap-targets/Cargo.toml
index 18070abb9e..0809ad1342 100644
--- a/crates/displays/Cargo.toml
+++ b/crates/scap-targets/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cap-displays"
+name = "scap-targets"
 version = "0.1.0"
 edition = "2024"
 
@@ -19,21 +19,13 @@ core-foundation = "0.10.0"
 cocoa = "0.26.0"
 objc = "0.2.7"
 
-[target.'cfg(target_os= "windows")'.dependencies]
+[target.'cfg(target_os = "windows")'.dependencies]
 windows = { workspace = true, features = [
 	"Win32_Foundation",
-	"Win32_System",
 	"Win32_System_Threading",
-	"Win32_System_Registry",
-	"Win32_System_Com",
-	"Win32_System_Wmi",
 	"Win32_UI_WindowsAndMessaging",
 	"Win32_UI_Shell",
 	"Win32_UI_HiDpi",
-	"Win32_Graphics_Dwm",
 	"Win32_Graphics_Gdi",
 	"Win32_Storage_FileSystem",
-	"Win32_Devices_Display",
-	"Graphics_Capture",
-	"Win32_System_WinRT_Graphics_Capture",
 ] }
diff --git a/crates/displays/src/bounds.rs b/crates/scap-targets/src/bounds.rs
similarity index 100%
rename from crates/displays/src/bounds.rs
rename to crates/scap-targets/src/bounds.rs
diff --git a/crates/displays/src/lib.rs b/crates/scap-targets/src/lib.rs
similarity index 100%
rename from crates/displays/src/lib.rs
rename to crates/scap-targets/src/lib.rs
diff --git a/crates/displays/src/main.rs b/crates/scap-targets/src/main.rs
similarity index 92%
rename from crates/displays/src/main.rs
rename to crates/scap-targets/src/main.rs
index 0a5ff9da16..8994ce11b7 100644
--- a/crates/displays/src/main.rs
+++ b/crates/scap-targets/src/main.rs
@@ -10,7 +10,7 @@ fn main() {
 
     // Test display functionality
     println!("=== Display Information ===");
-    for (index, display) in cap_displays::Display::list().iter().enumerate() {
+    for (index, display) in scap_targets::Display::list().iter().enumerate() {
         println!("Display {}: {}", index + 1, display.name().unwrap());
         println!("  ID: {}", display.id());
 
@@ -36,7 +36,7 @@ fn main() {
         }
 
         // Check if this is the main display
-        let main_display_id = cap_displays::Display::list().first().map(|d| d.id());
+        let main_display_id = scap_targets::Display::list().first().map(|d| d.id());
 
         if let Some(main_id) = main_display_id {
             if display.id() == main_id {
@@ -51,7 +51,7 @@ fn main() {
         println!();
     }
 
-    if let Some(cursor_display) = cap_displays::Display::get_containing_cursor() {
+    if let Some(cursor_display) = scap_targets::Display::get_containing_cursor() {
         println!(
             "🖱️  Cursor is currently on: {}",
             cursor_display.name().unwrap()
@@ -61,7 +61,7 @@ fn main() {
 
     // Test window functionality
     println!("=== Windows Under Cursor ===");
-    let windows = cap_displays::Window::list_containing_cursor();
+    let windows = scap_targets::Window::list_containing_cursor();
 
     if windows.is_empty() {
         println!("No windows found under cursor");
@@ -101,7 +101,7 @@ fn main() {
     }
 
     println!("\n=== Topmost Window Icon Test ===");
-    if let Some(topmost) = cap_displays::Window::get_topmost_at_cursor()
+    if let Some(topmost) = scap_targets::Window::get_topmost_at_cursor()
         && let Some(owner) = topmost.owner_name()
     {
         println!("Testing icon extraction for: {}", owner);
@@ -120,7 +120,7 @@ fn main() {
     println!("Monitoring window levels under cursor...\n");
 
     loop {
-        let mut relevant_windows = cap_displays::WindowImpl::list_containing_cursor()
+        let mut relevant_windows = scap_targets::WindowImpl::list_containing_cursor()
             .into_iter()
             .filter_map(|window| {
                 let level = window.level()?;
diff --git a/crates/displays/src/platform/macos.rs b/crates/scap-targets/src/platform/macos.rs
similarity index 100%
rename from crates/displays/src/platform/macos.rs
rename to crates/scap-targets/src/platform/macos.rs
diff --git a/crates/displays/src/platform/mod.rs b/crates/scap-targets/src/platform/mod.rs
similarity index 100%
rename from crates/displays/src/platform/mod.rs
rename to crates/scap-targets/src/platform/mod.rs
diff --git a/crates/displays/src/platform/win.rs b/crates/scap-targets/src/platform/win.rs
similarity index 56%
rename from crates/displays/src/platform/win.rs
rename to crates/scap-targets/src/platform/win.rs
index 697ed47072..4039ebe563 100644
--- a/crates/displays/src/platform/win.rs
+++ b/crates/scap-targets/src/platform/win.rs
@@ -3,15 +3,7 @@ use tracing::error;
 use windows::{
     Graphics::Capture::GraphicsCaptureItem,
     Win32::{
-        Devices::Display::{
-            DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME, DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME,
-            DISPLAYCONFIG_DEVICE_INFO_HEADER, DISPLAYCONFIG_MODE_INFO, DISPLAYCONFIG_PATH_INFO,
-            DISPLAYCONFIG_SOURCE_DEVICE_NAME, DISPLAYCONFIG_TARGET_DEVICE_NAME,
-            DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS, DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY,
-            DisplayConfigGetDeviceInfo, GetDisplayConfigBufferSizes, QDC_ONLY_ACTIVE_PATHS,
-            QueryDisplayConfig,
-        },
-        Foundation::{CloseHandle, HWND, LPARAM, POINT, RECT, TRUE, WIN32_ERROR, WPARAM},
+        Foundation::{CloseHandle, HWND, LPARAM, POINT, RECT, TRUE, WPARAM},
         Graphics::{
             Dwm::{DWMWA_CLOAKED, DWMWA_EXTENDED_FRAME_BOUNDS, DwmGetWindowAttribute},
             Gdi::{
@@ -26,10 +18,6 @@ use windows::{
         },
         Storage::FileSystem::{GetFileVersionInfoSizeW, GetFileVersionInfoW, VerQueryValueW},
         System::{
-            Registry::{
-                HKEY, HKEY_LOCAL_MACHINE, KEY_READ, REG_BINARY, REG_SZ, RegCloseKey, RegEnumKeyExW,
-                RegOpenKeyExW, RegQueryValueExW,
-            },
             Threading::{
                 GetCurrentProcessId, OpenProcess, PROCESS_NAME_FORMAT,
                 PROCESS_QUERY_LIMITED_INFORMATION, QueryFullProcessImageNameW,
@@ -63,6 +51,14 @@ use crate::bounds::{LogicalSize, PhysicalBounds, PhysicalPosition, PhysicalSize}
 // On Windows it's nigh impossible to get the logical position of a display
 // or window, since there's no simple API that accounts for each monitor having different DPI.
 
+static IGNORED_EXES: &'static [&str] = &[
+    // As it's a system webview it isn't owned by the Cap process.
+    "webview2",
+    "msedgewebview2",
+    // Just make sure, lol
+    "cap",
+];
+
 #[derive(Clone, Copy)]
 pub struct DisplayImpl(HMONITOR);
 
@@ -254,385 +250,6 @@ impl DisplayImpl {
         None
     }
 
-    fn get_friendly_name_from_displayconfig(&self) -> Option<String> {
-        unsafe {
-            // Get the device name first
-            let mut info = MONITORINFOEXW::default();
-            info.monitorInfo.cbSize = mem::size_of::<MONITORINFOEXW>() as u32;
-
-            if !GetMonitorInfoW(self.0, &mut info as *mut _ as *mut _).as_bool() {
-                return None;
-            }
-
-            let device_name = &info.szDevice;
-            let null_pos = device_name
-                .iter()
-                .position(|&c| c == 0)
-                .unwrap_or(device_name.len());
-            let device_name_str = String::from_utf16_lossy(&device_name[..null_pos]);
-
-            // Get display configuration
-            let mut num_paths = 0u32;
-            let mut num_modes = 0u32;
-
-            if GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &mut num_paths, &mut num_modes)
-                != WIN32_ERROR(0)
-            {
-                return None;
-            }
-
-            let mut paths = vec![DISPLAYCONFIG_PATH_INFO::default(); num_paths as usize];
-            let mut modes = vec![DISPLAYCONFIG_MODE_INFO::default(); num_modes as usize];
-
-            if QueryDisplayConfig(
-                QDC_ONLY_ACTIVE_PATHS,
-                &mut num_paths,
-                paths.as_mut_ptr(),
-                &mut num_modes,
-                modes.as_mut_ptr(),
-                None,
-            ) != WIN32_ERROR(0)
-            {
-                return None;
-            }
-
-            // Find the matching path for our monitor
-            for path in &paths {
-                // Get source device name to match with our monitor
-                let mut source_name = DISPLAYCONFIG_SOURCE_DEVICE_NAME {
-                    header: DISPLAYCONFIG_DEVICE_INFO_HEADER {
-                        r#type: DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME,
-                        size: mem::size_of::<DISPLAYCONFIG_SOURCE_DEVICE_NAME>() as u32,
-                        adapterId: path.sourceInfo.adapterId,
-                        id: path.sourceInfo.id,
-                    },
-                    viewGdiDeviceName: [0; 32],
-                };
-
-                if DisplayConfigGetDeviceInfo(&mut source_name.header as *mut _ as *mut _) != 0 {
-                    continue;
-                }
-
-                let source_device_name = String::from_utf16_lossy(&source_name.viewGdiDeviceName);
-                let source_null_pos = source_device_name
-                    .chars()
-                    .position(|c| c == '\0')
-                    .unwrap_or(source_device_name.len());
-                let source_trimmed = &source_device_name[..source_null_pos];
-
-                // Check if this matches our monitor
-                if source_trimmed == device_name_str {
-                    // Get the target (monitor) friendly name
-                    let mut target_name = DISPLAYCONFIG_TARGET_DEVICE_NAME {
-                        header: DISPLAYCONFIG_DEVICE_INFO_HEADER {
-                            r#type: DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME,
-                            size: mem::size_of::<DISPLAYCONFIG_TARGET_DEVICE_NAME>() as u32,
-                            adapterId: path.sourceInfo.adapterId,
-                            id: path.targetInfo.id,
-                        },
-                        flags: DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS::default(),
-                        outputTechnology: DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY::default(),
-                        edidManufactureId: 0,
-                        edidProductCodeId: 0,
-                        connectorInstance: 0,
-                        monitorFriendlyDeviceName: [0; 64],
-                        monitorDevicePath: [0; 128],
-                    };
-
-                    if DisplayConfigGetDeviceInfo(&mut target_name.header as *mut _ as *mut _) == 0
-                    {
-                        let friendly_name =
-                            String::from_utf16_lossy(&target_name.monitorFriendlyDeviceName);
-                        let null_pos = friendly_name
-                            .chars()
-                            .position(|c| c == '\0')
-                            .unwrap_or(friendly_name.len());
-                        let trimmed_name = friendly_name[..null_pos].trim();
-
-                        if !trimmed_name.is_empty() && trimmed_name != "Generic PnP Monitor" {
-                            return Some(trimmed_name.to_string());
-                        }
-                    }
-                }
-            }
-        }
-
-        None
-    }
-
-    fn get_friendly_name_from_wmi(&self) -> Option<String> {
-        unsafe {
-            // Get the device name first for matching
-            let mut info = MONITORINFOEXW::default();
-            info.monitorInfo.cbSize = mem::size_of::<MONITORINFOEXW>() as u32;
-
-            if !GetMonitorInfoW(self.0, &mut info as *mut _ as *mut _).as_bool() {
-                return None;
-            }
-
-            let device_name = &info.szDevice;
-            let null_pos = device_name
-                .iter()
-                .position(|&c| c == 0)
-                .unwrap_or(device_name.len());
-            let device_name_str = String::from_utf16_lossy(&device_name[..null_pos]);
-
-            // Try alternative registry paths for monitor information
-            let alt_registry_paths = [
-                format!(
-                    "SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\Configuration\\{}",
-                    device_name_str.replace("\\\\.\\", "")
-                ),
-                format!(
-                    "SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Control\\VIDEO\\{}",
-                    device_name_str.replace("\\\\.\\DISPLAY", "")
-                ),
-            ];
-
-            for registry_path in &alt_registry_paths {
-                let registry_path_wide: Vec<u16> = registry_path
-                    .encode_utf16()
-                    .chain(std::iter::once(0))
-                    .collect();
-
-                let mut key: HKEY = HKEY::default();
-                if RegOpenKeyExW(
-                    HKEY_LOCAL_MACHINE,
-                    PCWSTR(registry_path_wide.as_ptr()),
-                    Some(0),
-                    KEY_READ,
-                    &mut key,
-                )
-                .is_ok()
-                {
-                    // Try to get monitor description from alternative locations
-                    let value_names = ["Monitor_Name", "Description", "FriendlyName"];
-
-                    for value_name in &value_names {
-                        let value_name_wide = format!("{}\0", value_name)
-                            .encode_utf16()
-                            .collect::<Vec<u16>>();
-                        let mut buffer = [0u16; 512];
-                        let mut buffer_size = (buffer.len() * 2) as u32;
-                        let mut value_type = REG_SZ;
-
-                        if RegQueryValueExW(
-                            key,
-                            PCWSTR(value_name_wide.as_ptr()),
-                            None,
-                            Some(&mut value_type),
-                            Some(buffer.as_mut_ptr() as *mut u8),
-                            Some(&mut buffer_size),
-                        )
-                        .is_ok()
-                        {
-                            let null_pos =
-                                buffer.iter().position(|&c| c == 0).unwrap_or(buffer.len());
-                            let desc = String::from_utf16_lossy(&buffer[..null_pos]);
-                            let cleaned_name = desc.trim().to_string();
-
-                            if !cleaned_name.is_empty() && cleaned_name != "Default Monitor" {
-                                let _ = RegCloseKey(key);
-                                return Some(cleaned_name);
-                            }
-                        }
-                    }
-                    let _ = RegCloseKey(key);
-                }
-            }
-        }
-        None
-    }
-
-    fn get_friendly_name_from_registry(&self, device_name: &str) -> Option<String> {
-        unsafe {
-            // Try multiple registry paths for better name resolution
-            let registry_paths = [
-                format!(
-                    "SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\{}",
-                    device_name.replace("\\\\.\\", "")
-                ),
-                format!(
-                    "SYSTEM\\CurrentControlSet\\Control\\Class\\{{4d36e96e-e325-11ce-bfc1-08002be10318}}"
-                ),
-            ];
-
-            for registry_path in &registry_paths {
-                let registry_path_wide: Vec<u16> = registry_path
-                    .encode_utf16()
-                    .chain(std::iter::once(0))
-                    .collect();
-
-                let mut key: HKEY = HKEY::default();
-                if RegOpenKeyExW(
-                    HKEY_LOCAL_MACHINE,
-                    PCWSTR(registry_path_wide.as_ptr()),
-                    Some(0),
-                    KEY_READ,
-                    &mut key,
-                )
-                .is_ok()
-                {
-                    // Try multiple value names for better localization
-                    let value_names = ["FriendlyName", "DeviceDesc", "DriverDesc"];
-
-                    for value_name in &value_names {
-                        let value_name_wide = format!("{}\0", value_name)
-                            .encode_utf16()
-                            .collect::<Vec<u16>>();
-                        let mut buffer = [0u16; 512];
-                        let mut buffer_size = (buffer.len() * 2) as u32;
-                        let mut value_type = REG_SZ;
-
-                        if RegQueryValueExW(
-                            key,
-                            PCWSTR(value_name_wide.as_ptr()),
-                            None,
-                            Some(&mut value_type),
-                            Some(buffer.as_mut_ptr() as *mut u8),
-                            Some(&mut buffer_size),
-                        )
-                        .is_ok()
-                        {
-                            let null_pos =
-                                buffer.iter().position(|&c| c == 0).unwrap_or(buffer.len());
-                            let desc = String::from_utf16_lossy(&buffer[..null_pos]);
-
-                            // Clean up the description
-                            let cleaned_name = if let Some(semicolon_pos) = desc.rfind(';') {
-                                desc[semicolon_pos + 1..].trim().to_string()
-                            } else {
-                                desc.trim().to_string()
-                            };
-
-                            if !cleaned_name.is_empty()
-                                && !cleaned_name.contains("PCI\\VEN_")
-                                && cleaned_name != "Generic PnP Monitor"
-                            {
-                                let _ = RegCloseKey(key);
-                                return Some(cleaned_name);
-                            }
-                        }
-                    }
-                    let _ = RegCloseKey(key);
-                }
-            }
-        }
-        None
-    }
-
-    fn get_friendly_name_from_edid(&self, device_name: &str) -> Option<String> {
-        unsafe {
-            // Registry path for EDID data
-            let edid_path = format!(
-                "SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\{}",
-                device_name.replace("\\\\.\\", "")
-            );
-            let edid_path_wide: Vec<u16> =
-                edid_path.encode_utf16().chain(std::iter::once(0)).collect();
-
-            let mut key: HKEY = HKEY::default();
-            if RegOpenKeyExW(
-                HKEY_LOCAL_MACHINE,
-                PCWSTR(edid_path_wide.as_ptr()),
-                Some(0),
-                KEY_READ,
-                &mut key,
-            )
-            .is_ok()
-            {
-                // Enumerate subkeys to find device instances
-                let mut index = 0;
-                loop {
-                    let mut subkey_name = [0u16; 256];
-                    let mut subkey_size = subkey_name.len() as u32;
-
-                    if RegEnumKeyExW(
-                        key,
-                        index,
-                        Some(PWSTR(subkey_name.as_mut_ptr())),
-                        &mut subkey_size,
-                        None,
-                        Some(PWSTR::null()),
-                        None,
-                        None,
-                    )
-                    .is_err()
-                    {
-                        break;
-                    }
-
-                    // Open device parameters subkey
-                    let subkey_str = String::from_utf16_lossy(&subkey_name[..subkey_size as usize]);
-                    let params_path = format!("{}\\Device Parameters", subkey_str);
-                    let params_path_wide: Vec<u16> = params_path
-                        .encode_utf16()
-                        .chain(std::iter::once(0))
-                        .collect();
-
-                    let mut params_key: HKEY = HKEY::default();
-                    if RegOpenKeyExW(
-                        key,
-                        PCWSTR(params_path_wide.as_ptr()),
-                        Some(0),
-                        KEY_READ,
-                        &mut params_key,
-                    )
-                    .is_ok()
-                    {
-                        // Read EDID data
-                        let edid_value = "EDID\0".encode_utf16().collect::<Vec<u16>>();
-                        let mut edid_buffer = [0u8; 256];
-                        let mut edid_size = edid_buffer.len() as u32;
-                        let mut value_type = REG_BINARY;
-
-                        if RegQueryValueExW(
-                            params_key,
-                            PCWSTR(edid_value.as_ptr()),
-                            None,
-                            Some(&mut value_type),
-                            Some(edid_buffer.as_mut_ptr()),
-                            Some(&mut edid_size),
-                        )
-                        .is_ok()
-                            && edid_size >= 128
-                        {
-                            // Parse EDID for monitor name (descriptor blocks start at offset 54)
-                            for i in (54..126).step_by(18) {
-                                if i + 18 > edid_buffer.len() {
-                                    break;
-                                }
-                                if edid_buffer[i] == 0
-                                    && edid_buffer[i + 1] == 0
-                                    && edid_buffer[i + 2] == 0
-                                    && edid_buffer[i + 3] == 0xFC
-                                {
-                                    // Monitor name descriptor found
-                                    if i + 18 <= edid_buffer.len() {
-                                        let name_bytes = &edid_buffer[i + 5..i + 18];
-                                        let name_str = String::from_utf8_lossy(name_bytes);
-                                        let name =
-                                            name_str.trim_end_matches('\0').trim().to_string();
-
-                                        if !name.is_empty() {
-                                            let _ = RegCloseKey(params_key);
-                                            let _ = RegCloseKey(key);
-                                            return Some(name);
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        let _ = RegCloseKey(params_key);
-                    }
-                    index += 1;
-                }
-                let _ = RegCloseKey(key);
-            }
-        }
-        None
-    }
-
     pub fn try_as_capture_item(&self) -> windows::core::Result<GraphicsCaptureItem> {
         let interop = windows::core::factory::<GraphicsCaptureItem, IGraphicsCaptureItemInterop>()?;
         unsafe { interop.CreateForMonitor(self.0) }
@@ -907,9 +524,8 @@ impl WindowImpl {
 
     pub fn app_icon(&self) -> Option<Vec<u8>> {
         unsafe {
-            // Try multiple approaches to get the highest quality icon
-            let mut best_result = None;
-            let mut best_size = 0;
+            // Target size for acceptable icon quality - early termination threshold
+            const GOOD_SIZE_THRESHOLD: i32 = 64;
 
             // Method 1: Try to get the window's large icon first
             let large_icon = SendMessageW(
@@ -920,89 +536,80 @@ impl WindowImpl {
             ); // ICON_BIG = 1
 
             if large_icon.0 != 0 {
-                if let Some(result) = self.hicon_to_png_bytes_high_res(HICON(large_icon.0 as _)) {
-                    best_result = Some(result.0);
-                    best_size = result.1;
+                if let Some(result) = self.hicon_to_png_bytes_optimized(HICON(large_icon.0 as _)) {
+                    // If we got a good quality icon, return it immediately
+                    if result.1 >= GOOD_SIZE_THRESHOLD {
+                        return Some(result.0);
+                    }
                 }
             }
 
-            // Method 2: Try executable file extraction with priority on larger icons
+            // Method 2: Try executable file extraction (only first icon, most likely to be main app icon)
             if let Some(exe_path) = self.get_executable_path() {
                 let wide_path: Vec<u16> =
                     exe_path.encode_utf16().chain(std::iter::once(0)).collect();
 
-                // Try extracting icons from multiple indices
-                for icon_index in 0..6 {
-                    let mut large_icon: HICON = HICON::default();
-                    let mut small_icon: HICON = HICON::default();
-
-                    let extracted = ExtractIconExW(
-                        PCWSTR(wide_path.as_ptr()),
-                        icon_index,
-                        Some(&mut large_icon),
-                        Some(&mut small_icon),
-                        1,
-                    );
-
-                    if extracted > 0 {
-                        // Try large icon first
-                        if !large_icon.is_invalid() {
-                            if let Some(result) = self.hicon_to_png_bytes_high_res(large_icon) {
-                                if result.1 > best_size {
-                                    best_result = Some(result.0);
-                                    best_size = result.1;
-                                }
-                            }
+                let mut large_icon: HICON = HICON::default();
+                let mut small_icon: HICON = HICON::default();
+
+                let extracted = ExtractIconExW(
+                    PCWSTR(wide_path.as_ptr()),
+                    0, // Only try the first (main) icon
+                    Some(&mut large_icon),
+                    Some(&mut small_icon),
+                    1,
+                );
+
+                if extracted > 0 {
+                    // Try large icon first
+                    if !large_icon.is_invalid() {
+                        if let Some(result) = self.hicon_to_png_bytes_optimized(large_icon) {
                             let _ = DestroyIcon(large_icon);
+                            if !small_icon.is_invalid() {
+                                let _ = DestroyIcon(small_icon);
+                            }
+                            // Return immediately if we got a good quality icon
+                            if result.1 >= GOOD_SIZE_THRESHOLD {
+                                return Some(result.0);
+                            }
                         }
+                        let _ = DestroyIcon(large_icon);
+                    }
 
-                        // Try small icon if we haven't found anything good yet
-                        if !small_icon.is_invalid() && best_size < 64 {
-                            if let Some(result) = self.hicon_to_png_bytes_high_res(small_icon) {
-                                if result.1 > best_size {
-                                    best_result = Some(result.0);
-                                    best_size = result.1;
-                                }
-                            }
+                    // Try small icon as fallback
+                    if !small_icon.is_invalid() {
+                        if let Some(result) = self.hicon_to_png_bytes_optimized(small_icon) {
                             let _ = DestroyIcon(small_icon);
+                            return Some(result.0);
                         }
+                        let _ = DestroyIcon(small_icon);
                     }
                 }
             }
 
-            // Method 3: Try small window icon if we still don't have anything good
-            if best_size < 32 {
-                let small_icon = SendMessageW(
-                    self.0,
-                    WM_GETICON,
-                    Some(WPARAM(0usize)),
-                    Some(LPARAM(0isize)),
-                ); // ICON_SMALL = 0
-
-                if small_icon.0 != 0 {
-                    if let Some(result) = self.hicon_to_png_bytes_high_res(HICON(small_icon.0 as _))
-                    {
-                        if result.1 > best_size {
-                            best_result = Some(result.0);
-                            best_size = result.1;
-                        }
-                    }
+            // Method 3: Try small window icon as fallback
+            let small_icon = SendMessageW(
+                self.0,
+                WM_GETICON,
+                Some(WPARAM(0usize)),
+                Some(LPARAM(0isize)),
+            ); // ICON_SMALL = 0
+
+            if small_icon.0 != 0 {
+                if let Some(result) = self.hicon_to_png_bytes_optimized(HICON(small_icon.0 as _)) {
+                    return Some(result.0);
                 }
             }
 
             // Method 4: Try class icon as last resort
-            if best_size < 32 {
-                let class_icon = GetClassLongPtrW(self.0, GCLP_HICON) as isize;
-                if class_icon != 0 {
-                    if let Some(result) = self.hicon_to_png_bytes_high_res(HICON(class_icon as _)) {
-                        if result.1 > best_size {
-                            best_result = Some(result.0);
-                        }
-                    }
+            let class_icon = GetClassLongPtrW(self.0, GCLP_HICON) as isize;
+            if class_icon != 0 {
+                if let Some(result) = self.hicon_to_png_bytes_optimized(HICON(class_icon as _)) {
+                    return Some(result.0);
                 }
             }
 
-            best_result
+            None
         }
     }
 
@@ -1065,7 +672,7 @@ impl WindowImpl {
         }
     }
 
-    fn hicon_to_png_bytes_high_res(&self, icon: HICON) -> Option<(Vec<u8>, i32)> {
+    fn hicon_to_png_bytes_optimized(&self, icon: HICON) -> Option<(Vec<u8>, i32)> {
         unsafe {
             // Get icon info to determine actual size
             let mut icon_info = ICONINFO::default();
@@ -1080,133 +687,156 @@ impl WindowImpl {
             // Get the native icon size to prioritize it
             let native_size = self.get_icon_size(icon);
 
-            // Always try for the highest resolution possible, starting with the largest sizes
-            let mut sizes = vec![2048, 1024, 512, 256, 128, 96, 64, 48, 32, 24, 16];
-
-            // If we have native size info, prioritize it
-            if let Some((width, height)) = native_size {
+            // Determine the best size to try based on native size
+            let target_sizes = if let Some((width, height)) = native_size {
                 let native_dim = width.max(height);
-                const MAX_SIZE: i32 = 4096;
-                if !sizes.contains(&native_dim) && native_dim > 0 && native_dim <= MAX_SIZE {
-                    sizes.insert(0, native_dim);
+                if native_dim >= 256 {
+                    vec![native_dim, 256, 128] // High-res icon
+                } else if native_dim >= 64 {
+                    vec![native_dim, 64, 32] // Medium-res icon
+                } else if native_dim >= 32 {
+                    vec![native_dim, 32, 16] // Standard icon
+                } else {
+                    vec![32, 16] // Small icon, try standard sizes
                 }
-            }
+            } else {
+                // No native size info, try reasonable defaults
+                vec![128, 64, 32, 16]
+            };
 
-            let mut best_result = None;
-            let mut best_size = 0;
-
-            for &size in &sizes {
-                let width = size;
-                let height = size;
-
-                // Create bitmap info for this size
-                let mut bitmap_info = BITMAPINFO {
-                    bmiHeader: BITMAPINFOHEADER {
-                        biSize: mem::size_of::<BITMAPINFOHEADER>() as u32,
-                        biWidth: width,
-                        biHeight: -height, // Top-down DIB
-                        biPlanes: 1,
-                        biBitCount: 32, // 32 bits per pixel (BGRA)
-                        biCompression: BI_RGB.0,
-                        biSizeImage: 0,
-                        biXPelsPerMeter: 0,
-                        biYPelsPerMeter: 0,
-                        biClrUsed: 0,
-                        biClrImportant: 0,
-                    },
-                    bmiColors: [Default::default(); 1],
-                };
+            // Try each target size, return the first successful one
+            for &size in &target_sizes {
+                if let Some(result) = self.try_convert_icon_to_png(icon, size, screen_dc, mem_dc) {
+                    // Cleanup
+                    let _ = DeleteDC(mem_dc);
+                    let _ = ReleaseDC(Some(HWND::default()), screen_dc);
+                    let _ = DeleteObject(icon_info.hbmColor.into());
+                    let _ = DeleteObject(icon_info.hbmMask.into());
 
-                // Create a bitmap
-                let bitmap = CreateCompatibleBitmap(screen_dc, width, height);
-                if bitmap.is_invalid() {
-                    continue;
+                    return Some((result, size));
                 }
+            }
 
-                let old_bitmap = SelectObject(mem_dc, bitmap.into());
+            // Cleanup
+            let _ = DeleteDC(mem_dc);
+            let _ = ReleaseDC(Some(HWND::default()), screen_dc);
+            let _ = DeleteObject(icon_info.hbmColor.into());
+            let _ = DeleteObject(icon_info.hbmMask.into());
 
-                // Fill with transparent background
-                let brush = CreateSolidBrush(windows::Win32::Foundation::COLORREF(0));
-                let rect = RECT {
-                    left: 0,
-                    top: 0,
-                    right: width,
-                    bottom: height,
-                };
-                let _ = FillRect(mem_dc, &rect, brush);
-                let _ = DeleteObject(brush.into());
+            None
+        }
+    }
 
-                // Draw the icon onto the bitmap with proper scaling
-                let draw_result = DrawIconEx(
+    fn try_convert_icon_to_png(
+        &self,
+        icon: HICON,
+        size: i32,
+        screen_dc: HDC,
+        mem_dc: HDC,
+    ) -> Option<Vec<u8>> {
+        unsafe {
+            let width = size;
+            let height = size;
+
+            // Create bitmap info for this size
+            let mut bitmap_info = BITMAPINFO {
+                bmiHeader: BITMAPINFOHEADER {
+                    biSize: mem::size_of::<BITMAPINFOHEADER>() as u32,
+                    biWidth: width,
+                    biHeight: -height, // Top-down DIB
+                    biPlanes: 1,
+                    biBitCount: 32, // 32 bits per pixel (BGRA)
+                    biCompression: BI_RGB.0,
+                    biSizeImage: 0,
+                    biXPelsPerMeter: 0,
+                    biYPelsPerMeter: 0,
+                    biClrUsed: 0,
+                    biClrImportant: 0,
+                },
+                bmiColors: [Default::default(); 1],
+            };
+
+            // Create a bitmap
+            let bitmap = CreateCompatibleBitmap(screen_dc, width, height);
+            if bitmap.is_invalid() {
+                return None;
+            }
+
+            let old_bitmap = SelectObject(mem_dc, bitmap.into());
+
+            // Fill with transparent background
+            let brush = CreateSolidBrush(windows::Win32::Foundation::COLORREF(0));
+            let rect = RECT {
+                left: 0,
+                top: 0,
+                right: width,
+                bottom: height,
+            };
+            let _ = FillRect(mem_dc, &rect, brush);
+            let _ = DeleteObject(brush.into());
+
+            // Draw the icon onto the bitmap with proper scaling
+            let draw_result = DrawIconEx(
+                mem_dc,
+                0,
+                0,
+                icon,
+                width,
+                height,
+                0,
+                Some(HBRUSH::default()),
+                DI_FLAGS(0x0003), // DI_NORMAL
+            );
+
+            let mut result = None;
+
+            if draw_result.is_ok() {
+                // Get bitmap bits
+                let mut buffer = vec![0u8; (width * height * 4) as usize];
+                let get_bits_result = GetDIBits(
                     mem_dc,
+                    bitmap,
                     0,
-                    0,
-                    icon,
-                    width,
-                    height,
-                    0,
-                    Some(HBRUSH::default()),
-                    DI_FLAGS(0x0003), // DI_NORMAL
+                    height as u32,
+                    Some(buffer.as_mut_ptr() as *mut _),
+                    &mut bitmap_info,
+                    DIB_RGB_COLORS,
                 );
 
-                if draw_result.is_ok() {
-                    // Get bitmap bits
-                    let mut buffer = vec![0u8; (width * height * 4) as usize];
-                    let result = GetDIBits(
-                        mem_dc,
-                        bitmap,
-                        0,
-                        height as u32,
-                        Some(buffer.as_mut_ptr() as *mut _),
-                        &mut bitmap_info,
-                        DIB_RGB_COLORS,
-                    );
-
-                    if result > 0 {
-                        // Check if we have any non-transparent pixels
-                        let has_content = buffer.chunks_exact(4).any(|chunk| chunk[3] != 0);
-
-                        if has_content {
-                            // Convert BGRA to RGBA
-                            for chunk in buffer.chunks_exact_mut(4) {
-                                chunk.swap(0, 2); // Swap B and R
-                            }
+                if get_bits_result > 0 {
+                    // Check if we have any non-transparent pixels
+                    let has_content = buffer.chunks_exact(4).any(|chunk| chunk[3] != 0);
+
+                    if has_content {
+                        // Convert BGRA to RGBA
+                        for chunk in buffer.chunks_exact_mut(4) {
+                            chunk.swap(0, 2); // Swap B and R
+                        }
 
-                            // Create PNG using the image crate
-                            if let Some(img) =
-                                image::RgbaImage::from_raw(width as u32, height as u32, buffer)
+                        // Create PNG using the image crate
+                        if let Some(img) =
+                            image::RgbaImage::from_raw(width as u32, height as u32, buffer)
+                        {
+                            let mut png_data = Vec::new();
+                            if img
+                                .write_to(
+                                    &mut std::io::Cursor::new(&mut png_data),
+                                    image::ImageFormat::Png,
+                                )
+                                .is_ok()
                             {
-                                let mut png_data = Vec::new();
-                                if img
-                                    .write_to(
-                                        &mut std::io::Cursor::new(&mut png_data),
-                                        image::ImageFormat::Png,
-                                    )
-                                    .is_ok()
-                                {
-                                    // Keep the result if it's our first success or if this size is larger
-                                    if best_result.is_none() || size > best_size {
-                                        best_result = Some((png_data, size));
-                                        best_size = size;
-                                    }
-                                }
+                                result = Some(png_data);
                             }
                         }
                     }
                 }
-
-                // Cleanup for this iteration
-                let _ = SelectObject(mem_dc, old_bitmap);
-                let _ = DeleteObject(bitmap.into());
             }
 
-            // Cleanup
-            let _ = DeleteDC(mem_dc);
-            let _ = ReleaseDC(Some(HWND::default()), screen_dc);
-            let _ = DeleteObject(icon_info.hbmColor.into());
-            let _ = DeleteObject(icon_info.hbmMask.into());
+            // Cleanup for this iteration
+            let _ = SelectObject(mem_dc, old_bitmap);
+            let _ = DeleteObject(bitmap.into());
 
-            best_result
+            result
         }
     }
 
@@ -1369,6 +999,15 @@ impl WindowImpl {
             return false;
         }
 
+        // Also skip WebView2 and Cap-related processes
+        if let Ok(exe_path) = unsafe { pid_to_exe_path(id) } {
+            if let Some(exe_name) = exe_path.file_name().and_then(|n| n.to_str()) {
+                if IGNORED_EXES.contains(&&*exe_name.to_lowercase()) {
+                    return false;
+                }
+            }
+        }
+
         let mut rect = RECT::default();
         let result = unsafe { GetClientRect(self.0, &mut rect) };
         if result.is_ok() {
@@ -1399,7 +1038,20 @@ fn is_window_valid_for_enumeration(hwnd: HWND, current_process_id: u32) -> bool
         // Skip own process windows
         let mut process_id = 0u32;
         GetWindowThreadProcessId(hwnd, Some(&mut process_id));
-        process_id != current_process_id
+        if process_id == current_process_id {
+            return false;
+        }
+
+        // Also skip WebView2 and Cap-related processes
+        if let Ok(exe_path) = pid_to_exe_path(process_id) {
+            if let Some(exe_name) = exe_path.file_name().and_then(|n| n.to_str()) {
+                if IGNORED_EXES.contains(&&*exe_name.to_lowercase()) {
+                    return false;
+                }
+            }
+        }
+
+        true
     }
 }
 
@@ -1421,6 +1073,19 @@ fn is_window_valid_for_topmost_selection(
             return false;
         }
 
+        // Also skip WebView2 and Cap-related processes
+        if let Ok(exe_path) = pid_to_exe_path(process_id) {
+            if let Some(exe_name) = exe_path.file_name().and_then(|n| n.to_str()) {
+                let exe_name_lower = exe_name.to_lowercase();
+                if exe_name_lower.contains("webview2")
+                    || exe_name_lower.contains("msedgewebview2")
+                    || exe_name_lower.contains("cap")
+                {
+                    return false;
+                }
+            }
+        }
+
         // Check if point is actually in this window
         if !is_point_in_window(hwnd, point) {
             return false;
diff --git a/packages/ui-solid/icons/caret-down.svg b/packages/ui-solid/icons/caret-down.svg
new file mode 100644
index 0000000000..0a4bb6787a
--- /dev/null
+++ b/packages/ui-solid/icons/caret-down.svg
@@ -0,0 +1,3 @@
+<svg width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.80763 1.18378L5.46126 5.79649C5.40069 5.861 5.32872 5.91218 5.24947 5.9471C5.17023 5.98202 5.08526 6 4.99946 6C4.91365 6 4.82869 5.98202 4.74944 5.9471C4.67019 5.91218 4.59822 5.861 4.53765 5.79649L0.191285 1.18378C0.0688072 1.0538 -1.82506e-09 0.877507 0 0.693683C1.82506e-09 0.50986 0.0688072 0.333566 0.191285 0.203583C0.313762 0.0736001 0.479877 0.000576714 0.653086 0.000576712C0.826296 0.00057671 0.992411 0.0736001 1.11489 0.203583L5 4.32677L8.88511 0.203007C9.00759 0.0730239 9.1737 0 9.34691 0C9.52012 0 9.68624 0.0730239 9.80871 0.203007C9.93119 0.332989 10 0.509284 10 0.693107C10 0.87693 9.93119 1.05322 9.80871 1.18321L9.80763 1.18378Z" fill="white"/>
+</svg>
diff --git a/packages/ui-solid/icons/ellipsis-menu.svg b/packages/ui-solid/icons/ellipsis-menu.svg
new file mode 100644
index 0000000000..5238aae79c
--- /dev/null
+++ b/packages/ui-solid/icons/ellipsis-menu.svg
@@ -0,0 +1,5 @@
+<svg width="26" height="6" viewBox="0 0 26 6" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="3" cy="3" r="3" fill="#ABABAB"/>
+<circle cx="13" cy="3" r="3" fill="#ABABAB"/>
+<circle cx="23" cy="3" r="3" fill="#ABABAB"/>
+</svg>
diff --git a/packages/ui-solid/icons/gear.svg b/packages/ui-solid/icons/gear.svg
new file mode 100644
index 0000000000..152b22dd61
--- /dev/null
+++ b/packages/ui-solid/icons/gear.svg
@@ -0,0 +1,12 @@
+<svg
+	width="16"
+	height="16"
+	viewBox="0 0 16 16"
+	fill="none"
+	xmlns="http://www.w3.org/2000/svg"
+>
+<path
+		d="M15.4286 7.42857H14.8329C14.766 6.6137 14.5526 5.81759 14.2029 5.07857L14.7193 4.78071C14.8506 4.70494 14.9464 4.58011 14.9856 4.4337C15.0249 4.28729 15.0043 4.13128 14.9286 4C14.8528 3.86872 14.728 3.77291 14.5816 3.73367C14.4351 3.69442 14.2791 3.71494 14.1479 3.79071L13.63 4.09C13.1626 3.41972 12.5803 2.83742 11.91 2.37L12.2093 1.85214C12.2851 1.72086 12.3056 1.56485 12.2663 1.41844C12.2271 1.27203 12.1313 1.1472 12 1.07143C11.8687 0.995652 11.7127 0.975132 11.5663 1.01438C11.4199 1.05363 11.2951 1.14943 11.2193 1.28071L10.9214 1.79714C10.1824 1.44738 9.3863 1.23396 8.57143 1.16714V0.571429C8.57143 0.419876 8.51123 0.274531 8.40406 0.167368C8.2969 0.0602039 8.15155 0 8 0C7.84845 0 7.7031 0.0602039 7.59594 0.167368C7.48878 0.274531 7.42857 0.419876 7.42857 0.571429V1.16714C6.6137 1.23396 5.81759 1.44738 5.07857 1.79714L4.78071 1.28071C4.70494 1.14943 4.58011 1.05363 4.4337 1.01438C4.28729 0.975132 4.13128 0.995652 4 1.07143C3.86872 1.1472 3.77291 1.27203 3.73367 1.41844C3.69442 1.56485 3.71494 1.72086 3.79071 1.85214L4.09 2.37C3.41972 2.83742 2.83742 3.41972 2.37 4.09L1.85214 3.79071C1.78714 3.75319 1.71538 3.72884 1.64097 3.71906C1.56655 3.70927 1.49094 3.71423 1.41844 3.73367C1.27203 3.77291 1.1472 3.86872 1.07143 4C0.995652 4.13128 0.975132 4.28729 1.01438 4.4337C1.05363 4.58011 1.14943 4.70494 1.28071 4.78071L1.79714 5.07857C1.44738 5.81759 1.23396 6.6137 1.16714 7.42857H0.571429C0.419876 7.42857 0.274531 7.48878 0.167368 7.59594C0.0602039 7.7031 0 7.84845 0 8C0 8.15155 0.0602039 8.2969 0.167368 8.40406C0.274531 8.51123 0.419876 8.57143 0.571429 8.57143H1.16714C1.23396 9.3863 1.44738 10.1824 1.79714 10.9214L1.28071 11.2193C1.17171 11.2822 1.08651 11.3792 1.03833 11.4955C0.990146 11.6117 0.98168 11.7406 1.01424 11.8622C1.04681 11.9837 1.11858 12.0911 1.21842 12.1677C1.31827 12.2443 1.4406 12.2858 1.56643 12.2857C1.66676 12.286 1.76537 12.2596 1.85214 12.2093L2.37 11.91C2.83742 12.5803 3.41972 13.1626 4.09 13.63L3.79071 14.1479C3.71494 14.2791 3.69442 14.4351 3.73367 14.5816C3.77291 14.728 3.86872 14.8528 4 14.9286C4.13128 15.0043 4.28729 15.0249 4.4337 14.9856C4.58011 14.9464 4.70494 14.8506 4.78071 14.7193L5.07857 14.2029C5.81759 14.5526 6.6137 14.766 7.42857 14.8329V15.4286C7.42857 15.5801 7.48878 15.7255 7.59594 15.8326C7.7031 15.9398 7.84845 16 8 16C8.15155 16 8.2969 15.9398 8.40406 15.8326C8.51123 15.7255 8.57143 15.5801 8.57143 15.4286V14.8329C9.3863 14.766 10.1824 14.5526 10.9214 14.2029L11.2193 14.7193C11.2951 14.8506 11.4199 14.9464 11.5663 14.9856C11.7127 15.0249 11.8687 15.0043 12 14.9286C12.1313 14.8528 12.2271 14.728 12.2663 14.5816C12.3056 14.4351 12.2851 14.2791 12.2093 14.1479L11.91 13.63C12.5803 13.1626 13.1626 12.5803 13.63 11.91L14.1479 12.2093C14.2129 12.2468 14.2846 12.2712 14.359 12.281C14.4335 12.2908 14.5091 12.2858 14.5816 12.2664C14.6541 12.2469 14.722 12.2134 14.7816 12.1677C14.8411 12.122 14.8911 12.065 14.9286 12C15.0044 11.8688 15.0251 11.7129 14.986 11.5664C14.9469 11.42 14.8512 11.2952 14.72 11.2193L14.2036 10.9214C14.5533 10.1824 14.7668 9.3863 14.8336 8.57143H15.4286C15.5801 8.57143 15.7255 8.51123 15.8326 8.40406C15.9398 8.2969 16 8.15155 16 8C16 7.84845 15.9398 7.7031 15.8326 7.59594C15.7255 7.48878 15.5801 7.42857 15.4286 7.42857ZM4 8C3.99971 7.39465 4.13703 6.79716 4.4016 6.25268C4.66616 5.70821 5.05104 5.23101 5.52714 4.85714L7.34 8L5.52714 11.1429C5.05104 10.769 4.66616 10.2918 4.4016 9.74732C4.13703 9.20284 3.99971 8.60535 4 8ZM8 12C7.49152 12.0005 6.98766 11.9035 6.51571 11.7143L8.33 8.57143H11.9586C11.8199 9.5228 11.3437 10.3926 10.617 11.022C9.89027 11.6515 8.96142 11.9986 8 12ZM8.33 7.42857L6.51571 4.28571C7.0776 4.06125 7.68308 3.96718 8.28658 4.01058C8.89007 4.05398 9.47586 4.23373 9.99984 4.53629C10.5238 4.83885 10.9723 5.25634 11.3116 5.75732C11.6509 6.2583 11.8721 6.82973 11.9586 7.42857H8.33Z"
+		fill="currentColor"
+	/>
+</svg>
diff --git a/packages/ui-solid/icons/x.svg b/packages/ui-solid/icons/x.svg
new file mode 100644
index 0000000000..ebb57ec9be
--- /dev/null
+++ b/packages/ui-solid/icons/x.svg
@@ -0,0 +1,3 @@
+<svg width="9" height="9" viewBox="0 0 9 9" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.49846 7.4817C8.60682 7.59004 8.66769 7.73699 8.66769 7.89022C8.66769 8.04345 8.60682 8.1904 8.49846 8.29875C8.39011 8.4071 8.24315 8.46797 8.08991 8.46797C7.93668 8.46797 7.78972 8.4071 7.68136 8.29875L4.62973 5.24634L1.57715 8.29779C1.46879 8.40613 1.32183 8.467 1.1686 8.467C1.01536 8.467 0.868401 8.40613 0.760047 8.29779C0.651693 8.18944 0.59082 8.04249 0.59082 7.88926C0.59082 7.73603 0.651693 7.58908 0.760047 7.48074L3.81264 4.42929L0.761008 1.37688C0.652654 1.26854 0.591782 1.12159 0.591782 0.96836C0.591782 0.815133 0.652654 0.668182 0.761008 0.559834C0.869363 0.451486 1.01632 0.390617 1.16956 0.390617C1.32279 0.390617 1.46975 0.451486 1.57811 0.559834L4.62973 3.61224L7.68232 0.559353C7.79068 0.451006 7.93764 0.390137 8.09087 0.390137C8.24411 0.390137 8.39107 0.451006 8.49942 0.559353C8.60778 0.667701 8.66865 0.814652 8.66865 0.967879C8.66865 1.12111 8.60778 1.26806 8.49942 1.3764L5.44683 4.42929L8.49846 7.4817Z" fill="black"/>
+</svg>
diff --git a/packages/ui-solid/src/auto-imports.d.ts b/packages/ui-solid/src/auto-imports.d.ts
index 0dfc727b51..e73ebf83a2 100644
--- a/packages/ui-solid/src/auto-imports.d.ts
+++ b/packages/ui-solid/src/auto-imports.d.ts
@@ -11,6 +11,7 @@ declare global {
 	const IconCapBgBlur: typeof import("~icons/cap/bg-blur.jsx")["default"];
 	const IconCapCamera: typeof import("~icons/cap/camera.jsx")["default"];
 	const IconCapCaptions: typeof import("~icons/cap/captions.jsx")["default"];
+	const IconCapCaretDown: typeof import("~icons/cap/caret-down.jsx")["default"];
 	const IconCapChevronDown: typeof import("~icons/cap/chevron-down.jsx")["default"];
 	const IconCapCircle: typeof import("~icons/cap/circle.jsx")["default"];
 	const IconCapCircleCheck: typeof import("~icons/cap/circle-check.jsx")["default"];
@@ -25,6 +26,7 @@ declare global {
 	const IconCapFile: typeof import("~icons/cap/file.jsx")["default"];
 	const IconCapFilmCut: typeof import("~icons/cap/film-cut.jsx")["default"];
 	const IconCapGauge: typeof import("~icons/cap/gauge.jsx")["default"];
+	const IconCapGear: typeof import("~icons/cap/gear.jsx")["default"];
 	const IconCapHotkeys: typeof import("~icons/cap/hotkeys.jsx")["default"];
 	const IconCapImage: typeof import("~icons/cap/image.jsx")["default"];
 	const IconCapInfo: typeof import("~icons/cap/info.jsx")["default"];
@@ -55,6 +57,7 @@ declare global {
 	const IconCapTrash: typeof import("~icons/cap/trash.jsx")["default"];
 	const IconCapUndo: typeof import("~icons/cap/undo.jsx")["default"];
 	const IconCapUpload: typeof import("~icons/cap/upload.jsx")["default"];
+	const IconCapX: typeof import("~icons/cap/x.jsx")["default"];
 	const IconCapZoomIn: typeof import("~icons/cap/zoom-in.jsx")["default"];
 	const IconCapZoomOut: typeof import("~icons/cap/zoom-out.jsx")["default"];
 	const IconHugeiconsEaseCurveControlPoints: typeof import("~icons/hugeicons/ease-curve-control-points.jsx")["default"];
@@ -83,6 +86,7 @@ declare global {
 	const IconLucideVolume2: typeof import("~icons/lucide/volume2.jsx")["default"];
 	const IconLucideVolumeX: typeof import("~icons/lucide/volume-x.jsx")["default"];
 	const IconMaterialSymbolsScreenshotFrame2Rounded: typeof import("~icons/material-symbols/screenshot-frame2-rounded.jsx")["default"];
+	const IconMdiLoading: typeof import("~icons/mdi/loading.jsx")["default"];
 	const IconMdiMonitor: typeof import("~icons/mdi/monitor.jsx")["default"];
 	const IconPhMonitorBold: typeof import("~icons/ph/monitor-bold.jsx")["default"];
 }
