git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commitc670330a068fde9a807151fb1d0d29330757e63a
parent3c881cfb96
authorLucas Galante <[email protected]>
date2026-07-05 19:20
Refactor and fix scale factor sidebar scaling bug

 src/backend/window_runner.rs             |  21 +-
 src/color.rs                             | 245 ++++++++++++++
 src/layout.rs                            | 563 +++++++------------------------
 src/process.rs                           |  28 ++
 src/widget/container/container_layout.rs |  43 +++
 src/widget/container/hbox.rs             |  69 ++++
 src/widget/container/mod.rs              |   2 +-
 src/widget/container/parameters_bg.rs    |   2 +-
 src/widget/container/plate.rs            |  55 ++-
 src/widget/container/vbox.rs             |  66 ++++
 src/widget/core.rs                       |   6 +-
 src/widget/display/label.rs              |   5 +-
 src/widget/display/status_bar.rs         |   5 +-
 src/widget/input/button.rs               |  33 +-
 src/widget/input/button_strip.rs         |   9 +-
 src/widget/input/checkbox.rs             |  11 +-
 src/widget/input/dropdown.rs             |  65 +++-
 src/widget/input/ramp.rs                 |  27 +-
 src/widget/input/slider.rs               | 144 +++++---
 src/widget/input/spinbox.rs              |  76 +++--
 src/widget/input/text_box.rs             |  60 ++--
 src/widget/input/trackpad.rs             |  83 +++--
 src/widget/mod.rs                        |  81 +++--
 23 files changed, 1036 insertions(+), 663 deletions(-)

diff --git a/src/backend/window_runner.rs b/src/backend/window_runner.rs
index 6637a72..3237f83 100644
--- a/src/backend/window_runner.rs
+++ b/src/backend/window_runner.rs
@@ -1294,10 +1294,10 @@ pub trait Application: Sized + 'static {
         self.text_items().iter().map(|ti| {
             let mut item_bounds = if let Some([l, t, r, b]) = ti.bounds {
                 TextBounds {
-                    left: (l * scale_f32).round() as i32,
-                    top: (t * scale_f32).round() as i32,
-                    right: (r * scale_f32).round() as i32,
-                    bottom: (b * scale_f32).round() as i32,
+                    left: ((l * scale_f32).round() as i32).clamp(0, bounds.right),
+                    top: ((t * scale_f32).round() as i32).clamp(0, bounds.bottom),
+                    right: ((r * scale_f32).round() as i32).clamp(0, bounds.right),
+                    bottom: ((b * scale_f32).round() as i32).clamp(0, bounds.bottom),
                 }
             } else {
                 bounds
@@ -1641,7 +1641,16 @@ impl<A: Application> EngineState<A> {
         
         let bounds = TextBounds { left: 0, top: 0, right: pw as i32, bottom: ph as i32 };
         let areas = self.inner.as_ref().unwrap().text_areas(scale_f32, bounds);
-        eprintln!("DEBUG RENDER AREAS: len = {}", areas.len());
+        eprintln!("AREAS_LEN: {}", areas.len());
+        for (idx, area) in areas.iter().enumerate() {
+            let mut text_snippet = String::new();
+            for run in area.buffer.layout_runs() {
+                text_snippet.push_str(run.text);
+            }
+            eprintln!("TEXT_AREA idx={}: text='{}', left={}, top={}, bounds=[{}, {}, {}, {}]",
+                idx, text_snippet, area.left, area.top,
+                area.bounds.left, area.bounds.top, area.bounds.right, area.bounds.bottom);
+        }
         
         adapter.text_renderer.prepare(&adapter.device, &adapter.queue, &mut adapter.font_system, &mut adapter.text_atlas, &adapter.text_viewport, areas, &mut adapter.swash_cache).unwrap();
         
@@ -1973,6 +1982,7 @@ impl<A: Application> WindowHandler for EngineState<A> {
         crate::scale::set_maximized(is_max);
 
         let (w, h) = configure.new_size;
+        eprintln!("CONFIGURE_NEW_SIZE: w={:?}, h={:?}, scale={}", w, h, self.scale_factor);
         if let (Some(w), Some(h)) = (w, h) {
             let width = w.get();
             let height = h.get();
@@ -2929,4 +2939,5 @@ pub fn run<A: Application>() {
             }
         }
     }
+    crate::process::cleanup_spawned_processes();
 }
diff --git a/src/color.rs b/src/color.rs
index 5897384..708a8cb 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -34,6 +34,10 @@ static NODE_DRAG_COLOR: RwLock<[f32; 4]> = RwLock::new(NODE_DRAG);
 static SIDEBAR_BG_COLOR: RwLock<[f32; 4]> = RwLock::new(SIDEBAR_BG);
 static HIGHLIGHT_PRIMARY_COLOR: RwLock<[f32; 4]> = RwLock::new(HIGHLIGHT_PRIMARY);
 static MENUBAR_TAB_LABEL_COLOR: RwLock<[f32; 4]> = RwLock::new([0.90196, 0.90196, 0.94902, 1.0]); // sRGB [230, 230, 242] linear
+static CONTROL_LABEL_COLOR: RwLock<[f32; 4]> = RwLock::new([0.61206, 0.61206, 0.68666, 1.0]); // sRGB [204, 204, 212]
+static CONTROL_LABEL_COLOR_DETACHED: RwLock<[f32; 4]> = RwLock::new([0.22416, 0.22416, 0.2526, 1.0]); // sRGB [131, 131, 138]
+static CONTROL_LABEL_HOVER_COLOR: RwLock<Option<[f32; 4]>> = RwLock::new(None);
+static CONTROL_LABEL_FOCUS_COLOR: RwLock<Option<[f32; 4]>> = RwLock::new(None);
 static OPACITY: RwLock<Option<f32>> = RwLock::new(None);
 static BACKPLATE_OPACITY: RwLock<Option<f32>> = RwLock::new(None);
 static TOGGLE_ON_COLOR: RwLock<[f32; 4]> = RwLock::new(TOGGLE_ON);
@@ -79,6 +83,20 @@ static SPINBOX_TEXT_COLOR: RwLock<[f32; 4]> = RwLock::new([0.8, 0.8, 0.83, 1.0])
 static CHECKBOX_BG_COLOR: RwLock<[f32; 4]> = RwLock::new(CHECKBOX_BG);
 static CHECKBOX_CHECKED_COLOR: RwLock<[f32; 4]> = RwLock::new(CHECKBOX_CHECKED);
 static CHECKBOX_HOVER_COLOR: RwLock<[f32; 4]> = RwLock::new(CHECKBOX_HOVER);
+static CHECKBOX_BORDER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.25, 0.25, 0.30, 1.0]);
+
+static BUTTON_BORDER_COLOR: RwLock<Option<[f32; 4]>> = RwLock::new(None);
+static BUTTON_HOVER_COLOR: RwLock<Option<[f32; 4]>> = RwLock::new(None);
+
+static DROPDOWN_BORDER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.18, 0.18, 0.24, 1.0]);
+static DROPDOWN_TEXT_COLOR: RwLock<[f32; 4]> = RwLock::new([0.72305, 0.72305, 0.76008, 1.0]);
+
+static SLIDER_FILL_COLOR: RwLock<Option<[f32; 4]>> = RwLock::new(None);
+static SLIDER_THUMB_COLOR: RwLock<[f32; 4]> = RwLock::new(SLIDER_THUMB);
+static SLIDER_THUMB_DRAG_COLOR: RwLock<[f32; 4]> = RwLock::new(SLIDER_THUMB_DRAG);
+
+static RANGE_SLIDER_THUMB_COLOR: RwLock<[f32; 4]> = RwLock::new(SLIDER_THUMB);
+static RANGE_SLIDER_THUMB_DRAG_COLOR: RwLock<[f32; 4]> = RwLock::new(SLIDER_THUMB_DRAG);
 
 static TREE_BACKGROUND_COLOR: RwLock<[f32; 4]> = RwLock::new([0.08, 0.08, 0.12, 0.3]);
 static TREE_BORDER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.18, 0.18, 0.24, 1.0]);
@@ -327,6 +345,18 @@ fn parse_and_set_colors(content: &str) {
     if let Some(c) = get_color("/layout/menubar_tab_label_color").or_else(|| get_color("/layout/paginator_tab_label_color")) {
         if let Ok(mut lock) = MENUBAR_TAB_LABEL_COLOR.write() { *lock = c; }
     }
+    if let Some(c) = get_color("/style/control/label/color") {
+        if let Ok(mut lock) = CONTROL_LABEL_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/control/label/color_detached") {
+        if let Ok(mut lock) = CONTROL_LABEL_COLOR_DETACHED.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/control/label/hover_color") {
+        if let Ok(mut lock) = CONTROL_LABEL_HOVER_COLOR.write() { *lock = Some(c); }
+    }
+    if let Some(c) = get_color("/style/control/label/focus_color") {
+        if let Ok(mut lock) = CONTROL_LABEL_FOCUS_COLOR.write() { *lock = Some(c); }
+    }
     let toggle_border_color = get_color("/style/control/toggle/border_color")
         .or_else(|| get_color("/layout/toggle_border_color"));
 
@@ -385,6 +415,46 @@ fn parse_and_set_colors(content: &str) {
     if let Some(c) = get_color("/style/control/checkbox/hover_color").or_else(|| get_color("/style/checkbox/hover_color")) {
         if let Ok(mut lock) = CHECKBOX_HOVER_COLOR.write() { *lock = c; }
     }
+    if let Some(c) = get_color("/style/control/checkbox/border_color").or_else(|| get_color("/style/checkbox/border_color")) {
+        if let Ok(mut lock) = CHECKBOX_BORDER_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/control/button/border_color").or_else(|| get_color("/style/button/border_color")) {
+        if let Ok(mut lock) = BUTTON_BORDER_COLOR.write() { *lock = Some(c); }
+    }
+    if let Some(c) = get_color("/style/control/button/hover_color").or_else(|| get_color("/style/button/hover_color")) {
+        if let Ok(mut lock) = BUTTON_HOVER_COLOR.write() { *lock = Some(c); }
+    }
+    if let Some(c) = get_color("/style/control/dropdown/border_color").or_else(|| get_color("/style/dropdown/border_color")) {
+        if let Ok(mut lock) = DROPDOWN_BORDER_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/control/dropdown/text_color").or_else(|| get_color("/style/dropdown/text_color")) {
+        if let Ok(mut lock) = DROPDOWN_TEXT_COLOR.write() { *lock = c; }
+    }
+    if let Some(c) = get_color("/style/control/slider/fill_color").or_else(|| get_color("/style/slider/fill_color")) {
+        if let Ok(mut lock) = SLIDER_FILL_COLOR.write() { *lock = Some(c); }
+    }
+    if let Some(c) = get_color("/style/control/slider/thumb_color").or_else(|| get_color("/style/slider/thumb_color")) {
+        if let Ok(mut lock) = SLIDER_THUMB_COLOR.write() { *lock = c; }
+        if let Ok(mut lock_drag) = SLIDER_THUMB_DRAG_COLOR.write() {
+            *lock_drag = [
+                (c[0] + 0.15).min(1.0),
+                (c[1] + 0.15).min(1.0),
+                (c[2] + 0.15).min(1.0),
+                c[3]
+            ];
+        }
+    }
+    if let Some(c) = get_color("/style/control/rangeslider/thumb_color").or_else(|| get_color("/style/rangeslider/thumb_color")) {
+        if let Ok(mut lock) = RANGE_SLIDER_THUMB_COLOR.write() { *lock = c; }
+        if let Ok(mut lock_drag) = RANGE_SLIDER_THUMB_DRAG_COLOR.write() {
+            *lock_drag = [
+                (c[0] + 0.15).min(1.0),
+                (c[1] + 0.15).min(1.0),
+                (c[2] + 0.15).min(1.0),
+                c[3]
+            ];
+        }
+    }
     if let Some(c) = get_color("/style/control/progressbar/background") {
         if let Ok(mut lock) = PROGRESS_BG_COLOR.write() { *lock = c; }
     }
@@ -1121,6 +1191,105 @@ pub fn set_rangeslider_fill(color: [f32; 4]) {
     }
 }
 
+pub fn checkbox_border() -> [f32; 4] {
+    load_colors_once();
+    *CHECKBOX_BORDER_COLOR.read().unwrap()
+}
+
+pub fn set_checkbox_border(color: [f32; 4]) {
+    if let Ok(mut lock) = CHECKBOX_BORDER_COLOR.write() {
+        *lock = color;
+    }
+}
+
+pub fn button_border_color() -> Option<[f32; 4]> {
+    load_colors_once();
+    *BUTTON_BORDER_COLOR.read().unwrap()
+}
+
+pub fn set_button_border_color(color: [f32; 4]) {
+    if let Ok(mut lock) = BUTTON_BORDER_COLOR.write() {
+        *lock = Some(color);
+    }
+}
+
+pub fn dropdown_border_color() -> [f32; 4] {
+    load_colors_once();
+    *DROPDOWN_BORDER_COLOR.read().unwrap()
+}
+
+pub fn set_dropdown_border_color(color: [f32; 4]) {
+    if let Ok(mut lock) = DROPDOWN_BORDER_COLOR.write() {
+        *lock = color;
+    }
+}
+
+pub fn dropdown_text_color() -> [f32; 4] {
+    load_colors_once();
+    *DROPDOWN_TEXT_COLOR.read().unwrap()
+}
+
+pub fn set_dropdown_text_color(color: [f32; 4]) {
+    if let Ok(mut lock) = DROPDOWN_TEXT_COLOR.write() {
+        *lock = color;
+    }
+}
+
+pub fn slider_fill() -> Option<[f32; 4]> {
+    load_colors_once();
+    *SLIDER_FILL_COLOR.read().unwrap()
+}
+
+pub fn set_slider_fill(color: [f32; 4]) {
+    if let Ok(mut lock) = SLIDER_FILL_COLOR.write() {
+        *lock = Some(color);
+    }
+}
+
+pub fn slider_thumb() -> [f32; 4] {
+    load_colors_once();
+    *SLIDER_THUMB_COLOR.read().unwrap()
+}
+
+pub fn set_slider_thumb(color: [f32; 4]) {
+    if let Ok(mut lock) = SLIDER_THUMB_COLOR.write() {
+        *lock = color;
+    }
+}
+
+pub fn slider_thumb_drag() -> [f32; 4] {
+    load_colors_once();
+    *SLIDER_THUMB_DRAG_COLOR.read().unwrap()
+}
+
+pub fn set_slider_thumb_drag(color: [f32; 4]) {
+    if let Ok(mut lock) = SLIDER_THUMB_DRAG_COLOR.write() {
+        *lock = color;
+    }
+}
+
+pub fn rangeslider_thumb() -> [f32; 4] {
+    load_colors_once();
+    *RANGE_SLIDER_THUMB_COLOR.read().unwrap()
+}
+
+pub fn set_rangeslider_thumb(color: [f32; 4]) {
+    if let Ok(mut lock) = RANGE_SLIDER_THUMB_COLOR.write() {
+        *lock = color;
+    }
+}
+
+pub fn rangeslider_thumb_drag() -> [f32; 4] {
+    load_colors_once();
+    *RANGE_SLIDER_THUMB_DRAG_COLOR.read().unwrap()
+}
+
+pub fn set_rangeslider_thumb_drag(color: [f32; 4]) {
+    if let Ok(mut lock) = RANGE_SLIDER_THUMB_DRAG_COLOR.write() {
+        *lock = color;
+    }
+}
+
 pub fn spinbox_display() -> [f32; 4] {
     load_colors_once();
     *SPINBOX_DISPLAY_COLOR.read().unwrap()
@@ -1443,6 +1612,82 @@ pub fn set_plate_blur(b: bool) {
     }
 }
 
+pub fn control_label_color() -> [f32; 4] {
+    *CONTROL_LABEL_COLOR.read().unwrap()
+}
+
+pub fn control_label_color_u8() -> [u8; 3] {
+    let c = control_label_color();
+    [
+        (linear_to_srgb(c[0]) * 255.0).round() as u8,
+        (linear_to_srgb(c[1]) * 255.0).round() as u8,
+        (linear_to_srgb(c[2]) * 255.0).round() as u8,
+    ]
+}
+
+pub fn set_control_label_color(color: [f32; 4]) {
+    if let Ok(mut lock) = CONTROL_LABEL_COLOR.write() {
+        *lock = color;
+    }
+}
+
+pub fn control_label_hover_color() -> Option<[f32; 4]> {
+    *CONTROL_LABEL_HOVER_COLOR.read().unwrap()
+}
+
+pub fn control_label_focus_color() -> Option<[f32; 4]> {
+    *CONTROL_LABEL_FOCUS_COLOR.read().unwrap()
+}
+
+pub fn control_label_color_for_state(hovered: bool, focused: bool) -> [u8; 3] {
+    let c = if focused {
+        control_label_focus_color().unwrap_or_else(|| control_label_color())
+    } else if hovered {
+        control_label_hover_color().unwrap_or_else(|| control_label_color())
+    } else {
+        control_label_color()
+    };
+    [
+        (linear_to_srgb(c[0]) * 255.0).round() as u8,
+        (linear_to_srgb(c[1]) * 255.0).round() as u8,
+        (linear_to_srgb(c[2]) * 255.0).round() as u8,
+    ]
+}
+
+pub fn control_label_color_detached() -> [f32; 4] {
+    *CONTROL_LABEL_COLOR_DETACHED.read().unwrap()
+}
+
+pub fn control_label_color_detached_u8() -> [u8; 3] {
+    let c = control_label_color_detached();
+    [
+        (linear_to_srgb(c[0]) * 255.0).round() as u8,
+        (linear_to_srgb(c[1]) * 255.0).round() as u8,
+        (linear_to_srgb(c[2]) * 255.0).round() as u8,
+    ]
+}
+
+pub fn set_control_label_color_detached(color: [f32; 4]) {
+    if let Ok(mut lock) = CONTROL_LABEL_COLOR_DETACHED.write() {
+        *lock = color;
+    }
+}
+
+pub fn control_label_color_detached_for_state(hovered: bool, focused: bool) -> [u8; 3] {
+    let c = if focused {
+        control_label_focus_color().unwrap_or_else(|| control_label_color_detached())
+    } else if hovered {
+        control_label_hover_color().unwrap_or_else(|| control_label_color_detached())
+    } else {
+        control_label_color_detached()
+    };
+    [
+        (linear_to_srgb(c[0]) * 255.0).round() as u8,
+        (linear_to_srgb(c[1]) * 255.0).round() as u8,
+        (linear_to_srgb(c[2]) * 255.0).round() as u8,
+    ]
+}
+
 #[cfg(test)]
 mod color_tests {
     use super::*;
diff --git a/src/layout.rs b/src/layout.rs
index 188a8fe..dd1b715 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -67,30 +67,29 @@ fn flatten_json_to_flat_props(val: &serde_json::Value, prefix: &str, flat_props:
                 "style.list.font_color" | "style.data.list.font_color" => "list_font_color",
                 "style.control.breadcrumb.font" => "breadcrumb_font",
                 "style.control.breadcrumb.corner_radius" => "breadcrumb_corner_radius",
-                "style.control.button.font" => "button_font",
                 "style.control.button.padding" => "button_padding",
                 "style.control.button.height" => "button_height",
                 "style.control.button.corner_radius" => "button_corner_radius",
                 "style.list.corner_radius" | "style.data.list.corner_radius" => "list_corner_radius",
                 "style.control.textbox.corner_radius" | "style.textbox.corner_radius" | "style.data.textbox.corner_radius" => "textbox_corner_radius",
-                "style.control.dropdown.font" => "dropdown_font",
                 "style.control.dropdown.color" => "dropdown_color",
                 "style.control.font_selector.font" => "font_selector_font",
-                "style.control.slider.font" => "slider_font",
-                "style.control.spinbox.font" => "spinbox_font",
                 "style.section.font" => "section_label_font",
-                "style.control.textbox.font" | "style.textbox.font" | "style.data.textbox.font" => "textbox_font",
                 "style.control.button_strip.font" => "button_strip_font",
                 "style.control.button_strip.spacing" => "button_strip_spacing",
                 "style.control.dropdown.height" => "dropdown_height",
                 "style.control.dropdown.corner_radius" => "dropdown_corner_radius",
                 "style.control.font_selector.height" => "font_selector_height",
                 "style.control.font_selector.corner_radius" => "font_selector_corner_radius",
-                "style.label.font" => "label_font",
+                "style.control.label.font" => "control_label_font",
+                "style.control.label.font_detached" => "control_label_font_detached",
+                "style.control.label.margin" => "control_label_margin",
+                "style.control.label.layout" => "control_label_layout",
                 "style.control.slider.height" => "slider_height",
                 "style.control.slider.corner_radius" => "slider_corner_radius",
                 "style.control.progressbar.height" => "progressbar_height",
                 "style.control.rangeslider.height" => "rangeslider_height",
+                "style.control.rangeslider.corner_radius" | "style.rangeslider.corner_radius" => "rangeslider_corner_radius",
                 "style.control.scrollbar.width" => "scrollbar_width",
                 "style.control.spinbox.height" => "spinbox_height",
                 "style.control.spinbox.button_padding" => "spinbox_button_padding",
@@ -101,7 +100,6 @@ fn flatten_json_to_flat_props(val: &serde_json::Value, prefix: &str, flat_props:
                 "style.control.textbox.background_edit_color" | "style.textbox.background_edit_color" | "style.data.textbox.background_edit_color" => "textbox_background_edit_color",
                 "style.control.textbox.multiline.line_wrap" | "style.textbox.multiline.line_wrap" | "style.data.textbox.multiline.line_wrap" => "textbox_line_wrap",
                 "style.control.textbox.multiline.border_width" | "style.textbox.multiline.border_width" | "style.data.textbox.multiline.border_width" => "textbox_multiline_border_width",
-                "style.control.toggle.font" => "toggle_font",
                 "style.control.toggle.height" => "toggle_height",
                 "style.control.toggle.border_width" => "toggle_border_width",
                 "style.control.toggle.disabled_color" => "toggle_disabled_color",
@@ -268,7 +266,7 @@ static PLATE_PADDING: RwLock<f32> = RwLock::new(20.0);
 static DROPDOWN_HEIGHT: RwLock<f32> = RwLock::new(44.0);
 static NESTED_SECTION_LABEL_ALIGNMENT: RwLock<u8> = RwLock::new(0);
 
-static LABEL_MARGIN: RwLock<f32> = RwLock::new(6.0);
+
 static BUTTON_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
 static SPINBOX_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
 static TEXTBOX_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
@@ -276,28 +274,21 @@ static FONT_SELECTOR_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
 static DROPDOWN_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
 static TOGGLE_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
 static SLIDER_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
+static RANGESLIDER_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
 static BREADCRUMB_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
 static LIST_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
 static TREE_CORNER_RADIUS: RwLock<f32> = RwLock::new(4.0);
 static TOGGLE_BORDER_WIDTH: RwLock<f32> = RwLock::new(1.0);
-static TOGGLE_FONT: RwLock<String> = RwLock::new(String::new());
-static TOGGLE_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
 static FONT_SELECTOR_FONT: RwLock<String> = RwLock::new(String::new());
 static FONT_SELECTOR_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
 static BUTTON_STRIP_FONT: RwLock<String> = RwLock::new(String::new());
 static BUTTON_STRIP_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
-static BUTTON_FONT: RwLock<String> = RwLock::new(String::new());
-static BUTTON_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
-static LABEL_FONT: RwLock<String> = RwLock::new(String::new());
-static LABEL_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
-static DROPDOWN_FONT: RwLock<String> = RwLock::new(String::new());
-static DROPDOWN_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
-static TEXTBOX_FONT: RwLock<String> = RwLock::new(String::new());
-static TEXTBOX_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
-static SPINBOX_FONT: RwLock<String> = RwLock::new(String::new());
-static SPINBOX_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
-static SLIDER_FONT: RwLock<String> = RwLock::new(String::new());
-static SLIDER_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
+static CONTROL_LABEL_FONT: RwLock<String> = RwLock::new(String::new());
+static CONTROL_LABEL_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
+static CONTROL_LABEL_FONT_DETACHED: RwLock<String> = RwLock::new(String::new());
+static CONTROL_LABEL_FONT_DETACHED_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
+static CONTROL_LABEL_MARGIN: RwLock<f32> = RwLock::new(6.0);
+static CONTROL_LABEL_LAYOUT: RwLock<String> = RwLock::new(String::new());
 static PLATE_CORNER_RADIUS: RwLock<f32> = RwLock::new(12.0);
 static LIST_FONT: RwLock<String> = RwLock::new(String::new());
 static LIST_FONT_CACHED: RwLock<Option<(String, f32)>> = RwLock::new(None);
@@ -340,15 +331,10 @@ pub fn reload_config() {
     if let Some(content) = read_config() {
         let mut menubar_font_changed = false;
         let mut statusbar_font_changed = false;
-        let mut toggle_font_changed = false;
         let mut font_selector_font_changed = false;
         let mut button_strip_font_changed = false;
-        let mut button_font_changed = false;
         let mut label_font_changed = false;
-        let mut dropdown_font_changed = false;
-        let mut textbox_font_changed = false;
-        let mut spinbox_font_changed = false;
-        let mut slider_font_changed = false;
+        let mut label_font_detached_changed = false;
         let mut list_font_changed = false;
         let mut tree_font_changed = false;
         let mut graph_font_changed = false;
@@ -366,15 +352,22 @@ pub fn reload_config() {
                     }
                 }
             }
-            if let Some(rest) = trimmed.strip_prefix("label_margin") {
+            if let Some(rest) = trimmed.strip_prefix("control_label_margin") {
                 let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
                 let val_str = rest.trim_end_matches('"').trim();
                 if let Ok(val) = val_str.parse::<f32>() {
-                    if let Ok(mut lock) = LABEL_MARGIN.write() {
+                    if let Ok(mut lock) = CONTROL_LABEL_MARGIN.write() {
                         *lock = val;
                     }
                 }
             }
+            if let Some(rest) = trimmed.strip_prefix("control_label_layout") {
+                let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
+                let val_str = rest.trim_end_matches('"').trim().to_string();
+                if let Ok(mut lock) = CONTROL_LABEL_LAYOUT.write() {
+                    *lock = val_str;
+                }
+            }
             if let Some(rest) = trimmed.strip_prefix("nested_section_label_alignment") {
                 let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
                 let val_str = rest.trim_end_matches('"').trim();
@@ -867,81 +860,44 @@ pub fn reload_config() {
                     }
                 }
             }
-            if let Some(rest) = trimmed.strip_prefix("toggle_border_width") {
+            if let Some(rest) = trimmed.strip_prefix("rangeslider_corner_radius") {
                 let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
                 let val_str = rest.trim_end_matches('"').trim();
                 if let Ok(val) = val_str.parse::<f32>() {
-                    if let Ok(mut lock) = TOGGLE_BORDER_WIDTH.write() {
+                    if let Ok(mut lock) = RANGESLIDER_CORNER_RADIUS.write() {
                         *lock = val;
                     }
                 }
             }
-            if let Some(rest) = trimmed.strip_prefix("toggle_font") {
-                let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                let rest = mod_rest(rest);
-                let font = rest.trim().to_string();
-                let mut changed = false;
-                if let Ok(mut lock) = TOGGLE_FONT.write() {
-                    if *lock != font {
-                        *lock = font;
-                        changed = true;
-                    }
-                }
-                if changed {
-                    toggle_font_changed = true;
-                }
-            }
-            if let Some(rest) = trimmed.strip_prefix("font_selector_font") {
-                let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                let rest = mod_rest(rest);
-                let font = rest.trim().to_string();
-                let mut changed = false;
-                if let Ok(mut lock) = FONT_SELECTOR_FONT.write() {
-                    if *lock != font {
-                        *lock = font;
-                        changed = true;
-                    }
-                }
-                if changed {
-                    font_selector_font_changed = true;
-                }
-            }
-            if let Some(rest) = trimmed.strip_prefix("button_strip_font") {
-                let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                let rest = mod_rest(rest);
-                let font = rest.trim().to_string();
-                let mut changed = false;
-                if let Ok(mut lock) = BUTTON_STRIP_FONT.write() {
-                    if *lock != font {
-                        *lock = font;
-                        changed = true;
+            if let Some(rest) = trimmed.strip_prefix("toggle_border_width") {
+                let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
+                let val_str = rest.trim_end_matches('"').trim();
+                if let Ok(val) = val_str.parse::<f32>() {
+                    if let Ok(mut lock) = TOGGLE_BORDER_WIDTH.write() {
+                        *lock = val;
                     }
                 }
-                if changed {
-                    button_strip_font_changed = true;
-                }
             }
-            if let Some(rest) = trimmed.strip_prefix("button_font") {
+            if let Some(rest) = trimmed.strip_prefix("control_label_font_detached") {
                 let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
                 let rest = mod_rest(rest);
                 let font = rest.trim().to_string();
                 let mut changed = false;
-                if let Ok(mut lock) = BUTTON_FONT.write() {
+                if let Ok(mut lock) = CONTROL_LABEL_FONT_DETACHED.write() {
                     if *lock != font {
                         *lock = font;
                         changed = true;
                     }
                 }
                 if changed {
-                    button_font_changed = true;
+                    label_font_detached_changed = true;
                 }
-            }
-            if let Some(rest) = trimmed.strip_prefix("label_font") {
+            } else if let Some(rest) = trimmed.strip_prefix("control_label_font") {
                 let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
                 let rest = mod_rest(rest);
                 let font = rest.trim().to_string();
                 let mut changed = false;
-                if let Ok(mut lock) = LABEL_FONT.write() {
+                if let Ok(mut lock) = CONTROL_LABEL_FONT.write() {
                     if *lock != font {
                         *lock = font;
                         changed = true;
@@ -951,64 +907,34 @@ pub fn reload_config() {
                     label_font_changed = true;
                 }
             }
-            if let Some(rest) = trimmed.strip_prefix("dropdown_font") {
-                let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                let rest = mod_rest(rest);
-                let font = rest.trim().to_string();
-                let mut changed = false;
-                if let Ok(mut lock) = DROPDOWN_FONT.write() {
-                    if *lock != font {
-                        *lock = font;
-                        changed = true;
-                    }
-                }
-                if changed {
-                    dropdown_font_changed = true;
-                }
-            }
-            if let Some(rest) = trimmed.strip_prefix("textbox_font") {
-                let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                let rest = mod_rest(rest);
-                let font = rest.trim().to_string();
-                let mut changed = false;
-                if let Ok(mut lock) = TEXTBOX_FONT.write() {
-                    if *lock != font {
-                        *lock = font;
-                        changed = true;
-                    }
-                }
-                if changed {
-                    textbox_font_changed = true;
-                }
-            }
-            if let Some(rest) = trimmed.strip_prefix("spinbox_font") {
+            if let Some(rest) = trimmed.strip_prefix("font_selector_font") {
                 let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
                 let rest = mod_rest(rest);
                 let font = rest.trim().to_string();
                 let mut changed = false;
-                if let Ok(mut lock) = SPINBOX_FONT.write() {
+                if let Ok(mut lock) = FONT_SELECTOR_FONT.write() {
                     if *lock != font {
                         *lock = font;
                         changed = true;
                     }
                 }
                 if changed {
-                    spinbox_font_changed = true;
+                    font_selector_font_changed = true;
                 }
             }
-            if let Some(rest) = trimmed.strip_prefix("slider_font") {
+            if let Some(rest) = trimmed.strip_prefix("button_strip_font") {
                 let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
                 let rest = mod_rest(rest);
                 let font = rest.trim().to_string();
                 let mut changed = false;
-                if let Ok(mut lock) = SLIDER_FONT.write() {
+                if let Ok(mut lock) = BUTTON_STRIP_FONT.write() {
                     if *lock != font {
                         *lock = font;
                         changed = true;
                     }
                 }
                 if changed {
-                    slider_font_changed = true;
+                    button_strip_font_changed = true;
                 }
             }
             if let Some(rest) = trimmed.strip_prefix("list_font") {
@@ -1091,8 +1017,8 @@ pub fn reload_config() {
                 *lock = None;
             }
         }
-        if toggle_font_changed {
-            if let Ok(mut lock) = TOGGLE_FONT_CACHED.write() {
+        if label_font_detached_changed {
+            if let Ok(mut lock) = CONTROL_LABEL_FONT_DETACHED_CACHED.write() {
                 *lock = None;
             }
         }
@@ -1106,36 +1032,12 @@ pub fn reload_config() {
                 *lock = None;
             }
         }
-        if button_font_changed {
-            if let Ok(mut lock) = BUTTON_FONT_CACHED.write() {
-                *lock = None;
-            }
-        }
         if label_font_changed {
-            if let Ok(mut lock) = LABEL_FONT_CACHED.write() {
-                *lock = None;
-            }
-        }
-        if dropdown_font_changed {
-            if let Ok(mut lock) = DROPDOWN_FONT_CACHED.write() {
-                *lock = None;
-            }
-        }
-        if textbox_font_changed {
-            if let Ok(mut lock) = TEXTBOX_FONT_CACHED.write() {
-                *lock = None;
-            }
-        }
-        if spinbox_font_changed {
-            if let Ok(mut lock) = SPINBOX_FONT_CACHED.write() {
-                *lock = None;
-            }
-        }
-        if slider_font_changed {
-            if let Ok(mut lock) = SLIDER_FONT_CACHED.write() {
+            if let Ok(mut lock) = CONTROL_LABEL_FONT_CACHED.write() {
                 *lock = None;
             }
         }
+
         if list_font_changed {
             if let Ok(mut lock) = LIST_FONT_CACHED.write() {
                 *lock = None;
@@ -1171,34 +1073,33 @@ fn mod_rest(rest: &str) -> &str {
     }
 }
 
+pub fn control_label_margin() -> f32 {
+    *CONTROL_LABEL_MARGIN.read().unwrap()
+}
+
+pub fn control_label_layout() -> String {
+    let lock = CONTROL_LABEL_LAYOUT.read().unwrap();
+    if lock.is_empty() {
+        "top".to_string()
+    } else {
+        lock.clone()
+    }
+}
+
 pub fn label_margin() -> f32 {
-    use std::sync::Once;
-    static INIT: Once = Once::new();
-    INIT.call_once(|| {
-        if let Some(content) = read_config() {
-            for line in content.lines() {
-                let trimmed = line.trim();
-                if let Some(rest) = trimmed.strip_prefix("label_margin") {
-                    let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=' || c == '"');
-                    let val_str = rest.trim_end_matches('"').trim();
-                    if let Ok(val) = val_str.parse::<f32>() {
-                        if let Ok(mut lock) = LABEL_MARGIN.write() {
-                            *lock = val;
-                        }
-                    }
-                }
-            }
-        }
-    });
-    *LABEL_MARGIN.read().unwrap()
+    control_label_margin()
 }
 
-pub fn set_label_margin(margin: f32) {
-    if let Ok(mut lock) = LABEL_MARGIN.write() {
+pub fn set_control_label_margin(margin: f32) {
+    if let Ok(mut lock) = CONTROL_LABEL_MARGIN.write() {
         *lock = margin;
     }
 }
 
+pub fn set_label_margin(margin: f32) {
+    set_control_label_margin(margin);
+}
+
 pub fn nested_section_label_alignment() -> u8 {
     use std::sync::Once;
     static INIT: Once = Once::new();
@@ -1604,6 +1505,18 @@ pub fn set_slider_corner_radius(radius: f32) {
     }
 }
 
+pub fn rangeslider_corner_radius() -> f32 {
+    lazy_init_style_registry();
+    get_style_registry().read().unwrap().get_float("rangeslider_corner_radius").unwrap_or(4.0)
+}
+
+pub fn set_rangeslider_corner_radius(radius: f32) {
+    lazy_init_style_registry();
+    if let Ok(mut registry) = get_style_registry().write() {
+        registry.set_float("rangeslider_corner_radius", radius);
+    }
+}
+
 pub fn plate_corner_radius() -> f32 {
     lazy_init_style_registry();
     let r = get_style_registry().read().unwrap();
@@ -1914,57 +1827,7 @@ pub fn set_statusbar_font(font: &str) {
     }
 }
 
-pub fn toggle_font() -> String {
-    use std::sync::Once;
-    static INIT: Once = Once::new();
-    INIT.call_once(|| {
-        let mut font = "Outfit".to_string();
-        if let Some(content) = read_config() {
-            for line in content.lines() {
-                let trimmed = line.trim();
-                if let Some(rest) = trimmed.strip_prefix("toggle_font") {
-                    let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                    let rest = mod_rest(rest);
-                    font = rest.trim().to_string();
-                }
-            }
-        }
-        if let Ok(mut lock) = TOGGLE_FONT.write() {
-            *lock = font;
-        }
-    });
-    let lock = TOGGLE_FONT.read().unwrap();
-    if lock.is_empty() {
-        "Outfit".to_string()
-    } else {
-        lock.clone()
-    }
-}
-
-pub fn toggle_font_parsed() -> (String, f32) {
-    if let Ok(lock) = TOGGLE_FONT_CACHED.read() {
-        if let Some(ref val) = *lock {
-            return val.clone();
-        }
-    }
-    let font_str = toggle_font();
-    let parsed = parse_font_string(&font_str);
-    let size = parsed.1.unwrap_or(12.0);
-    let val = (parsed.0, size);
-    if let Ok(mut lock) = TOGGLE_FONT_CACHED.write() {
-        *lock = Some(val.clone());
-    }
-    val
-}
 
-pub fn set_toggle_font(font: &str) {
-    if let Ok(mut lock) = TOGGLE_FONT.write() {
-        *lock = font.to_string();
-    }
-    if let Ok(mut lock) = TOGGLE_FONT_CACHED.write() {
-        *lock = None;
-    }
-}
 
 pub fn font_selector_font() -> String {
     use std::sync::Once;
@@ -2071,61 +1934,10 @@ pub fn set_button_strip_font(font: &str) {
     }
 }
 
-// Button Font
-pub fn button_font() -> String {
-    use std::sync::Once;
-    static INIT: Once = Once::new();
-    INIT.call_once(|| {
-        let mut font = "Outfit".to_string();
-        if let Some(content) = read_config() {
-            for line in content.lines() {
-                let trimmed = line.trim();
-                if let Some(rest) = trimmed.strip_prefix("button_font") {
-                    let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                    let rest = mod_rest(rest);
-                    font = rest.trim().to_string();
-                }
-            }
-        }
-        if let Ok(mut lock) = BUTTON_FONT.write() {
-            *lock = font;
-        }
-    });
-    let lock = BUTTON_FONT.read().unwrap();
-    if lock.is_empty() {
-        "Outfit".to_string()
-    } else {
-        lock.clone()
-    }
-}
-
-pub fn button_font_parsed() -> (String, f32) {
-    if let Ok(lock) = BUTTON_FONT_CACHED.read() {
-        if let Some(ref val) = *lock {
-            return val.clone();
-        }
-    }
-    let font_str = button_font();
-    let parsed = parse_font_string(&font_str);
-    let size = parsed.1.unwrap_or(12.0);
-    let val = (parsed.0, size);
-    if let Ok(mut lock) = BUTTON_FONT_CACHED.write() {
-        *lock = Some(val.clone());
-    }
-    val
-}
 
-pub fn set_button_font(font: &str) {
-    if let Ok(mut lock) = BUTTON_FONT.write() {
-        *lock = font.to_string();
-    }
-    if let Ok(mut lock) = BUTTON_FONT_CACHED.write() {
-        *lock = None;
-    }
-}
 
-// Label Font
-pub fn label_font() -> String {
+// Control Label Font
+pub fn control_label_font() -> String {
     use std::sync::Once;
     static INIT: Once = Once::new();
     INIT.call_once(|| {
@@ -2133,18 +1945,18 @@ pub fn label_font() -> String {
         if let Some(content) = read_config() {
             for line in content.lines() {
                 let trimmed = line.trim();
-                if let Some(rest) = trimmed.strip_prefix("label_font") {
+                if let Some(rest) = trimmed.strip_prefix("control_label_font") {
                     let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
                     let rest = mod_rest(rest);
                     font = rest.trim().to_string();
                 }
             }
         }
-        if let Ok(mut lock) = LABEL_FONT.write() {
+        if let Ok(mut lock) = CONTROL_LABEL_FONT.write() {
             *lock = font;
         }
     });
-    let lock = LABEL_FONT.read().unwrap();
+    let lock = CONTROL_LABEL_FONT.read().unwrap();
     if lock.is_empty() {
         "Outfit".to_string()
     } else {
@@ -2152,33 +1964,33 @@ pub fn label_font() -> String {
     }
 }
 
-pub fn label_font_parsed() -> (String, f32) {
-    if let Ok(lock) = LABEL_FONT_CACHED.read() {
+pub fn control_label_font_parsed() -> (String, f32) {
+    if let Ok(lock) = CONTROL_LABEL_FONT_CACHED.read() {
         if let Some(ref val) = *lock {
             return val.clone();
         }
     }
-    let font_str = label_font();
+    let font_str = control_label_font();
     let parsed = parse_font_string(&font_str);
     let size = parsed.1.unwrap_or(12.0);
     let val = (parsed.0, size);
-    if let Ok(mut lock) = LABEL_FONT_CACHED.write() {
+    if let Ok(mut lock) = CONTROL_LABEL_FONT_CACHED.write() {
         *lock = Some(val.clone());
     }
     val
 }
 
-pub fn set_label_font(font: &str) {
-    if let Ok(mut lock) = LABEL_FONT.write() {
+pub fn set_control_label_font(font: &str) {
+    if let Ok(mut lock) = CONTROL_LABEL_FONT.write() {
         *lock = font.to_string();
     }
-    if let Ok(mut lock) = LABEL_FONT_CACHED.write() {
+    if let Ok(mut lock) = CONTROL_LABEL_FONT_CACHED.write() {
         *lock = None;
     }
 }
 
-// Dropdown Font
-pub fn dropdown_font() -> String {
+// Control Label Font Detached
+pub fn control_label_font_detached() -> String {
     use std::sync::Once;
     static INIT: Once = Once::new();
     INIT.call_once(|| {
@@ -2186,18 +1998,18 @@ pub fn dropdown_font() -> String {
         if let Some(content) = read_config() {
             for line in content.lines() {
                 let trimmed = line.trim();
-                if let Some(rest) = trimmed.strip_prefix("dropdown_font") {
+                if let Some(rest) = trimmed.strip_prefix("control_label_font_detached") {
                     let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
                     let rest = mod_rest(rest);
                     font = rest.trim().to_string();
                 }
             }
         }
-        if let Ok(mut lock) = DROPDOWN_FONT.write() {
+        if let Ok(mut lock) = CONTROL_LABEL_FONT_DETACHED.write() {
             *lock = font;
         }
     });
-    let lock = DROPDOWN_FONT.read().unwrap();
+    let lock = CONTROL_LABEL_FONT_DETACHED.read().unwrap();
     if lock.is_empty() {
         "Outfit".to_string()
     } else {
@@ -2205,31 +2017,33 @@ pub fn dropdown_font() -> String {
     }
 }
 
-pub fn dropdown_font_parsed() -> (String, f32) {
-    if let Ok(lock) = DROPDOWN_FONT_CACHED.read() {
+pub fn control_label_font_detached_parsed() -> (String, f32) {
+    if let Ok(lock) = CONTROL_LABEL_FONT_DETACHED_CACHED.read() {
         if let Some(ref val) = *lock {
             return val.clone();
         }
     }
-    let font_str = dropdown_font();
+    let font_str = control_label_font_detached();
     let parsed = parse_font_string(&font_str);
     let size = parsed.1.unwrap_or(12.0);
     let val = (parsed.0, size);
-    if let Ok(mut lock) = DROPDOWN_FONT_CACHED.write() {
+    if let Ok(mut lock) = CONTROL_LABEL_FONT_DETACHED_CACHED.write() {
         *lock = Some(val.clone());
     }
     val
 }
 
-pub fn set_dropdown_font(font: &str) {
-    if let Ok(mut lock) = DROPDOWN_FONT.write() {
+pub fn set_control_label_font_detached(font: &str) {
+    if let Ok(mut lock) = CONTROL_LABEL_FONT_DETACHED.write() {
         *lock = font.to_string();
     }
-    if let Ok(mut lock) = DROPDOWN_FONT_CACHED.write() {
+    if let Ok(mut lock) = CONTROL_LABEL_FONT_DETACHED_CACHED.write() {
         *lock = None;
     }
 }
 
+
+
 // List Font
 pub fn list_font() -> String {
     use std::sync::Once;
@@ -2471,164 +2285,7 @@ pub fn set_list_justification(just: u8) {
     }
 }
 
-// Textbox Font
-pub fn textbox_font() -> String {
-    use std::sync::Once;
-    static INIT: Once = Once::new();
-    INIT.call_once(|| {
-        let mut font = "Outfit".to_string();
-        if let Some(content) = read_config() {
-            for line in content.lines() {
-                let trimmed = line.trim();
-                if let Some(rest) = trimmed.strip_prefix("textbox_font") {
-                    let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                    let rest = mod_rest(rest);
-                    font = rest.trim().to_string();
-                }
-            }
-        }
-        if let Ok(mut lock) = TEXTBOX_FONT.write() {
-            *lock = font;
-        }
-    });
-    let lock = TEXTBOX_FONT.read().unwrap();
-    if lock.is_empty() {
-        "Outfit".to_string()
-    } else {
-        lock.clone()
-    }
-}
-
-pub fn textbox_font_parsed() -> (String, f32) {
-    if let Ok(lock) = TEXTBOX_FONT_CACHED.read() {
-        if let Some(ref val) = *lock {
-            return val.clone();
-        }
-    }
-    let font_str = textbox_font();
-    let parsed = parse_font_string(&font_str);
-    let size = parsed.1.unwrap_or(12.0);
-    let val = (parsed.0, size);
-    if let Ok(mut lock) = TEXTBOX_FONT_CACHED.write() {
-        *lock = Some(val.clone());
-    }
-    val
-}
-
-pub fn set_textbox_font(font: &str) {
-    if let Ok(mut lock) = TEXTBOX_FONT.write() {
-        *lock = font.to_string();
-    }
-    if let Ok(mut lock) = TEXTBOX_FONT_CACHED.write() {
-        *lock = None;
-    }
-}
-
-// Spinbox Font
-pub fn spinbox_font() -> String {
-    use std::sync::Once;
-    static INIT: Once = Once::new();
-    INIT.call_once(|| {
-        let mut font = "monospace".to_string();
-        if let Some(content) = read_config() {
-            for line in content.lines() {
-                let trimmed = line.trim();
-                if let Some(rest) = trimmed.strip_prefix("spinbox_font") {
-                    let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                    let rest = mod_rest(rest);
-                    font = rest.trim().to_string();
-                }
-            }
-        }
-        if let Ok(mut lock) = SPINBOX_FONT.write() {
-            *lock = font;
-        }
-    });
-    let lock = SPINBOX_FONT.read().unwrap();
-    if lock.is_empty() {
-        "monospace".to_string()
-    } else {
-        lock.clone()
-    }
-}
-
-pub fn spinbox_font_parsed() -> (String, f32) {
-    if let Ok(lock) = SPINBOX_FONT_CACHED.read() {
-        if let Some(ref val) = *lock {
-            return val.clone();
-        }
-    }
-    let font_str = spinbox_font();
-    let parsed = parse_font_string(&font_str);
-    let size = parsed.1.unwrap_or(12.0);
-    let val = (parsed.0, size);
-    if let Ok(mut lock) = SPINBOX_FONT_CACHED.write() {
-        *lock = Some(val.clone());
-    }
-    val
-}
-
-pub fn set_spinbox_font(font: &str) {
-    if let Ok(mut lock) = SPINBOX_FONT.write() {
-        *lock = font.to_string();
-    }
-    if let Ok(mut lock) = SPINBOX_FONT_CACHED.write() {
-        *lock = None;
-    }
-}
-
-// Slider Font
-pub fn slider_font() -> String {
-    use std::sync::Once;
-    static INIT: Once = Once::new();
-    INIT.call_once(|| {
-        let mut font = "Outfit".to_string();
-        if let Some(content) = read_config() {
-            for line in content.lines() {
-                let trimmed = line.trim();
-                if let Some(rest) = trimmed.strip_prefix("slider_font") {
-                    let rest = rest.trim_start_matches(|c: char| c == ' ' || c == '=');
-                    let rest = mod_rest(rest);
-                    font = rest.trim().to_string();
-                }
-            }
-        }
-        if let Ok(mut lock) = SLIDER_FONT.write() {
-            *lock = font;
-        }
-    });
-    let lock = SLIDER_FONT.read().unwrap();
-    if lock.is_empty() {
-        "Outfit".to_string()
-    } else {
-        lock.clone()
-    }
-}
-
-pub fn slider_font_parsed() -> (String, f32) {
-    if let Ok(lock) = SLIDER_FONT_CACHED.read() {
-        if let Some(ref val) = *lock {
-            return val.clone();
-        }
-    }
-    let font_str = slider_font();
-    let parsed = parse_font_string(&font_str);
-    let size = parsed.1.unwrap_or(12.0);
-    let val = (parsed.0, size);
-    if let Ok(mut lock) = SLIDER_FONT_CACHED.write() {
-        *lock = Some(val.clone());
-    }
-    val
-}
 
-pub fn set_slider_font(font: &str) {
-    if let Ok(mut lock) = SLIDER_FONT.write() {
-        *lock = font.to_string();
-    }
-    if let Ok(mut lock) = SLIDER_FONT_CACHED.write() {
-        *lock = None;
-    }
-}
 
 
 pub fn section_label_font() -> String {
@@ -5541,6 +5198,10 @@ mod tests {
     fn test_vstack_flow() {
         let orig_margin = label_margin();
         set_label_margin(6.0);
+        let orig_font = control_label_font();
+        set_control_label_font("Outfit 12");
+        let orig_font_detached = control_label_font_detached();
+        set_control_label_font_detached("Outfit 12");
         let _ = section_padding();
         set_section_padding(8.0);
         let mut mock_pc = MockRenderTarget { rects: Vec::new() };
@@ -5568,9 +5229,13 @@ mod tests {
         let mut w3 = MockWidgetWithLabel { base };
         stack.add_widget(&mut w3, 70.0, 50.0, &mut dummy);
 
-        // Third widget has label, so its y should be shifted by 18.0
-        assert_eq!(w3.base.y, start_y + 30.0 + 10.0 + 40.0 + 10.0 + 18.0);
+        let offset = w3.base.label_offset();
+        
+        // Third widget has label, so its y should be shifted by offset
+        assert_eq!(w3.base.y, start_y + 30.0 + 10.0 + 40.0 + 10.0 + offset);
         set_label_margin(orig_margin);
+        set_control_label_font(&orig_font);
+        set_control_label_font_detached(&orig_font_detached);
     }
 
     #[test]
diff --git a/src/process.rs b/src/process.rs
index f942c17..9851e38 100644
--- a/src/process.rs
+++ b/src/process.rs
@@ -1,4 +1,7 @@
 use std::process::Command;
+use std::sync::Mutex;
+
+static TRACKED_PROCESSES: Mutex<Vec<std::process::Child>> = Mutex::new(Vec::new());
 
 /// Spawns a process detached and automatically reaps it when it exits.
 ///
@@ -20,6 +23,24 @@ pub fn spawn_detached(mut cmd: Command) -> std::io::Result<()> {
     Ok(())
 }
 
+/// Spawns a process and registers it to be automatically killed when the application exits.
+pub fn spawn_tracked(mut cmd: Command) -> std::io::Result<()> {
+    let child = cmd.spawn()?;
+    if let Ok(mut lock) = TRACKED_PROCESSES.lock() {
+        lock.push(child);
+    }
+    Ok(())
+}
+
+/// Kills all spawned and tracked child processes. Called automatically on application exit.
+pub fn cleanup_spawned_processes() {
+    if let Ok(mut lock) = TRACKED_PROCESSES.lock() {
+        for mut child in lock.drain(..) {
+            let _ = child.kill();
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -29,4 +50,11 @@ mod tests {
         let cmd = Command::new("true");
         assert!(spawn_detached(cmd).is_ok());
     }
+
+    #[test]
+    fn test_spawn_tracked() {
+        let cmd = Command::new("true");
+        assert!(spawn_tracked(cmd).is_ok());
+        cleanup_spawned_processes();
+    }
 }
diff --git a/src/widget/container/container_layout.rs b/src/widget/container/container_layout.rs
index b099704..83fbb33 100644
--- a/src/widget/container/container_layout.rs
+++ b/src/widget/container/container_layout.rs
@@ -67,6 +67,49 @@ impl ContainerLayout for OverlayLayout {
     }
 }
 
+#[derive(Debug, Clone, Copy, Default, PartialEq)]
+pub struct ManualLayout {
+    left: f32,
+    top: f32,
+    width: f32,
+    height: f32,
+}
+
+impl crate::layout::LayoutStrategy for ManualLayout {
+    fn init(&mut self, left: f32, top: f32, width: f32, height: f32) {
+        self.left = left;
+        self.top = top;
+        self.width = width;
+        self.height = height;
+    }
+
+    fn allocate(&mut self, _ww: f32, _wh: f32) -> (f32, f32, f32, f32) {
+        (self.left, self.top, self.width, self.height)
+    }
+
+    fn layout(&self, _x: f32, _y: f32, _w: f32, _h: f32, _children: &[*mut (dyn Element + 'static)], _ctx: &mut UiContext) -> f32 {
+        self.height
+    }
+
+    fn measure(&self, constraints: LayoutConstraints, _children: &[*mut (dyn Element + 'static)], _ctx: &UiContext) -> Size {
+        Size {
+            width: self.width.clamp(constraints.min_width, constraints.max_width),
+            height: self.height.clamp(constraints.min_height, constraints.max_height),
+        }
+    }
+
+    fn box_clone(&self) -> Box<dyn crate::layout::LayoutStrategy> {
+        Box::new(*self)
+    }
+}
+
+impl ContainerLayout for ManualLayout {
+    fn box_clone_container(&self) -> Box<dyn ContainerLayout> {
+        Box::new(*self)
+    }
+}
+
+
 #[derive(Debug, Clone, Copy)]
 pub struct VerticalLayout {
     pub padding_x: f32,
diff --git a/src/widget/container/hbox.rs b/src/widget/container/hbox.rs
new file mode 100644
index 0000000..42823bf
--- /dev/null
+++ b/src/widget/container/hbox.rs
@@ -0,0 +1,69 @@
+use crate::widget::*;
+
+pub struct HBox {
+    pub base: Widget,
+    pub children: Vec<*mut (dyn Element + 'static)>,
+    pub parent: Option<*mut (dyn Element + 'static)>,
+    pub gap: f32,
+    pub margin: f32,
+}
+
+impl HBox {
+    pub fn new(gap: f32, margin: f32) -> Self {
+        Self {
+            base: Widget::new(),
+            children: Vec::new(),
+            parent: None,
+            gap,
+            margin,
+        }
+    }
+
+    pub fn add_child(&mut self, child: *mut (dyn Element + 'static)) {
+        self.children.push(child);
+    }
+}
+
+impl Element for HBox {
+    crate::impl_widget_base!(HBox);
+
+    fn color(&self) -> [f32; 4] {
+        [0.0, 0.0, 0.0, 0.0]
+    }
+
+    fn children(&self, _ctx: &UiContext) -> Vec<*mut (dyn Element + 'static)> {
+        self.children.clone()
+    }
+
+    fn parent(&self, _ctx: &UiContext) -> Option<*mut (dyn Element + 'static)> {
+        self.parent
+    }
+
+    fn set_parent(&mut self, parent: Option<*mut (dyn Element + 'static)>, _ctx: &mut UiContext) {
+        self.parent = parent;
+    }
+
+    fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) {
+        self.base.x = x;
+        self.base.y = y;
+        self.base.w = w;
+        self.base.h = h;
+
+        let count = self.children.len();
+        if count == 0 {
+            return;
+        }
+
+        let total_w = w - 2.0 * self.margin;
+        let child_w = (total_w - (count as f32 - 1.0) * self.gap) / count as f32;
+        let child_h = h - 2.0 * self.margin;
+        let mut current_x = x + self.margin;
+
+        for &child_ptr in &self.children {
+            unsafe {
+                (*child_ptr).set_rect(current_x, y + self.margin, child_w, child_h);
+                current_x += child_w + self.gap;
+            }
+        }
+    }
+}
diff --git a/src/widget/container/mod.rs b/src/widget/container/mod.rs
index 92e1b12..09089e8 100644
--- a/src/widget/container/mod.rs
+++ b/src/widget/container/mod.rs
@@ -24,7 +24,7 @@ pub mod hbox;
 
 pub use container::Container;
 pub use control_panel::ControlPanel;
-pub use container_layout::{ContainerLayout, OverlayLayout, VerticalLayout, GridLayout, AdaptiveGridLayout, ColumnsLayout, MosaicLayout, ReverseMosaicLayout};
+pub use container_layout::{ContainerLayout, OverlayLayout, ManualLayout, VerticalLayout, GridLayout, AdaptiveGridLayout, ColumnsLayout, MosaicLayout, ReverseMosaicLayout};
 pub use section_container::SectionContainer;
 pub use header::Header;
 pub use content_bg::ContentBg;
diff --git a/src/widget/container/parameters_bg.rs b/src/widget/container/parameters_bg.rs
index f48fe4a..c09f245 100644
--- a/src/widget/container/parameters_bg.rs
+++ b/src/widget/container/parameters_bg.rs
@@ -285,7 +285,7 @@ impl Element for ParametersBg {
     crate::impl_widget_base!(ParametersBg);
 
     fn widget_font(&self) -> Option<String> {
-        Some(crate::layout::label_font())
+        Some(crate::layout::control_label_font())
     }
 
     fn rounded_corners(&self) -> (bool, bool, bool, bool) { (true, true, true, true) }
diff --git a/src/widget/container/plate.rs b/src/widget/container/plate.rs
index 6e02746..7589a17 100644
--- a/src/widget/container/plate.rs
+++ b/src/widget/container/plate.rs
@@ -224,6 +224,7 @@ impl Element for Plate {
     }
 
     fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) {
+        let label_off = self.base.base.label_offset();
         let (clamped_x, clamped_y, clamped_w, clamped_h) = if let Some(parent_ptr) = self.base.parent {
             let (px, py, pw, ph) = unsafe { (*parent_ptr).rect() };
             let cx = x.clamp(px, px + pw.max(0.0));
@@ -238,7 +239,7 @@ impl Element for Plate {
         self.base.base.x = clamped_x;
         self.base.base.y = clamped_y;
         self.base.base.w = clamped_w;
-        self.base.base.h = clamped_h;
+        self.base.base.h = clamped_h + label_off;
 
         if !self.base.visible {
             return;
@@ -249,7 +250,7 @@ impl Element for Plate {
         let padding_y = pad;
         let left_x = clamped_x + padding_x;
         let available_w = (clamped_w - 2.0 * padding_x).max(1.0);
-        let start_y = clamped_y + padding_y;
+        let start_y = clamped_y + label_off + padding_y;
         let available_h = (clamped_h - 2.0 * padding_y).max(1.0);
 
         let center_x = left_x + available_w / 2.0;
@@ -287,7 +288,7 @@ impl Element for Plate {
                 let cx = (center_x - use_w / 2.0).clamp(left_x, (left_x + available_w - use_w).max(left_x));
                 let cy = (center_y - use_h / 2.0).clamp(start_y, (start_y + available_h - use_h).max(start_y));
                 let cw = use_w.min(clamped_x + clamped_w - padding_x - cx);
-                let ch = use_h.min(clamped_y + clamped_h - padding_y - cy);
+                let ch = use_h.min(clamped_y + label_off + clamped_h - padding_y - cy);
                 w.set_rect(cx, cy, cw, ch);
             } else {
                 let mut ring = 1;
@@ -309,7 +310,7 @@ impl Element for Plate {
                         let cx = raw_x.clamp(left_x, (left_x + available_w - use_w).max(left_x));
                         let cy = raw_y.clamp(start_y, (start_y + available_h - use_h).max(start_y));
                         let cw = use_w.min(clamped_x + clamped_w - padding_x - cx);
-                        let ch = use_h.min(clamped_y + clamped_h - padding_y - cy);
+                        let ch = use_h.min(clamped_y + label_off + clamped_h - padding_y - cy);
 
                         w.set_rect(cx, cy, cw, ch);
                         placed = true;
@@ -366,6 +367,28 @@ impl Element for Plate {
         ctx.clear_children_ids(id);
     }
 
+    fn all_rounded_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, f32, [f32; 4], (bool, bool, bool, bool))> {
+        if !self.visible {
+            return Vec::new();
+        }
+        let mut quads = Vec::new();
+        let (r1, r2, r3, r4) = self.rounded_corners();
+        if r1 || r2 || r3 || r4 {
+            let (x, y, w, h) = self.rect();
+            let label_off = self.base.base.label_offset();
+            let radius = self.corner_radius();
+            let c = self.color();
+            if c[3].abs() > 0.001 {
+                quads.push((x, y + label_off, w, h - label_off, radius, c, (r1, r2, r3, r4)));
+            }
+        }
+        for &child_ptr in &self.base.children {
+            let widget = unsafe { &*child_ptr };
+            quads.extend(widget.all_rounded_quads(ctx));
+        }
+        quads
+    }
+
     fn all_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
         if !self.visible {
             return Vec::new();
@@ -374,7 +397,8 @@ impl Element for Plate {
         let (px, py, pw, ph) = self.rect();
         let has_rounded = self.rounded_corners() != (false, false, false, false);
         if !has_rounded {
-            quads.push((px, py, pw, ph, self.color()));
+            let label_off = self.base.base.label_offset();
+            quads.push((px, py + label_off, pw, ph - label_off, self.color()));
         }
 
         for &child_ptr in &self.base.children {
@@ -397,12 +421,13 @@ impl Element for Plate {
         }
         let mut labels = Vec::new();
         if let Some(ref label) = self.base.base.label {
+            let (_, font_size) = crate::layout::control_label_font_parsed();
             labels.push(TextLabel {
                 text: label.clone(),
                 x: self.base.base.x,
-                y: self.base.base.y - (12.0 + crate::layout::label_margin()),
-                font_size: 12.0,
-                color: [0x83, 0x83, 0x8a],
+                y: self.base.base.y,
+                font_size,
+                color: colors::control_label_color_u8(),
             });
         }
         for &child_ptr in &self.base.children {
@@ -418,13 +443,14 @@ impl Element for Plate {
         }
         let mut result = Vec::new();
         if let Some(ref label) = self.base.base.label {
+            let (_, font_size) = crate::layout::control_label_font_parsed();
             result.push((
                 TextLabel {
                     text: label.clone(),
                     x: self.base.base.x,
-                    y: self.base.base.y - (12.0 + crate::layout::label_margin()),
-                    font_size: 12.0,
-                    color: [0x83, 0x83, 0x8a],
+                    y: self.base.base.y,
+                    font_size,
+                    color: colors::control_label_color_u8(),
                 },
                 None,
             ));
@@ -442,13 +468,14 @@ impl Element for Plate {
         }
         let mut result = Vec::new();
         if let Some(ref label) = self.base.base.label {
+            let (_, font_size) = crate::layout::control_label_font_parsed();
             result.push((
                 TextLabel {
                     text: label.clone(),
                     x: self.base.base.x,
-                    y: self.base.base.y - (12.0 + crate::layout::label_margin()),
-                    font_size: 12.0,
-                    color: [0x83, 0x83, 0x8a],
+                    y: self.base.base.y,
+                    font_size,
+                    color: colors::control_label_color_u8(),
                 },
                 None,
                 None,
diff --git a/src/widget/container/vbox.rs b/src/widget/container/vbox.rs
new file mode 100644
index 0000000..d218ab0
--- /dev/null
+++ b/src/widget/container/vbox.rs
@@ -0,0 +1,66 @@
+use crate::widget::*;
+
+pub struct VBox {
+    pub base: Widget,
+    pub children: Vec<*mut (dyn Element + 'static)>,
+    pub parent: Option<*mut (dyn Element + 'static)>,
+    pub gap: f32,
+    pub margin: f32,
+}
+
+impl VBox {
+    pub fn new(gap: f32, margin: f32) -> Self {
+        Self {
+            base: Widget::new(),
+            children: Vec::new(),
+            parent: None,
+            gap,
+            margin,
+        }
+    }
+
+    pub fn add_child(&mut self, child: *mut (dyn Element + 'static)) {
+        self.children.push(child);
+    }
+}
+
+impl Element for VBox {
+    crate::impl_widget_base!(VBox);
+
+    fn color(&self) -> [f32; 4] {
+        [0.0, 0.0, 0.0, 0.0]
+    }
+
+    fn children(&self, _ctx: &UiContext) -> Vec<*mut (dyn Element + 'static)> {
+        self.children.clone()
+    }
+
+    fn parent(&self, _ctx: &UiContext) -> Option<*mut (dyn Element + 'static)> {
+        self.parent
+    }
+
+    fn set_parent(&mut self, parent: Option<*mut (dyn Element + 'static)>, _ctx: &mut UiContext) {
+        self.parent = parent;
+    }
+
+    fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) {
+        self.base.x = x;
+        self.base.y = y;
+        self.base.w = w;
+        self.base.h = h;
+
+        let mut current_y = y + self.margin;
+        let child_w = w - 2.0 * self.margin;
+
+        for &child_ptr in &self.children {
+            unsafe {
+                let preferred_h = (*child_ptr).preferred_height().unwrap_or(24.0);
+                let label_off = (*child_ptr).base().map_or(0.0, |b| b.label_offset());
+                let total_h = preferred_h + label_off;
+                
+                (*child_ptr).set_rect(x + self.margin, current_y, child_w, preferred_h);
+                current_y += total_h + self.gap;
+            }
+        }
+    }
+}
diff --git a/src/widget/core.rs b/src/widget/core.rs
index ef84086..ab63a0d 100644
--- a/src/widget/core.rs
+++ b/src/widget/core.rs
@@ -756,8 +756,12 @@ impl Widget {
     }
 
     pub fn label_offset(&self) -> f32 {
+        if crate::layout::control_label_layout() == "side" {
+            return 0.0;
+        }
         if self.label.is_some() {
-            12.0 + crate::layout::label_margin()
+            let (_, font_size) = crate::layout::control_label_font_detached_parsed();
+            font_size + crate::layout::control_label_margin()
         } else {
             0.0
         }
diff --git a/src/widget/display/label.rs b/src/widget/display/label.rs
index 3a9a5ad..b0b9520 100644
--- a/src/widget/display/label.rs
+++ b/src/widget/display/label.rs
@@ -12,10 +12,11 @@ impl Label {
     pub fn new(text: &str) -> Self {
         let mut base = Widget::new();
         base.label = Some(text.to_string());
+        let (_, font_size) = crate::layout::control_label_font_parsed();
         Self {
             base,
-            font_size: 12.0,
-            color: [0x83, 0x83, 0x8a],
+            font_size,
+            color: colors::control_label_color_u8(),
         }
     }
 
diff --git a/src/widget/display/status_bar.rs b/src/widget/display/status_bar.rs
index fa5ca32..01a6104 100644
--- a/src/widget/display/status_bar.rs
+++ b/src/widget/display/status_bar.rs
@@ -94,7 +94,10 @@ impl Element for StatusBar {
     fn color(&self) -> [f32; 4] {
         if let Some(p_ptr) = self.parent {
             if unsafe { (*p_ptr).is_backplate() } {
-                return crate::colors::backplate_statusbar_color();
+                let theme_color = crate::colors::backplate_statusbar_color();
+                if theme_color[3] > 0.001 {
+                    return theme_color;
+                }
             }
         }
         self.bg_color.unwrap_or(colors::STATUS_BG)
diff --git a/src/widget/input/button.rs b/src/widget/input/button.rs
index ec36e6f..22fddff 100644
--- a/src/widget/input/button.rs
+++ b/src/widget/input/button.rs
@@ -258,7 +258,7 @@ impl Element for Button {
                         if self.selected { [230, 230, 242] }
                         else { [178, 178, 191] }
                     }
-                    _ => [0xcc, 0xcc, 0xd4]
+                    _ => colors::control_label_color_u8()
                 }
             };
             let justify = if self.kind == ButtonKind::ListRow {
@@ -289,10 +289,37 @@ impl Element for Button {
         self.selected = selected;
     }
 
+    fn all_rounded_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, f32, [f32; 4], (bool, bool, bool, bool))> {
+        let mut quads = Vec::new();
+        let (r1, r2, r3, r4) = self.rounded_corners();
+        if r1 || r2 || r3 || r4 {
+            let radius = self.corner_radius();
+            let c = self.color();
+            if let Some(bc) = colors::button_border_color() {
+                quads.push((self.base.x, self.base.y, self.base.w, self.base.h, radius, bc, (r1, r2, r3, r4)));
+                quads.push((self.base.x + 1.0, self.base.y + 1.0, self.base.w - 2.0, self.base.h - 2.0, (radius - 1.0).max(0.0), c, (r1, r2, r3, r4)));
+            } else {
+                if c[3].abs() > 0.001 {
+                    quads.push((self.base.x, self.base.y, self.base.w, self.base.h, radius, c, (r1, r2, r3, r4)));
+                }
+            }
+        }
+        for &child_ptr in &self.children(ctx) {
+            let widget = unsafe { &*child_ptr };
+            quads.extend(widget.all_rounded_quads(ctx));
+        }
+        quads
+    }
+
     fn extra_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
         let mut quads = Vec::new();
         if self.corner_radius() <= 0.0 {
-            quads.push((self.base.x, self.base.y, self.base.w, self.base.h, self.color()));
+            if let Some(bc) = colors::button_border_color() {
+                quads.push((self.base.x, self.base.y, self.base.w, self.base.h, bc));
+                quads.push((self.base.x + 1.0, self.base.y + 1.0, self.base.w - 2.0, self.base.h - 2.0, self.color()));
+            } else {
+                quads.push((self.base.x, self.base.y, self.base.w, self.base.h, self.color()));
+            }
         }
         if let Some(ref svg) = self.svg {
             let svg_x = self.base.x + (self.base.w - svg.w) / 2.0;
@@ -319,7 +346,7 @@ impl Element for Button {
         if self.kind == ButtonKind::ListRow {
             Some(crate::layout::list_font())
         } else {
-            Some(crate::layout::button_font())
+            Some(crate::layout::control_label_font())
         }
     }
 
diff --git a/src/widget/input/button_strip.rs b/src/widget/input/button_strip.rs
index aca3e20..0a740ed 100644
--- a/src/widget/input/button_strip.rs
+++ b/src/widget/input/button_strip.rs
@@ -15,6 +15,7 @@ pub struct ButtonStrip {
     pub tab_quads_cache: std::collections::HashMap<String, Vec<(f32, f32, f32, f32, [f32; 4])>>,
     pub last_padding: Option<f32>,
     pub last_font: Option<String>,
+    pub last_scale: Option<f32>,
 }
 
 impl ButtonStrip {
@@ -31,6 +32,7 @@ impl ButtonStrip {
             tab_quads_cache: std::collections::HashMap::new(),
             last_padding: None,
             last_font: None,
+            last_scale: None,
         }
     }
 
@@ -94,6 +96,7 @@ impl ButtonStrip {
 
         let (font_fam, font_size) = crate::layout::button_strip_font_parsed();
         let scale = crate::scale::scale_factor().max(1.0);
+        self.last_scale = Some(scale);
 
         for (i, page_name) in self.buttons.iter().enumerate() {
             let color = if self.selected == Some(i) {
@@ -262,7 +265,11 @@ impl Element for ButtonStrip {
         let mut changed = false;
         let current_padding = crate::layout::button_padding();
         let current_font = crate::layout::button_strip_font();
-        if self.last_padding != Some(current_padding) || self.last_font.as_ref() != Some(&current_font) {
+        let current_scale = crate::scale::scale_factor().max(1.0);
+        if self.last_padding != Some(current_padding)
+            || self.last_font.as_ref() != Some(&current_font)
+            || self.last_scale != Some(current_scale)
+        {
             self.generate_rotated_labels();
             changed = true;
         }
diff --git a/src/widget/input/checkbox.rs b/src/widget/input/checkbox.rs
index b3f390c..285d5b7 100644
--- a/src/widget/input/checkbox.rs
+++ b/src/widget/input/checkbox.rs
@@ -156,14 +156,14 @@ impl Element for Checkbox {
     fn text_labels(&self) -> Vec<TextLabel> {
         let mut labels = Vec::new();
         if let Some(ref label) = self.base.label {
-            let font_size = 12.0;
+            let (_, font_size) = crate::layout::control_label_font_parsed();
             let y = crate::layout::align_text_y(self.base.y, self.base.h, font_size, 0.0);
             labels.push(TextLabel {
                 text: label.clone(),
                 x: self.base.x + 8.0,
                 y,
                 font_size,
-                color: [0xcc, 0xcc, 0xd4],
+                color: colors::control_label_color_for_state(self.base.hovered, self.base.focused),
             });
         }
         labels
@@ -274,7 +274,7 @@ impl Element for Toggle {
     }
 
     fn widget_font(&self) -> Option<String> {
-        Some(crate::layout::toggle_font())
+        Some(crate::layout::control_label_font())
     }
 
     fn mouse_input(&mut self, button: MouseButton, state: ElementState, px: f32, py: f32, ctx: &mut UiContext) -> bool {
@@ -394,15 +394,14 @@ impl Element for Toggle {
     fn text_labels(&self) -> Vec<TextLabel> {
         let mut labels = Vec::new();
         if let Some(ref label) = self.base.label {
-            let font_size = 12.0;
-            let font_fam = crate::layout::toggle_font_parsed().0;
+            let (font_fam, font_size) = crate::layout::control_label_font_parsed();
             let est_w = crate::widget::display::measure_text_width(label, &font_fam, font_size);
             labels.push(TextLabel {
                 text: label.clone(),
                 x: self.base.x + (self.base.w - est_w) / 2.0,
                 y: crate::layout::align_text_y(self.base.y, self.base.h, font_size, 0.0),
                 font_size,
-                color: [0xcc, 0xcc, 0xd4],
+                color: colors::control_label_color_for_state(self.base.hovered, self.base.focused),
             });
         }
         labels
diff --git a/src/widget/input/dropdown.rs b/src/widget/input/dropdown.rs
index 85d8e91..d52b246 100644
--- a/src/widget/input/dropdown.rs
+++ b/src/widget/input/dropdown.rs
@@ -71,7 +71,7 @@ impl Dropdown {
 
     pub fn popover_width(&self) -> f32 {
         let mut w = self.base.w;
-        let font_setting = crate::layout::dropdown_font();
+        let font_setting = crate::layout::control_label_font_detached();
         let (font_family, font_size_opt) = crate::layout::parse_font_string(&font_setting);
         let font_size = font_size_opt.unwrap_or(12.0);
         for opt in &self.options {
@@ -88,8 +88,9 @@ impl Dropdown {
         let rh = self.options.len() as f32 * 24.0;
         
         let open_upward = self.open_upward.unwrap_or_else(|| self.base.y > 400.0);
+        let label_x = self.label_x_offset();
         
-        let mut rx = self.base.x;
+        let mut rx = self.base.x + label_x;
         let mut ry = if open_upward {
             let label_offset = self.base.label_offset();
             self.base.y + label_offset - rh
@@ -297,16 +298,21 @@ impl Element for Dropdown {
             let border_color = if self.open {
                 [0.30, 0.50, 0.32, 1.0]
             } else if self.base.hovered {
-                [0.25, 0.25, 0.35, 1.0]
+                let bc = colors::dropdown_border_color();
+                [(bc[0] + 0.15).min(1.0), (bc[1] + 0.15).min(1.0), (bc[2] + 0.15).min(1.0), bc[3]]
             } else {
-                [0.18, 0.18, 0.24, 1.0]
+                colors::dropdown_border_color()
             };
 
+            let label_x = self.label_x_offset();
+            let x = self.base.x + label_x;
+            let w = self.base.w - label_x;
+
             // Draw border
-            quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, radius, border_color, (r1, r2, r3, r4)));
+            quads.push((x, self.base.y + top, w, visual_h, radius, border_color, (r1, r2, r3, r4)));
             // Draw background (slightly inset to show border)
             let inner_radius = (radius - 1.0).max(0.0);
-            quads.push((self.base.x + 1.0, self.base.y + top + 1.0, self.base.w - 2.0, visual_h - 2.0, inner_radius, bg_color, (r1, r2, r3, r4)));
+            quads.push((x + 1.0, self.base.y + top + 1.0, w - 2.0, visual_h - 2.0, inner_radius, bg_color, (r1, r2, r3, r4)));
         }
         for &child_ptr in &self.children(ctx) {
             let widget = unsafe { &*child_ptr };
@@ -316,7 +322,7 @@ impl Element for Dropdown {
     }
 
     fn widget_font(&self) -> Option<String> {
-        Some(crate::layout::dropdown_font())
+        Some(crate::layout::control_label_font_detached())
     }
 
     fn hit_test(&self, px: f32, py: f32, ctx: &UiContext) -> bool {
@@ -497,13 +503,18 @@ impl Element for Dropdown {
         let border_color = if self.open {
             [0.30, 0.50, 0.32, 1.0]
         } else if self.base.hovered {
-            [0.25, 0.25, 0.35, 1.0]
+            let bc = colors::dropdown_border_color();
+            [(bc[0] + 0.15).min(1.0), (bc[1] + 0.15).min(1.0), (bc[2] + 0.15).min(1.0), bc[3]]
         } else {
-            [0.18, 0.18, 0.24, 1.0]
+            colors::dropdown_border_color()
         };
 
-        quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, border_color));
-        quads.push((self.base.x + 1.0, self.base.y + top + 1.0, self.base.w - 2.0, visual_h - 2.0, bg_color));
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+
+        quads.push((x, self.base.y + top, w, visual_h, border_color));
+        quads.push((x + 1.0, self.base.y + top + 1.0, w - 2.0, visual_h - 2.0, bg_color));
 
         quads
     }
@@ -523,12 +534,20 @@ impl Element for Dropdown {
             self.options.get(self.selected).cloned().unwrap_or_default()
         };
 
-        let font_family = crate::layout::dropdown_font_parsed().0;
-        let start_x = self.base.x + 8.0;
-        let right_limit = self.base.x + self.base.w - 28.0; // 10px margin before the arrow
+        let font_family = crate::layout::control_label_font_detached_parsed().0;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+        let start_x = x + 8.0;
+        let right_limit = x + w - 28.0; // 10px margin before the arrow
         let fade_start_x = (right_limit - 24.0).max(start_x); // Fade out over the last 24px
         let text_y = crate::layout::align_text_y(self.base.y, self.base.h, 12.0, top);
-        let default_color = [0xdd, 0xdd, 0xe2];
+        let tc = colors::dropdown_text_color();
+        let default_color = [
+            (colors::linear_to_srgb(tc[0]) * 255.0).round() as u8,
+            (colors::linear_to_srgb(tc[1]) * 255.0).round() as u8,
+            (colors::linear_to_srgb(tc[2]) * 255.0).round() as u8,
+        ];
         let bg_color = colors::dropdown_background_color();
         let mut parent_color = colors::page_color();
         if let Some(parent_ptr) = self.parent {
@@ -643,9 +662,13 @@ impl Element for Dropdown {
             }
         }
 
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+
         labels.push(TextLabel {
             text: "â–¼".to_string(),
-            x: self.base.x + self.base.w - 18.0,
+            x: x + w - 18.0,
             y: crate::layout::align_text_y(self.base.y, self.base.h, 10.0, top),
             font_size: 10.0,
             color: [0x83, 0x83, 0x8a],
@@ -835,8 +858,14 @@ mod tests {
         let first_char = &labels[0];
         let last_char = &labels[last_char_idx];
         
-        assert_eq!(first_char.color, [0xdd, 0xdd, 0xe2]);
-        assert_ne!(last_char.color, [0xdd, 0xdd, 0xe2]); // color has shifted towards background
+        let tc = colors::dropdown_text_color();
+        let expected_color = [
+            (colors::linear_to_srgb(tc[0]) * 255.0).round() as u8,
+            (colors::linear_to_srgb(tc[1]) * 255.0).round() as u8,
+            (colors::linear_to_srgb(tc[2]) * 255.0).round() as u8,
+        ];
+        assert_eq!(first_char.color, expected_color);
+        assert_ne!(last_char.color, expected_color); // color has shifted towards background
     }
 }
 
diff --git a/src/widget/input/ramp.rs b/src/widget/input/ramp.rs
index 346752f..be7d8a8 100644
--- a/src/widget/input/ramp.rs
+++ b/src/widget/input/ramp.rs
@@ -808,18 +808,14 @@ impl Element for Ramp {
         }
         let mut quads = Vec::new();
         
-        let track_x = self.base.x + 10.0;
-        let track_w = self.base.w - 20.0;
-        let ch = self.base.h - 20.0;
-        
         let border_color = colors::ramp_border_color();
         let bg_color = [0.15, 0.15, 0.18, 1.0];
         let radius = 6.0f32;
         
-        // Draw container border (rounded quad)
-        quads.push((track_x - 1.0, self.base.y + 10.0 - 1.0, track_w + 2.0, ch + 2.0, radius, border_color, (true, true, true, true)));
-        // Draw container background (rounded quad)
-        quads.push((track_x, self.base.y + 10.0, track_w, ch, (radius - 1.0).max(0.0), bg_color, (true, true, true, true)));
+        // Draw container border (rounded quad) using full widget bounds
+        quads.push((self.base.x - 1.0, self.base.y - 1.0, self.base.w + 2.0, self.base.h + 2.0, radius, border_color, (true, true, true, true)));
+        // Draw container background (rounded quad) using full widget bounds
+        quads.push((self.base.x, self.base.y, self.base.w, self.base.h, (radius - 1.0).max(0.0), bg_color, (true, true, true, true)));
         
         // Extend children's rounded quads
         for &child_ptr in &self.children(ctx) {
@@ -1013,13 +1009,16 @@ impl Element for Ramp {
             (track_w - gap) / 2.0
         };
         
+        let (_, font_size) = crate::layout::control_label_font_detached_parsed();
+        let label_color = colors::control_label_color_detached_u8();
+
         labels.push((
             TextLabel {
                 text: "Preset".to_string(),
                 x: track_x + 4.0,
                 y: sy - 2.0,
-                font_size: 12.0,
-                color: [0x83, 0x83, 0x8a],
+                font_size,
+                color: label_color,
             },
             self.preset_dropdown.widget_font(),
             None,
@@ -1030,8 +1029,8 @@ impl Element for Ramp {
                 text: "Line Type".to_string(),
                 x: track_x + col_w + gap + 4.0,
                 y: sy - 2.0,
-                font_size: 12.0,
-                color: [0x83, 0x83, 0x8a],
+                font_size,
+                color: label_color,
             },
             self.line_type_dropdown.widget_font(),
             None,
@@ -1043,8 +1042,8 @@ impl Element for Ramp {
                     text: "Value".to_string(),
                     x: track_x + 2.0 * (col_w + gap) + 4.0,
                     y: sy - 2.0,
-                    font_size: 12.0,
-                    color: [0x83, 0x83, 0x8a],
+                    font_size,
+                    color: label_color,
                 },
                 self.val_slider.widget_font(),
                 None,
diff --git a/src/widget/input/slider.rs b/src/widget/input/slider.rs
index 626a54c..f6b31af 100644
--- a/src/widget/input/slider.rs
+++ b/src/widget/input/slider.rs
@@ -121,7 +121,7 @@ impl Element for Slider {
     }
 
     fn widget_font(&self) -> Option<String> {
-        Some(crate::layout::slider_font())
+        Some(crate::layout::control_label_font_detached())
     }
 
     fn get_value_string(&self) -> Option<String> {
@@ -183,13 +183,16 @@ impl Element for Slider {
     fn drag_update(&mut self, px: f32, _py: f32) -> bool {
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
         let (track_x, track_w) = if self.show_readout {
             let readout_w = 60.0;
             let gap = 8.0;
-            let tw = (self.base.w - readout_w - gap).max(10.0);
-            (self.base.x, tw)
+            let tw = (w - readout_w - gap).max(10.0);
+            (x, tw)
         } else {
-            (self.base.x, self.base.w)
+            (x, w)
         };
         let thumb_size = visual_h * 0.9;
         let range = track_w - thumb_size;
@@ -213,13 +216,16 @@ impl Element for Slider {
         self.dragging = true;
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
         let (track_x, track_w) = if self.show_readout {
             let readout_w = 60.0;
             let gap = 8.0;
-            let tw = (self.base.w - readout_w - gap).max(10.0);
-            (self.base.x, tw)
+            let tw = (w - readout_w - gap).max(10.0);
+            (x, tw)
         } else {
-            (self.base.x, self.base.w)
+            (x, w)
         };
         let thumb_size = visual_h * 0.9;
         let thumb_x = track_x + self.value * (track_w - thumb_size);
@@ -273,10 +279,13 @@ impl Element for Slider {
         
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
         
         if self.show_readout {
             let readout_w = 60.0;
-            let rx = self.base.x + self.base.w - readout_w;
+            let rx = x + w - readout_w;
             
             if px >= rx && px <= rx + readout_w && py >= self.base.y + top && py <= self.base.y + top + visual_h {
                 if state == ElementState::Pressed {
@@ -296,10 +305,10 @@ impl Element for Slider {
                 let (track_x, track_w) = if self.show_readout {
                     let readout_w = 60.0;
                     let gap = 8.0;
-                    let tw = (self.base.w - readout_w - gap).max(10.0);
-                    (self.base.x, tw)
+                    let tw = (w - readout_w - gap).max(10.0);
+                    (x, tw)
                 } else {
-                    (self.base.x, self.base.w)
+                    (x, w)
                 };
                 let thumb_size = visual_h * 0.9;
                 let thumb_x = track_x + self.value * (track_w - thumb_size);
@@ -390,15 +399,18 @@ impl Element for Slider {
         let mut quads = Vec::new();
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
         
         let (track_x, track_w) = if self.show_readout {
             let readout_w = 60.0;
             let gap = 8.0;
-            let tw = (self.base.w - readout_w - gap).max(10.0);
+            let tw = (w - readout_w - gap).max(10.0);
             
-            quads.push((self.base.x, self.base.y + top, tw, visual_h, colors::slider_track()));
+            quads.push((x, self.base.y + top, tw, visual_h, colors::slider_track()));
             
-            let rx = self.base.x + self.base.w - readout_w;
+            let rx = x + w - readout_w;
             let bg_color = if self.editing {
                 [0.06, 0.10, 0.18, 1.0]
             } else {
@@ -415,19 +427,25 @@ impl Element for Slider {
                 quads.push((rx + readout_w - border_t, self.base.y + top, border_t, visual_h, border_color));
             }
 
-            (self.base.x, tw)
+            (x, tw)
         } else {
-            quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, colors::slider_track()));
-            (self.base.x, self.base.w)
+            quads.push((x, self.base.y + top, w, visual_h, colors::slider_track()));
+            (x, w)
         };
 
         let thumb_size = visual_h * 0.9;
         let thumb_x = track_x + self.value * (track_w - thumb_size);
+
+        if let Some(fill_color) = colors::slider_fill() {
+            let fill_w = (thumb_x + thumb_size / 2.0 - track_x).max(0.0).min(track_w);
+            quads.push((track_x, self.base.y + top, fill_w, visual_h, fill_color));
+        }
+
         let thumb_y = self.base.y + top + (visual_h - thumb_size) / 2.0;
         let thumb_color = if self.dragging {
-            colors::SLIDER_THUMB_DRAG
+            colors::slider_thumb_drag()
         } else {
-            colors::SLIDER_THUMB
+            colors::slider_thumb()
         };
         quads.push((thumb_x, thumb_y, thumb_size, thumb_size, thumb_color));
         
@@ -444,15 +462,18 @@ impl Element for Slider {
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
         let radius = self.corner_radius();
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
         
         let (track_x, track_w) = if self.show_readout {
             let readout_w = 60.0;
             let gap = 8.0;
-            let tw = (self.base.w - readout_w - gap).max(10.0);
+            let tw = (w - readout_w - gap).max(10.0);
             
-            quads.push((self.base.x, self.base.y + top, tw, visual_h, radius, colors::slider_track(), (r1, r2, r3, r4)));
+            quads.push((x, self.base.y + top, tw, visual_h, radius, colors::slider_track(), (r1, r2, r3, r4)));
             
-            let rx = self.base.x + self.base.w - readout_w;
+            let rx = x + w - readout_w;
             let bg_color = if self.editing {
                 [0.06, 0.10, 0.18, 1.0]
             } else {
@@ -468,19 +489,25 @@ impl Element for Slider {
                 quads.push((rx, self.base.y + top, readout_w, visual_h, radius, bg_color, (r1, r2, r3, r4)));
             }
 
-            (self.base.x, tw)
+            (x, tw)
         } else {
-            quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, radius, colors::slider_track(), (r1, r2, r3, r4)));
-            (self.base.x, self.base.w)
+            quads.push((x, self.base.y + top, w, visual_h, radius, colors::slider_track(), (r1, r2, r3, r4)));
+            (x, w)
         };
 
         let thumb_size = visual_h * 0.9;
         let thumb_x = track_x + self.value * (track_w - thumb_size);
+
+        if let Some(fill_color) = colors::slider_fill() {
+            let fill_w = (thumb_x + thumb_size / 2.0 - track_x).max(0.0).min(track_w);
+            quads.push((track_x, self.base.y + top, fill_w, visual_h, radius.min(visual_h / 2.0), fill_color, (true, true, true, true)));
+        }
+
         let thumb_y = self.base.y + top + (visual_h - thumb_size) / 2.0;
         let thumb_color = if self.dragging {
-            colors::SLIDER_THUMB_DRAG
+            colors::slider_thumb_drag()
         } else {
-            colors::SLIDER_THUMB
+            colors::slider_thumb()
         };
         quads.push((thumb_x, thumb_y, thumb_size, thumb_size, thumb_size / 2.0, thumb_color, (true, true, true, true)));
         
@@ -491,6 +518,9 @@ impl Element for Slider {
         let mut labels = Vec::new();
         let top = self.base.label_offset();
         let _visual_h = self.base.h - top;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
         
         if let Some(lbl) = self.control_label() {
             labels.push(lbl);
@@ -498,7 +528,7 @@ impl Element for Slider {
         
         if self.show_readout {
             let readout_w = 60.0;
-            let rx = self.base.x + self.base.w - readout_w;
+            let rx = x + w - readout_w;
             let ry = crate::layout::align_text_y(self.base.y, self.base.h, 12.0, top);
             
             let text = if self.editing {
@@ -597,7 +627,7 @@ impl Element for RangeSlider {
     }
 
     fn rounded_corners(&self) -> (bool, bool, bool, bool) {
-        let r = crate::layout::slider_corner_radius();
+        let r = crate::layout::rangeslider_corner_radius();
         if r > 0.0 {
             (true, true, true, true)
         } else {
@@ -606,7 +636,7 @@ impl Element for RangeSlider {
     }
 
     fn corner_radius(&self) -> f32 {
-        crate::layout::slider_corner_radius()
+        crate::layout::rangeslider_corner_radius()
     }
 
     fn draggable(&self) -> bool { true }
@@ -616,11 +646,14 @@ impl Element for RangeSlider {
         let Some(active) = self.active_thumb else { return false; };
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
         let thumb_size = visual_h * 0.9;
-        let range = self.base.w - thumb_size;
+        let range = w - thumb_size;
         if range <= 0.0 { return false; }
         
-        let new_val = ((px - self.drag_offset - self.base.x) / range).clamp(0.0, 1.0);
+        let new_val = ((px - self.drag_offset - x) / range).clamp(0.0, 1.0);
         match active {
             ActiveThumb::Low => {
                 let constrained = new_val.min(self.value_high);
@@ -643,10 +676,13 @@ impl Element for RangeSlider {
     fn drag_begin(&mut self, px: f32, _py: f32) {
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
         let thumb_size = visual_h * 0.9;
-        let range = self.base.w - thumb_size;
-        let thumb_low_x = self.base.x + self.value_low * range;
-        let thumb_high_x = self.base.x + self.value_high * range;
+        let range = w - thumb_size;
+        let thumb_low_x = x + self.value_low * range;
+        let thumb_high_x = x + self.value_high * range;
         let center_low = thumb_low_x + thumb_size / 2.0;
         let center_high = thumb_high_x + thumb_size / 2.0;
 
@@ -744,9 +780,12 @@ impl Element for RangeSlider {
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
         let thumb_size = visual_h * 0.9;
-        let range = self.base.w - thumb_size;
-        let thumb_low_x = self.base.x + self.value_low * range;
-        let thumb_high_x = self.base.x + self.value_high * range;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+        let range = w - thumb_size;
+        let thumb_low_x = x + self.value_low * range;
+        let thumb_high_x = x + self.value_high * range;
         
         let thumb_y = self.base.y + top + (visual_h - thumb_size) / 2.0;
         
@@ -757,19 +796,19 @@ impl Element for RangeSlider {
         let highlight_h = visual_h * 0.3;
         
         let low_color = if self.active_thumb == Some(ActiveThumb::Low) {
-            colors::SLIDER_THUMB_DRAG
+            colors::rangeslider_thumb_drag()
         } else {
-            colors::SLIDER_THUMB
+            colors::rangeslider_thumb()
         };
 
         let high_color = if self.active_thumb == Some(ActiveThumb::High) {
-            colors::SLIDER_THUMB_DRAG
+            colors::rangeslider_thumb_drag()
         } else {
-            colors::SLIDER_THUMB
+            colors::rangeslider_thumb()
         };
 
         vec![
-            (self.base.x, self.base.y + top, self.base.w, visual_h, colors::rangeslider_track()),
+            (x, self.base.y + top, w, visual_h, colors::rangeslider_track()),
             (highlight_x, highlight_y, highlight_w, highlight_h, colors::rangeslider_fill()),
             (thumb_low_x, thumb_y, thumb_size, thumb_size, low_color),
             (thumb_high_x, thumb_y, thumb_size, thumb_size, high_color),
@@ -788,9 +827,12 @@ impl Element for RangeSlider {
         let radius = self.corner_radius();
         
         let thumb_size = visual_h * 0.9;
-        let range = self.base.w - thumb_size;
-        let thumb_low_x = self.base.x + self.value_low * range;
-        let thumb_high_x = self.base.x + self.value_high * range;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+        let range = w - thumb_size;
+        let thumb_low_x = x + self.value_low * range;
+        let thumb_high_x = x + self.value_high * range;
         
         let thumb_y = self.base.y + top + (visual_h - thumb_size) / 2.0;
         
@@ -801,19 +843,19 @@ impl Element for RangeSlider {
         let highlight_h = visual_h * 0.3;
         
         let low_color = if self.active_thumb == Some(ActiveThumb::Low) {
-            colors::SLIDER_THUMB_DRAG
+            colors::rangeslider_thumb_drag()
         } else {
-            colors::SLIDER_THUMB
+            colors::rangeslider_thumb()
         };
 
         let high_color = if self.active_thumb == Some(ActiveThumb::High) {
-            colors::SLIDER_THUMB_DRAG
+            colors::rangeslider_thumb_drag()
         } else {
-            colors::SLIDER_THUMB
+            colors::rangeslider_thumb()
         };
         
         // Track background
-        quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, radius, colors::rangeslider_track(), (r1, r2, r3, r4)));
+        quads.push((x, self.base.y + top, w, visual_h, radius, colors::rangeslider_track(), (r1, r2, r3, r4)));
         // Progress fill (highlight track)
         quads.push((highlight_x, highlight_y, highlight_w, highlight_h, radius.min(highlight_h / 2.0), colors::rangeslider_fill(), (true, true, true, true)));
         // Low thumb
diff --git a/src/widget/input/spinbox.rs b/src/widget/input/spinbox.rs
index 1dcb672..b319ef9 100644
--- a/src/widget/input/spinbox.rs
+++ b/src/widget/input/spinbox.rs
@@ -144,7 +144,7 @@ impl Element for Spinbox {
 
     fn color(&self) -> [f32; 4] { [0.0, 0.0, 0.0, 0.0] }
     fn value(&self) -> i32 { self.value }
-    fn widget_font(&self) -> Option<String> { Some(crate::layout::spinbox_font()) }
+    fn widget_font(&self) -> Option<String> { Some(crate::layout::control_label_font_detached()) }
 
     fn on_cursor_moved(&mut self, px: f32, py: f32, ctx: &mut UiContext) -> bool {
         let was = self.base.hovered;
@@ -160,11 +160,14 @@ impl Element for Spinbox {
         let p = crate::layout::spinbox_button_padding();
         let btn_y = self.base.y + top + p;
         let btn_h = (visual_h - 2.0 * p).max(0.0);
-        let split_dec = self.base.x + self.base.w * 0.55;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+        let split_dec = x + w * 0.55;
         
         let in_y = py >= btn_y && py < btn_y + btn_h;
-        let hd = in_y && px >= split_dec + p && px < self.base.x + self.base.w * 0.775;
-        let hi = in_y && px >= self.base.x + self.base.w * 0.775 && px < self.base.x + self.base.w - p;
+        let hd = in_y && px >= split_dec + p && px < x + w * 0.775;
+        let hi = in_y && px >= x + w * 0.775 && px < x + w - p;
         let changed = hd != self.hover_dec || hi != self.hover_inc;
         self.hover_dec = hd;
         self.hover_inc = hi;
@@ -187,17 +190,20 @@ impl Element for Spinbox {
                 let p = crate::layout::spinbox_button_padding();
                 let btn_y = self.base.y + top + p;
                 let btn_h = (visual_h - 2.0 * p).max(0.0);
-                let split_dec = self.base.x + self.base.w * 0.55;
+                let label_x = self.label_x_offset();
+                let x = self.base.x + label_x;
+                let w = self.base.w - label_x;
+                let split_dec = x + w * 0.55;
                 
                 let in_y = py >= btn_y && py < btn_y + btn_h;
-                if in_y && px >= split_dec + p && px < self.base.x + self.base.w * 0.775 {
+                if in_y && px >= split_dec + p && px < x + w * 0.775 {
                     let old_val = self.value;
                     self.value = (self.value - self.step).max(self.min);
                     if self.value != old_val {
                         self.just_changed = true;
                     }
                     true
-                } else if in_y && px >= self.base.x + self.base.w * 0.775 && px < self.base.x + self.base.w - p {
+                } else if in_y && px >= x + w * 0.775 && px < x + w - p {
                     let old_val = self.value;
                     self.value = (self.value + self.step).min(self.max);
                     if self.value != old_val {
@@ -213,7 +219,7 @@ impl Element for Spinbox {
                         self.edit_buffer = self.value.to_string();
                     }
                     let char_width = 8.4;
-                    let click_idx = (((px - (self.base.x + 4.0)) / char_width).round() as isize)
+                    let click_idx = (((px - (x + 4.0)) / char_width).round() as isize)
                         .max(0)
                         .min(self.edit_buffer.chars().count() as isize) as usize;
                     self.cursor_idx = click_idx;
@@ -350,10 +356,13 @@ impl Element for Spinbox {
 
         let top = self.base.label_offset();
         let visual_h = self.base.h - top;
-        let display_w = self.base.w * 0.55;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+        let display_w = w * 0.55;
 
         let p = crate::layout::spinbox_button_padding();
-        let split_dec = self.base.x + display_w;
+        let split_dec = x + display_w;
         let inc_col = if self.hover_inc { colors::spinbox_button_hover() } else { colors::spinbox_button() };
         let dec_col = if self.hover_dec { colors::spinbox_button_hover() } else { colors::spinbox_button() };
         
@@ -363,11 +372,11 @@ impl Element for Spinbox {
             colors::spinbox_display()
         };
         
-        quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, display_bg));
+        quads.push((x, self.base.y + top, w, visual_h, display_bg));
         
         let btn_y = self.base.y + top + p;
         let btn_h = (visual_h - 2.0 * p).max(0.0);
-        let pair_w = (self.base.w * 0.45 - 2.0 * p).max(0.0);
+        let pair_w = (w * 0.45 - 2.0 * p).max(0.0);
         let btn_w_padded = pair_w / 2.0;
         
         if btn_h > 0.0 && btn_w_padded > 0.0 {
@@ -377,14 +386,14 @@ impl Element for Spinbox {
         
         if self.editing {
             let border_color = [0.20, 0.50, 0.85, 1.0];
-            quads.push((self.base.x, self.base.y + top, self.base.w, 1.0, border_color));
-            quads.push((self.base.x, self.base.y + top + visual_h - 1.0, self.base.w, 1.0, border_color));
-            quads.push((self.base.x, self.base.y + top, 1.0, visual_h, border_color));
-            quads.push((self.base.x + self.base.w - 1.0, self.base.y + top, 1.0, visual_h, border_color));
+            quads.push((x, self.base.y + top, w, 1.0, border_color));
+            quads.push((x, self.base.y + top + visual_h - 1.0, w, 1.0, border_color));
+            quads.push((x, self.base.y + top, 1.0, visual_h, border_color));
+            quads.push((x + w - 1.0, self.base.y + top, 1.0, visual_h, border_color));
 
             let char_width = 8.4;
-            let cursor_x = self.base.x + 4.0 + (self.cursor_idx as f32 * char_width);
-            let max_cursor_x = self.base.x + display_w - 4.0;
+            let cursor_x = x + 4.0 + (self.cursor_idx as f32 * char_width);
+            let max_cursor_x = x + display_w - 4.0;
             let final_cursor_x = cursor_x.min(max_cursor_x);
             let cursor_y = self.base.y + top + (visual_h - 14.0) / 2.0;
             quads.push((final_cursor_x, cursor_y, 1.5, 14.0, [0.80, 0.80, 0.85, 1.0]));
@@ -411,7 +420,7 @@ impl Element for Spinbox {
             colors::spinbox_display()
         };
 
-        let display_w = self.base.w * 0.55;
+
         let border_color = if self.editing {
             [0.20, 0.50, 0.85, 1.0]
         } else if self.base.hovered {
@@ -420,17 +429,22 @@ impl Element for Spinbox {
             [0.18, 0.18, 0.24, 1.0]
         };
 
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+        let display_w = w * 0.55;
+
         // Draw display border (outer) and background (inner)
-        quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, radius, border_color, (r1, r2, r3, r4)));
-        quads.push((self.base.x + 1.0, self.base.y + top + 1.0, self.base.w - 2.0, visual_h - 2.0, radius - 1.0, display_bg, (r1, r2, r3, r4)));
+        quads.push((x, self.base.y + top, w, visual_h, radius, border_color, (r1, r2, r3, r4)));
+        quads.push((x + 1.0, self.base.y + top + 1.0, w - 2.0, visual_h - 2.0, radius - 1.0, display_bg, (r1, r2, r3, r4)));
 
         // Increment/decrement buttons
         let p = crate::layout::spinbox_button_padding();
         let btn_y = self.base.y + top + p;
         let btn_h = (visual_h - 2.0 * p).max(0.0);
-        let pair_w = (self.base.w * 0.45 - 2.0 * p).max(0.0);
+        let pair_w = (w * 0.45 - 2.0 * p).max(0.0);
         let btn_w_padded = pair_w / 2.0;
-        let split_dec = self.base.x + display_w;
+        let split_dec = x + display_w;
         let inc_col = if self.hover_inc { colors::spinbox_button_hover() } else { colors::spinbox_button() };
         let dec_col = if self.hover_dec { colors::spinbox_button_hover() } else { colors::spinbox_button() };
 
@@ -444,8 +458,8 @@ impl Element for Spinbox {
         // Draw cursor if editing and rounded
         if self.editing {
             let char_width = 8.4;
-            let cursor_x = self.base.x + 4.0 + (self.cursor_idx as f32 * char_width);
-            let max_cursor_x = self.base.x + display_w - 4.0;
+            let cursor_x = x + 4.0 + (self.cursor_idx as f32 * char_width);
+            let max_cursor_x = x + display_w - 4.0;
             let final_cursor_x = cursor_x.min(max_cursor_x);
             let cursor_y = self.base.y + top + (visual_h - 14.0) / 2.0;
             quads.push((final_cursor_x, cursor_y, 1.5, 14.0, 0.0, [0.80, 0.80, 0.85, 1.0], (false, false, false, false)));
@@ -469,14 +483,16 @@ impl Element for Spinbox {
         };
         
         let top = self.base.label_offset();
-        let _visual_h = self.base.h - top;
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
         
         let tc = colors::spinbox_text_color();
         let text_color_u8 = [(tc[0]*255.0) as u8, (tc[1]*255.0) as u8, (tc[2]*255.0) as u8];
 
         labels.push(TextLabel {
             text: value_text,
-            x: self.base.x + 4.0,
+            x: x + 4.0,
             y: crate::layout::align_text_y(self.base.y, self.base.h, 14.0, top),
             font_size: 14.0,
             color: text_color_u8,
@@ -484,7 +500,7 @@ impl Element for Spinbox {
         if let Some(ref unit) = self.unit {
             labels.push(TextLabel {
                 text: unit.clone(),
-                x: self.base.x + 4.0 + 36.0,
+                x: x + 4.0 + 36.0,
                 y: crate::layout::align_text_y(self.base.y, self.base.h, 11.0, top),
                 font_size: 11.0,
                 color: [0x73, 0x73, 0x7a],
@@ -492,8 +508,8 @@ impl Element for Spinbox {
         }
 
         let p = crate::layout::spinbox_button_padding();
-        let split_dec = self.base.x + self.base.w * 0.55;
-        let pair_w = (self.base.w * 0.45 - 2.0 * p).max(0.0);
+        let split_dec = x + w * 0.55;
+        let pair_w = (w * 0.45 - 2.0 * p).max(0.0);
         let btn_w_padded = pair_w / 2.0;
 
         if btn_w_padded > 0.0 {
diff --git a/src/widget/input/text_box.rs b/src/widget/input/text_box.rs
index ec630b2..4c32a8b 100644
--- a/src/widget/input/text_box.rs
+++ b/src/widget/input/text_box.rs
@@ -50,7 +50,7 @@ pub struct TextBox {
 
 impl TextBox {
     pub fn new(text: String) -> Self {
-        let (style_family, style_size) = crate::layout::textbox_font_parsed();
+        let (style_family, style_size) = crate::layout::control_label_font_detached_parsed();
         let editor_state = TextEditorState::new(text.clone());
         Self {
             base: Widget::new(),
@@ -99,7 +99,8 @@ impl TextBox {
     }
 
     fn map_x_to_idx(&self, click_x: f32) -> usize {
-        let relative_x = click_x - (self.base.x + 8.0) + self.scroll_x;
+        let label_x = self.label_x_offset();
+        let relative_x = click_x - (self.base.x + label_x + 8.0) + self.scroll_x;
         if self.glyph_positions.is_empty() {
             let char_width = self.char_width();
             return ((relative_x / char_width).round() as isize)
@@ -497,7 +498,7 @@ impl Element for TextBox {
     crate::impl_widget_base!(TextBox);
 
     fn prepare_text(&mut self, fs: &mut glyphon::FontSystem) {
-        let (style_family, style_size) = crate::layout::textbox_font_parsed();
+        let (style_family, style_size) = crate::layout::control_label_font_detached_parsed();
         if self.font_size == self.default_font_size {
             self.font_size = style_size;
         }
@@ -721,7 +722,7 @@ impl Element for TextBox {
 
     fn draggable(&self) -> bool { !self.disabled }
     fn is_dragging(&self) -> bool { self.dragging }
-    fn widget_font(&self) -> Option<String> { Some(crate::layout::textbox_font()) }
+    fn widget_font(&self) -> Option<String> { Some(crate::layout::control_label_font_detached()) }
 
     fn drag_begin(&mut self, _px: f32, _py: f32) {
         if self.disabled || !self.editing { return; }
@@ -784,16 +785,17 @@ impl Element for TextBox {
                 } else {
                     let char_width = self.char_width();
                     let top = self.base.label_offset();
+                    let label_x = self.label_x_offset();
                     let idx = if self.multiline {
                         let line_height = self.line_height();
                         let max_chars = if self.line_wrap_enabled() {
-                            (((self.base.w - 16.0) / char_width).floor() as usize).max(1)
+                            ((((self.base.w - label_x) - 16.0) / char_width).floor() as usize).max(1)
                         } else {
                             999999
                         };
                         let (lines, index_map) = self.wrap_text(max_chars);
                         let click_line = (((py - (self.base.y + top + 8.0) + self.scroll_y) / line_height).floor() as isize).max(0) as usize;
-                        let click_col = (((px - (self.base.x + 8.0) + self.scroll_x) / char_width).round() as isize).max(0) as usize;
+                        let click_col = (((px - (self.base.x + label_x + 8.0) + self.scroll_x) / char_width).round() as isize).max(0) as usize;
                         self.map_2d_to_1d(&index_map, click_line, click_col, lines.len() - 1)
                     } else {
                         self.map_x_to_idx(px)
@@ -1178,10 +1180,14 @@ impl Element for TextBox {
             [0.18, 0.18, 0.24, 1.0]
         };
         
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+
         if self.draw_bg_border {
             let border_w = self.border_width();
-            quads.push((self.base.x, self.base.y + top, self.base.w, visual_h, radius, border_color, (r1, r2, r3, r4)));
-            quads.push((self.base.x + border_w, self.base.y + top + border_w, self.base.w - 2.0 * border_w, visual_h - 2.0 * border_w, (radius - border_w).max(0.0), bg_color, (r1, r2, r3, r4)));
+            quads.push((x, self.base.y + top, w, visual_h, radius, border_color, (r1, r2, r3, r4)));
+            quads.push((x + border_w, self.base.y + top + border_w, w - 2.0 * border_w, visual_h - 2.0 * border_w, (radius - border_w).max(0.0), bg_color, (r1, r2, r3, r4)));
         }
 
         if self.editing || self.select_anchor.is_some() {
@@ -1200,7 +1206,7 @@ impl Element for TextBox {
 
             if self.multiline {
                 let max_chars = if self.line_wrap_enabled() {
-                    (((self.base.w - 16.0) / char_width).floor() as usize).max(1)
+                    (((w - 16.0) / char_width).floor() as usize).max(1)
                 } else {
                     999999
                 };
@@ -1230,13 +1236,13 @@ impl Element for TextBox {
                             }
                         }
                         if let (Some(sc), Some(ec)) = (line_start_col, line_end_col) {
-                            let highlight_x = self.base.x + 8.0 + (sc as f32 * char_width) - self.scroll_x;
+                            let highlight_x = x + 8.0 + (sc as f32 * char_width) - self.scroll_x;
                             let highlight_w = (ec - sc + 1) as f32 * char_width;
                             let highlight_y = self.base.y + top + 8.0 + (line_idx as f32 * line_height) - self.scroll_y;
                             let clipped_y = highlight_y.max(view_top);
                             let clipped_bottom = (highlight_y + line_height).min(view_bottom);
-                            let h_left = highlight_x.max(self.base.x + 8.0);
-                            let h_right = (highlight_x + highlight_w).min(self.base.x + self.base.w - 8.0);
+                            let h_left = highlight_x.max(x + 8.0);
+                            let h_right = (highlight_x + highlight_w).min(x + w - 8.0);
                             if h_left < h_right && clipped_y < clipped_bottom {
                                 quads.push((h_left, clipped_y, h_right - h_left, clipped_bottom - clipped_y, 0.0, highlight_color, (false, false, false, false)));
                             }
@@ -1247,11 +1253,11 @@ impl Element for TextBox {
                 if self.editing {
                     let caret_h = self.font_size * 1.15;
                     let (cursor_l, cursor_c) = index_map[self.cursor_idx.min(index_map.len() - 1)];
-                    let cursor_x = self.base.x + 8.0 + (cursor_c as f32 * char_width) - self.scroll_x;
+                    let cursor_x = x + 8.0 + (cursor_c as f32 * char_width) - self.scroll_x;
                     let cursor_y = self.base.y + top + 8.0 + (cursor_l as f32 * line_height) + (line_height - caret_h) / 2.0 - self.scroll_y;
                     let clipped_y = cursor_y.max(view_top);
                     let clipped_bottom = (cursor_y + caret_h).min(view_bottom);
-                    if cursor_x >= self.base.x + 8.0 && cursor_x <= self.base.x + self.base.w - 8.0 {
+                    if cursor_x >= x + 8.0 && cursor_x <= x + w - 8.0 {
                         if clipped_y < clipped_bottom {
                             quads.push((cursor_x, clipped_y, 1.5, clipped_bottom - clipped_y, 0.0, cursor_color, (false, false, false, false)));
                         }
@@ -1262,9 +1268,9 @@ impl Element for TextBox {
                 if start != end {
                     let h_left_offset = self.glyph_positions.get(start).copied().unwrap_or_else(|| start as f32 * char_width);
                     let h_right_offset = self.glyph_positions.get(end).copied().unwrap_or_else(|| end as f32 * char_width);
-                    let highlight_x = self.base.x + 8.0 + h_left_offset - self.scroll_x;
-                    let h_left = highlight_x.max(self.base.x + 8.0);
-                    let h_right = (self.base.x + 8.0 + h_right_offset - self.scroll_x).min(self.base.x + self.base.w - 8.0);
+                    let highlight_x = x + 8.0 + h_left_offset - self.scroll_x;
+                    let h_left = highlight_x.max(x + 8.0);
+                    let h_right = (x + 8.0 + h_right_offset - self.scroll_x).min(x + w - 8.0);
                     if h_left < h_right {
                         quads.push((
                             h_left,
@@ -1284,8 +1290,8 @@ impl Element for TextBox {
                     } else {
                         self.cursor_x_offset
                     };
-                    let cursor_x = self.base.x + 8.0 + offset - self.scroll_x;
-                    if cursor_x >= self.base.x + 8.0 && cursor_x <= self.base.x + self.base.w - 8.0 {
+                    let cursor_x = x + 8.0 + offset - self.scroll_x;
+                    if cursor_x >= x + 8.0 && cursor_x <= x + w - 8.0 {
                         let text_y = crate::layout::align_text_y(self.base.y, self.base.h, self.font_size, top);
                         let cursor_y = text_y + (self.font_size - caret_h) / 2.0;
                         quads.push((cursor_x, cursor_y, 1.5, caret_h, 0.0, cursor_color, (false, false, false, false)));
@@ -1338,11 +1344,15 @@ impl Element for TextBox {
             [0xcc, 0xcc, 0xd4]
         };
 
+        let label_x = self.label_x_offset();
+        let x = self.base.x + label_x;
+        let w = self.base.w - label_x;
+
         if self.multiline {
             let char_width = self.char_width();
             let line_height = self.line_height();
             let max_chars = if self.line_wrap_enabled() {
-                (((self.base.w - 16.0) / char_width).floor() as usize).max(1)
+                (((w - 16.0) / char_width).floor() as usize).max(1)
             } else {
                 999999
             };
@@ -1372,7 +1382,7 @@ impl Element for TextBox {
             for (line_idx, line_text) in lines_to_draw.iter().enumerate() {
                 labels.push(TextLabel {
                     text: line_text.clone(),
-                    x: self.base.x + 8.0 - self.scroll_x,
+                    x: x + 8.0 - self.scroll_x,
                     y: self.base.y + top + 8.0 + (line_idx as f32 * line_height) + (line_height - self.font_size) / 2.0 - self.scroll_y,
                     font_size: self.font_size,
                     color: label_color,
@@ -1381,7 +1391,7 @@ impl Element for TextBox {
         } else {
             labels.push(TextLabel {
                 text: display_text,
-                x: self.base.x + 8.0 - self.scroll_x,
+                x: x + 8.0 - self.scroll_x,
                 y: crate::layout::align_text_y(self.base.y, self.base.h, self.font_size, top),
                 font_size: self.font_size,
                 color: label_color,
@@ -1391,13 +1401,15 @@ impl Element for TextBox {
     }
 
     fn text_labels_with_bounds(&self, _ctx: &UiContext) -> Vec<(TextLabel, Option<[f32; 4]>)> {
-        let bounds = Some([self.base.x, self.base.y, self.base.x + self.base.w, self.base.y + self.base.h]);
+        let label_x = self.label_x_offset();
+        let bounds = Some([self.base.x + label_x, self.base.y, self.base.x + self.base.w, self.base.y + self.base.h]);
         self.text_labels().into_iter().map(|l| (l, bounds)).collect()
     }
 
     fn text_labels_with_font_and_bounds(&self, _ctx: &UiContext) -> Vec<(TextLabel, Option<String>, Option<[f32; 4]>)> {
         let font = self.widget_font();
-        let bounds = Some([self.base.x, self.base.y, self.base.x + self.base.w, self.base.y + self.base.h]);
+        let label_x = self.label_x_offset();
+        let bounds = Some([self.base.x + label_x, self.base.y, self.base.x + self.base.w, self.base.y + self.base.h]);
         self.text_labels().into_iter().map(|l| (l, font.clone(), bounds)).collect()
     }
 
diff --git a/src/widget/input/trackpad.rs b/src/widget/input/trackpad.rs
index dcf8c74..33a5fcc 100644
--- a/src/widget/input/trackpad.rs
+++ b/src/widget/input/trackpad.rs
@@ -31,8 +31,12 @@ impl Trackpad {
     }
 
     pub fn label_offset(&self) -> f32 {
+        if crate::layout::control_label_layout() == "side" {
+            return 0.0;
+        }
         if self.base.label.is_some() {
-            12.0 + crate::layout::label_margin()
+            let (_, font_size) = crate::layout::control_label_font_detached_parsed();
+            font_size + crate::layout::control_label_margin()
         } else {
             0.0
         }
@@ -42,30 +46,42 @@ impl Trackpad {
 impl Element for Trackpad {
     crate::impl_widget_base!(Trackpad);
 
+    fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) {
+        self.base.x = x;
+        self.base.y = y;
+        self.base.w = w;
+        self.base.h = h + self.label_offset();
+    }
+
     fn color(&self) -> [f32; 4] {
         [0.11, 0.11, 0.16, 0.85]
     }
 
     fn extra_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
-        let (x, y, w, h) = self.rect();
+        let (rx_rect, y, rw_rect, h) = self.rect();
+        let label_x = self.label_x_offset();
+        let x = rx_rect + label_x;
+        let w = rw_rect - label_x;
+        let top = self.label_offset();
+        let visual_h = h - top;
         let mut quads = Vec::new();
 
         // 1. Background
-        quads.push((x, y, w, h, [0.11, 0.11, 0.16, 0.85]));
+        quads.push((x, y + top, w, visual_h, [0.11, 0.11, 0.16, 0.85]));
 
         // 2. Borders
         let border_color = [0.28, 0.28, 0.38, 1.0];
-        quads.push((x, y, w, 1.0, border_color));             // Top
-        quads.push((x, y + h - 1.0, w, 1.0, border_color));     // Bottom
-        quads.push((x, y, 1.0, h, border_color));             // Left
-        quads.push((x + w - 1.0, y, 1.0, h, border_color));     // Right
+        quads.push((x, y + top, w, 1.0, border_color));             // Top
+        quads.push((x, y + top + visual_h - 1.0, w, 1.0, border_color));     // Bottom
+        quads.push((x, y + top, 1.0, visual_h, border_color));             // Left
+        quads.push((x + w - 1.0, y + top, 1.0, visual_h, border_color));     // Right
 
         // 3. Fingers
         for finger in &self.fingers {
             let rx = finger.x.clamp(0.0, 1.0);
             let ry = finger.y.clamp(0.0, 1.0);
             let fx = x + rx * w;
-            let fy = y + ry * h;
+            let fy = y + top + ry * visual_h;
             let dot_size = 12.0;
 
             // Render glow (outer light blue rectangle)
@@ -90,26 +106,32 @@ impl Element for Trackpad {
     }
 
     fn text_labels(&self) -> Vec<TextLabel> {
-        let (x, y, _w, h) = self.rect();
+        let (rx_rect, y, rw_rect, h) = self.rect();
+        let label_x = self.label_x_offset();
+        let x = rx_rect + label_x;
+        let _w = rw_rect - label_x;
+        let top = self.label_offset();
+        let visual_h = h - top;
         let mut labels = Vec::new();
 
         // Render "Touchpad Area" label
         labels.push(TextLabel {
             text: "Touchpad Area".to_string(),
             x: x + 12.0,
-            y: y + h - 22.0,
+            y: y + top + visual_h - 22.0,
             font_size: 11.0,
             color: [0x73, 0x73, 0x8c],
         });
 
         // Optional widget-base label on top
         if let Some(ref label) = self.base.label {
+            let (_, font_size) = crate::layout::control_label_font_detached_parsed();
             labels.push(TextLabel {
                 text: label.clone(),
-                x,
-                y: y - (12.0 + crate::layout::label_margin()),
-                font_size: 12.0,
-                color: [0x83, 0x83, 0x8a],
+                x: rx_rect,
+                y,
+                font_size,
+                color: colors::control_label_color_detached_for_state(self.base.hovered, self.base.focused),
             });
         }
 
@@ -120,19 +142,29 @@ impl Element for Trackpad {
     fn is_dragging(&self) -> bool { !self.fingers.is_empty() }
 
     fn drag_begin(&mut self, px: f32, py: f32) {
-        let (x, y, w, h) = self.rect();
-        if w > 0.0 && h > 0.0 {
+        let (rx_rect, y, rw_rect, h) = self.rect();
+        let label_x = self.label_x_offset();
+        let x = rx_rect + label_x;
+        let w = rw_rect - label_x;
+        let top = self.label_offset();
+        let visual_h = h - top;
+        if w > 0.0 && visual_h > 0.0 {
             let rx = ((px - x) / w).clamp(0.0, 1.0);
-            let ry = ((py - y) / h).clamp(0.0, 1.0);
+            let ry = ((py - (y + top)) / visual_h).clamp(0.0, 1.0);
             self.fingers = vec![Finger { slot: 0, x: rx, y: ry }];
         }
     }
 
     fn drag_update(&mut self, px: f32, py: f32) -> bool {
-        let (x, y, w, h) = self.rect();
-        if w > 0.0 && h > 0.0 {
+        let (rx_rect, y, rw_rect, h) = self.rect();
+        let label_x = self.label_x_offset();
+        let x = rx_rect + label_x;
+        let w = rw_rect - label_x;
+        let top = self.label_offset();
+        let visual_h = h - top;
+        if w > 0.0 && visual_h > 0.0 {
             let rx = ((px - x) / w).clamp(0.0, 1.0);
-            let ry = ((py - y) / h).clamp(0.0, 1.0);
+            let ry = ((py - (y + top)) / visual_h).clamp(0.0, 1.0);
             self.fingers = vec![Finger { slot: 0, x: rx, y: ry }];
             true
         } else {
@@ -146,11 +178,16 @@ impl Element for Trackpad {
 
     fn mouse_input(&mut self, button: MouseButton, state: ElementState, px: f32, py: f32, _ctx: &mut UiContext) -> bool {
         if button == MouseButton::Left {
-            let (x, y, w, h) = self.rect();
-            if px >= x && px <= x + w && py >= y && py <= y + h {
+            let (rx_rect, y, rw_rect, h) = self.rect();
+            let label_x = self.label_x_offset();
+            let x = rx_rect + label_x;
+            let w = rw_rect - label_x;
+            let top = self.label_offset();
+            let visual_h = h - top;
+            if px >= x && px <= x + w && py >= y + top && py <= y + top + visual_h {
                 if state == ElementState::Pressed {
                     let rx = ((px - x) / w).clamp(0.0, 1.0);
-                    let ry = ((py - y) / h).clamp(0.0, 1.0);
+                    let ry = ((py - (y + top)) / visual_h).clamp(0.0, 1.0);
                     self.fingers = vec![Finger { slot: 0, x: rx, y: ry }];
                     return true;
                 } else {
diff --git a/src/widget/mod.rs b/src/widget/mod.rs
index 92c73d5..2011bad 100644
--- a/src/widget/mod.rs
+++ b/src/widget/mod.rs
@@ -332,7 +332,7 @@ pub trait Element {
         if w <= 0.0 || h <= 0.0 {
             return false;
         }
-        let (hx, hw) = if let Some(b) = self.base() {
+        let (mut hx, mut hw) = if let Some(b) = self.base() {
             if b.row_w > 0.0 {
                 (b.row_x, b.row_w)
             } else {
@@ -341,6 +341,9 @@ pub trait Element {
         } else {
             (x, w)
         };
+        let label_x = self.label_x_offset();
+        hx += label_x;
+        hw -= label_x;
         px >= hx && px <= hx + hw && py >= y && py <= y + h
     }
 
@@ -409,13 +412,14 @@ pub trait Element {
 
     fn highlight_quad(&self, ctx: &UiContext) -> Option<(f32, f32, f32, f32, [f32; 4])> {
         let hc = self.highlight_color(ctx)?;
+        let label_x = self.label_x_offset();
         if let Some(b) = self.base() {
-            let hx = if b.row_w > 0.0 { b.row_x } else { b.x };
-            let hw = if b.row_w > 0.0 { b.row_w } else { b.w };
+            let hx = if b.row_w > 0.0 { b.row_x } else { b.x } + label_x;
+            let hw = if b.row_w > 0.0 { b.row_w } else { b.w } - label_x;
             Some((hx, b.y, hw, b.h, hc))
         } else {
             let (x, y, w, h) = self.rect();
-            Some((x, y, w, h, hc))
+            Some((x + label_x, y, w - label_x, h, hc))
         }
     }
 
@@ -430,6 +434,18 @@ pub trait Element {
     fn take_click(&mut self) -> bool { false }
     fn draggable(&self) -> bool { false }
 
+    fn label_x_offset(&self) -> f32 {
+        let name = self.type_name();
+        if name == "Label" || name == "Button" || name == "Checkbox" || name == "Toggle" || name == "Plate" || name == "Ramp" {
+            return 0.0;
+        }
+        if crate::layout::control_label_layout() == "side" && self.base().map_or(false, |b| b.label.is_some()) {
+            90.0
+        } else {
+            0.0
+        }
+    }
+
     fn extra_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> { Vec::new() }
     fn extra_arcs(&self) -> Vec<(f32, f32, f32, f32, f32, f32, [f32; 4])> { Vec::new() }
     fn extra_circles(&self) -> Vec<(f32, f32, f32, [f32; 4])> { Vec::new() }
@@ -476,12 +492,27 @@ pub trait Element {
     fn text_labels(&self) -> Vec<TextLabel> {
         if let Some(b) = self.base() {
             if let Some(ref label) = b.label {
+                let (_, font_size) = crate::layout::control_label_font_detached_parsed();
+                let color = colors::control_label_color_detached_for_state(b.hovered, b.focused);
+                if crate::layout::control_label_layout() == "side" {
+                    let label_x = self.label_x_offset();
+                    if label_x > 0.0 {
+                        let y_pos = crate::layout::align_text_y(b.y, b.h, font_size, 0.0);
+                        return vec![TextLabel {
+                            text: label.clone(),
+                            x: b.x + 4.0,
+                            y: y_pos,
+                            font_size,
+                            color,
+                        }];
+                    }
+                }
                 return vec![TextLabel {
                     text: label.clone(),
                     x: b.x,
                     y: b.y,
-                    font_size: 12.0,
-                    color: [0x83, 0x83, 0x8a],
+                    font_size,
+                    color,
                 }];
             }
         }
@@ -649,19 +680,31 @@ pub trait Control: Element {
         let label = b.label.as_ref()?;
         let name = self.type_name();
         
-        let x_offset = if name == "Slider" || name == "RangeSlider" {
-            0.0
+        let (_, font_size) = crate::layout::control_label_font_detached_parsed();
+        let color = colors::control_label_color_detached_for_state(b.hovered, b.focused);
+        if crate::layout::control_label_layout() == "side" {
+            let y_pos = crate::layout::align_text_y(b.y, b.h, font_size, 0.0);
+            Some(TextLabel {
+                text: label.clone(),
+                x: b.x + 4.0,
+                y: y_pos,
+                font_size,
+                color,
+            })
         } else {
-            4.0
-        };
-        
-        Some(TextLabel {
-            text: label.clone(),
-            x: b.x + x_offset,
-            y: b.y,
-            font_size: 12.0,
-            color: [0x83, 0x83, 0x8a],
-        })
+            let x_offset = if name == "Slider" || name == "RangeSlider" {
+                0.0
+            } else {
+                4.0
+            };
+            Some(TextLabel {
+                text: label.clone(),
+                x: b.x + x_offset,
+                y: b.y,
+                font_size,
+                color,
+            })
+        }
     }
 }
 
@@ -684,7 +727,7 @@ pub use self::input::{
     KeybindsControl, KeybindRow, KeybindRecorder, Ramp, RampKey, ColorRamp, ColorRampKey
 };
 pub use self::container::{
-    Container, ContainerLayout, OverlayLayout, VerticalLayout, GridLayout, AdaptiveGridLayout,
+    Container, ContainerLayout, OverlayLayout, ManualLayout, VerticalLayout, GridLayout, AdaptiveGridLayout,
     ColumnsLayout, MosaicLayout, ReverseMosaicLayout,
     SectionContainer, Header, ContentBg, ViewportBg, ParametersBg, List,
     ScrollBox, Menu, MenuBar, Spreadsheet, Breadcrumb, Plate,