git.lucas.co / cce-layout-interface
page layout tool
git clone https://git.lucas.co/cce-layout-interface.git

commit911aa87b096a590e13ca0955f67647dbcc64bc5b
parentdcde33baff
authorLucas Galante <[email protected]>
date2026-06-05 20:13
feat: introduce PageContent rendering structure and typography alignment types

 Cargo.toml  |    1 +
 Makefile    |   14 +
 src/main.rs | 2460 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
 3 files changed, 2014 insertions(+), 461 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 95e1c19..424130b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,3 +18,4 @@ glyphon = "0.8"
 tokio = { version = "1", features = ["full"] }
 serde = { version = "1", features = ["derive"] }
 serde_json = "1"
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ef7437c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+.PHONY: build install run clean
+
+build:
+	cargo build --release
+
+install: build
+	mkdir -p ~/.local/bin
+	install -m 755 target/release/clear-layout-interface ~/.local/bin/clear-layout-interface
+
+run:
+	cargo run
+
+clean:
+	cargo clean
diff --git a/src/main.rs b/src/main.rs
index caad333..d38508c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,29 +1,138 @@
 use wayland_client::QueueHandle;
 use glyphon::{FontSystem, Buffer, Metrics, Attrs};
-use clear_ui::engine::{Application, EngineState, LogicalPosition, LogicalSize, WindowSettings};
+use serde::{Serialize, Deserialize};
+use clear_ui::engine::{Application, EngineState, LogicalPosition, LogicalSize, WindowSettings, LineCap};
 use clear_ui::widget::{
     MouseButton, ElementState, MouseScrollDelta, KeyEvent, TextItem, Widget,
-    MenuBar, TextBox, Slider, TextLabel, Paginator, Button, Dropdown, Toggle, ColorSelector,
-    Label, SectionHeader, Spinbox
+    TextBox, Slider, TextLabel, Paginator, Button, Dropdown, Toggle, ColorSelector,
+    Label, Spinbox, Key, NamedKey, ScrollingList, FontSelector
 };
+use clear_ui::layout::{RenderTarget, render_widget, Section, UiFrame};
+
+pub struct PageContent {
+    pub rects: Vec<([f32; 4], f32, f32, f32, f32)>,
+    pub texts: Vec<(String, f32, f32, f32, [f32; 4], Option<String>, Option<[f32; 4]>)>,
+}
+
+impl PageContent {
+    pub fn new() -> Self {
+        Self {
+            rects: Vec::new(),
+            texts: Vec::new(),
+        }
+    }
+}
+
+impl RenderTarget for PageContent {
+    fn rect(&mut self, color: [f32; 4], x: f32, y: f32, w: f32, h: f32) {
+        self.rects.push((color, x, y, w, h));
+    }
+
+    fn text(&mut self, content: &str, x: f32, y: f32, size: f32, color: [f32; 4]) {
+        self.texts.push((content.to_string(), size, x, y, color, None, None));
+    }
+
+    fn text_with_font(&mut self, content: &str, x: f32, y: f32, size: f32, color: [f32; 4], font: &str) {
+        self.texts.push((content.to_string(), size, x, y, color, Some(font.to_string()), None));
+    }
+
+    fn text_with_bounds(&mut self, content: &str, x: f32, y: f32, size: f32, color: [f32; 4], bounds: Option<[f32; 4]>) {
+        self.texts.push((content.to_string(), size, x, y, color, None, bounds));
+    }
+
+    fn text_with_font_and_bounds(&mut self, content: &str, x: f32, y: f32, size: f32, color: [f32; 4], font: &str, bounds: Option<[f32; 4]>) {
+        self.texts.push((content.to_string(), size, x, y, color, Some(font.to_string()), bounds));
+    }
+}
+
+fn make_text_buffer_with_font(
+    fs: &mut FontSystem,
+    text: &str,
+    size: f32,
+    font: Option<&str>,
+) -> Buffer {
+    let metrics = Metrics::new(size, size * 1.4);
+    let mut buf = Buffer::new(fs, metrics);
+    let mut attrs = Attrs::new();
+    if let Some(font_name) = font {
+        let family = match font_name {
+            "monospace" => glyphon::Family::Monospace,
+            "sans-serif" => glyphon::Family::SansSerif,
+            "serif" => glyphon::Family::Serif,
+            _ => glyphon::Family::Name(font_name),
+        };
+        attrs = attrs.family(family);
+    }
+    buf.set_text(fs, text, attrs, glyphon::Shaping::Advanced);
+    buf.shape_until_scroll(fs, true);
+    buf
+}
+
+
+#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
+pub enum TextAlignH {
+    Left,
+    Center,
+    Right,
+}
+
+impl Default for TextAlignH {
+    fn default() -> Self {
+        TextAlignH::Left
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
+pub enum TextAlignV {
+    Top,
+    Middle,
+    Bottom,
+}
+
+impl Default for TextAlignV {
+    fn default() -> Self {
+        TextAlignV::Top
+    }
+}
+
+fn point_to_line_segment_distance(px: f32, py: f32, x1: f32, y1: f32, x2: f32, y2: f32) -> f32 {
+    let dx = x2 - x1;
+    let dy = y2 - y1;
+    let len_sq = dx * dx + dy * dy;
+    if len_sq < 0.001 {
+        let dx_p = px - x1;
+        let dy_p = py - y1;
+        return (dx_p * dx_p + dy_p * dy_p).sqrt();
+    }
+    let t = (((px - x1) * dx + (py - y1) * dy) / len_sq).clamp(0.0, 1.0);
+    let proj_x = x1 + t * dx;
+    let proj_y = y1 + t * dy;
+    let dx_p = px - proj_x;
+    let dy_p = py - proj_y;
+    (dx_p * dx_p + dy_p * dy_p).sqrt()
+}
 
 #[derive(Debug, Clone)]
 enum AppMessage {
     Exit,
     NewDocument,
+    Open,
+    Save,
+    SaveAs,
     AddText,
     AddRectangle,
     AddBanner,
-    ToggleGrid,
+    AddVector,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
 enum ShapeType {
     Rectangle,
     Banner,
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+#[serde(tag = "type")]
 enum Element {
     Text {
         text: String,
@@ -34,6 +143,12 @@ enum Element {
         font_size: f32,
         color: [f32; 4],
         font_family: String,
+        #[serde(default, rename = "align")]
+        align_h: TextAlignH,
+        #[serde(default)]
+        align_v: TextAlignV,
+        #[serde(default = "default_multiline")]
+        multiline: bool,
     },
     Shape {
         shape_type: ShapeType,
@@ -43,6 +158,91 @@ enum Element {
         h: f32,
         color: [f32; 4],
     },
+    Vector {
+        x1: f32,
+        y1: f32,
+        x2: f32,
+        y2: f32,
+        stroke_width: f32,
+        color: [f32; 4],
+        #[serde(default = "default_line_cap")]
+        line_cap: LineCap,
+    },
+}
+
+fn default_line_cap() -> LineCap {
+    LineCap::Arrow
+}
+
+fn default_grid_color() -> [f32; 4] {
+    [0.20, 0.35, 0.60, 0.8]
+}
+
+fn default_grid_size() -> f32 {
+    1.5
+}
+
+fn default_multiline() -> bool {
+    true
+}
+
+fn default_margin_color() -> [f32; 4] {
+    [0.20, 0.50, 0.85, 0.35]
+}
+
+fn default_margin_thickness() -> f32 {
+    1.0
+}
+
+fn default_grid_enabled() -> bool {
+    true
+}
+
+fn default_grid_units() -> usize {
+    0
+}
+
+fn default_zoom() -> f32 {
+    0.33333334
+}
+
+fn default_rulers_enabled() -> bool {
+    false
+}
+
+fn default_ruler_units() -> usize {
+    0
+}
+
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+struct LayoutDocument {
+    page_w: f32,
+    page_h: f32,
+    page_color: [f32; 4],
+    margin_enabled: bool,
+    margin_x: f32,
+    margin_y: f32,
+    word_processor_enabled: bool,
+    wp_text: String,
+    elements: Vec<Element>,
+    #[serde(default = "default_grid_color")]
+    grid_color: [f32; 4],
+    #[serde(default = "default_grid_size")]
+    grid_size: f32,
+    #[serde(default = "default_margin_color")]
+    margin_color: [f32; 4],
+    #[serde(default = "default_margin_thickness")]
+    margin_thickness: f32,
+    #[serde(default = "default_grid_enabled")]
+    grid_enabled: bool,
+    #[serde(default = "default_grid_units")]
+    grid_units: usize,
+    #[serde(default = "default_zoom")]
+    zoom: f32,
+    #[serde(default = "default_rulers_enabled")]
+    rulers_enabled: bool,
+    #[serde(default = "default_ruler_units")]
+    ruler_units: usize,
 }
 
 struct PagePreset {
@@ -53,21 +253,38 @@ struct PagePreset {
 
 const PRESETS: &[PagePreset] = &[
     PagePreset { name: "Letter (8.5\" x 11\")", w: 510.0, h: 660.0 },
+    PagePreset { name: "Legal (8.5\" x 14\")", w: 510.0, h: 840.0 },
     PagePreset { name: "Tabloid (11\" x 17\")", w: 660.0, h: 1020.0 },
+    PagePreset { name: "Executive (7.25\" x 10.5\")", w: 435.0, h: 630.0 },
+    PagePreset { name: "A3 (297 x 420 mm)", w: 701.0, h: 992.0 },
     PagePreset { name: "A4 (210 x 297 mm)", w: 496.0, h: 701.0 },
     PagePreset { name: "A5 (148 x 210 mm)", w: 350.0, h: 496.0 },
-    PagePreset { name: "Poster (8\" x 8\")", w: 480.0, h: 480.0 },
+    PagePreset { name: "A6 (105 x 148 mm)", w: 248.0, h: 350.0 },
+    PagePreset { name: "B5 (JIS) (182 x 257 mm)", w: 430.0, h: 607.0 },
+    PagePreset { name: "Business Card (3.5\" x 2\")", w: 210.0, h: 120.0 },
+    PagePreset { name: "Presentation (16:9)", w: 800.0, h: 450.0 },
+    PagePreset { name: "Square Poster (12\" x 12\")", w: 720.0, h: 720.0 },
     PagePreset { name: "Custom", w: 510.0, h: 660.0 },
 ];
 
 struct LayoutApp {
-    menu_bar: MenuBar,
+    btn_new_doc: Button,
+    btn_open: Button,
+    recent_files: Vec<std::path::PathBuf>,
+    recent_files_list: ScrollingList,
+    recent_files_buttons: Vec<Button>,
+    btn_exit: Button,
+    btn_save: Button,
+    btn_save_as: Button,
     paginator: Paginator,
+    layer_buttons: Vec<Box<Button>>,
     elements: Vec<Element>,
     selected_idx: Option<usize>,
     dragging: Option<(usize, f32, f32)>, // Index, offset_x, offset_y
     grid_enabled: bool,
     width: u32,
+    current_file_path: Option<std::path::PathBuf>,
+    last_saved_document: LayoutDocument,
     height: u32,
     scale_factor: f64,
     text_items: Vec<TextItem>,
@@ -90,13 +307,19 @@ struct LayoutApp {
     toggle_word_processor: Toggle,
     word_processor_enabled: bool,
     wp_text_box: TextBox,
-    sidebar_x: TextBox,
-    sidebar_y: TextBox,
-    sidebar_w: TextBox,
-    sidebar_h: TextBox,
+    sidebar_x: Spinbox,
+    sidebar_y: Spinbox,
+    sidebar_w: Spinbox,
+    sidebar_h: Spinbox,
     sidebar_text: TextBox,
     sidebar_size: Spinbox,
-    dropdown_font_family: Dropdown,
+    font_selector: FontSelector,
+    dropdown_text_align_h: Dropdown,
+    dropdown_text_align_v: Dropdown,
+    toggle_multiline: Toggle,
+    dropdown_align_h: Dropdown,
+    dropdown_align_v: Dropdown,
+    dropdown_line_cap: Dropdown,
     wp_base_font_size: f32,
     
     slider_r: Slider,
@@ -105,22 +328,28 @@ struct LayoutApp {
     slider_zoom: Slider,
     
     // Page 1: Canvas settings controls
-    btn_toggle_grid: Button,
-    btn_clear_canvas: Button,
+    toggle_grid: Toggle,
+    grid_color_selector: ColorSelector,
+    grid_color: [f32; 4],
+    grid_size: f32,
+    spinbox_grid_size: Spinbox,
+    dropdown_grid_units: Dropdown,
+    margin_color_selector: ColorSelector,
+    margin_color: [f32; 4],
+    spinbox_margin_thickness: Spinbox,
+    margin_thickness: f32,
     btn_add_text: Button,
     btn_add_rect: Button,
     btn_add_banner: Button,
+    btn_add_vector: Button,
 
-    // Page 3: View settings controls
     toggle_rulers: Toggle,
     dropdown_units: Dropdown,
 
-    section_rulers: SectionHeader,
-
     label_sel_status: Label,
     label_sel_desc1: Label,
     label_sel_desc2: Label,
-    label_grid_snap: Label,
+    label_grid_snap: Toggle,
     label_total_elements: Label,
 
     last_selected: Option<usize>,
@@ -128,7 +357,7 @@ struct LayoutApp {
     page_h: f32,
     pan_x: f32,
     pan_y: f32,
-    widgets_registered: bool,
+    sidebar_quads: Vec<(f32, f32, f32, f32, [f32; 4])>,
 }
 
 fn get_monitor_ppi() -> f32 {
@@ -171,7 +400,238 @@ fn get_monitor_ppi() -> f32 {
     fallback_ppi
 }
 
+fn get_system_fonts() -> Vec<String> {
+    let mut fonts = Vec::new();
+    if let Ok(output) = std::process::Command::new("fc-list")
+        .arg(":")
+        .arg("family")
+        .output()
+    {
+        if let Ok(stdout) = String::from_utf8(output.stdout) {
+            for line in stdout.lines() {
+                for part in line.split(',') {
+                    let cleaned = part.replace('\\', "").trim().to_string();
+                    if !cleaned.is_empty() {
+                        fonts.push(cleaned);
+                    }
+                }
+            }
+        }
+    }
+    fonts.sort_by(|a, b| a.to_lowercase().cmp(&b.to_lowercase()));
+    fonts.dedup();
+    if fonts.is_empty() {
+        fonts = vec![
+            "Monospace".to_string(),
+            "Sans-Serif".to_string(),
+            "Serif".to_string(),
+        ];
+    }
+    fonts
+}
+
 impl LayoutApp {
+    fn get_recent_files_path() -> Option<std::path::PathBuf> {
+        std::env::var("HOME").ok().map(|h| {
+            let mut path = std::path::PathBuf::from(h);
+            path.push(".config");
+            path.push("clear-layout-interface");
+            path.push("recent_files.json");
+            path
+        })
+    }
+
+    fn load_recent_files() -> Vec<std::path::PathBuf> {
+        if let Some(path) = Self::get_recent_files_path() {
+            if let Ok(file) = std::fs::File::open(path) {
+                if let Ok(list) = serde_json::from_reader::<_, Vec<String>>(file) {
+                    return list.into_iter().map(std::path::PathBuf::from).collect();
+                }
+            }
+        }
+        Vec::new()
+    }
+
+    fn save_recent_files(files: &[std::path::PathBuf]) {
+        if let Some(path) = Self::get_recent_files_path() {
+            if let Some(parent) = path.parent() {
+                let _ = std::fs::create_dir_all(parent);
+            }
+            if let Ok(file) = std::fs::File::create(path) {
+                let list: Vec<String> = files.iter().map(|p| p.to_string_lossy().to_string()).collect();
+                let _ = serde_json::to_writer_pretty(file, &list);
+            }
+        }
+    }
+
+    fn add_recent_file(&mut self, path: std::path::PathBuf) {
+        self.recent_files.retain(|p| p != &path);
+        self.recent_files.insert(0, path);
+        self.recent_files.truncate(10);
+        Self::save_recent_files(&self.recent_files);
+        self.rebuild_recent_buttons();
+    }
+
+    fn rebuild_recent_buttons(&mut self) {
+        self.recent_files_buttons.clear();
+        for file in &self.recent_files {
+            let label = file.file_name()
+                .map(|n| n.to_string_lossy().to_string())
+                .unwrap_or_else(|| file.to_string_lossy().to_string());
+            let btn = Button::new_list_row(0.0, 0.0, 0.0, 0.0).with_label(&label);
+            self.recent_files_buttons.push(btn);
+        }
+    }
+
+    fn save_document(&self, path: &std::path::Path) -> std::io::Result<()> {
+        let doc = self.get_current_document();
+        let file = std::fs::File::create(path)?;
+        serde_json::to_writer_pretty(file, &doc)?;
+        Ok(())
+    }
+
+    fn perform_save_as(&mut self) {
+        let path_opt = std::process::Command::new("/home/lsgalante/.local/bin/clear-filesystem-interface")
+            .arg("--save")
+            .output()
+            .or_else(|_| {
+                std::process::Command::new("clear-filesystem-interface")
+                    .arg("--save")
+                    .output()
+            })
+            .ok()
+            .and_then(|output| {
+                if output.status.success() {
+                    let stdout = String::from_utf8_lossy(&output.stdout);
+                    let trimmed = stdout.trim();
+                    if !trimmed.is_empty() {
+                        Some(std::path::PathBuf::from(trimmed))
+                    } else {
+                        None
+                    }
+                } else {
+                    None
+                }
+            });
+
+        if let Some(path) = path_opt {
+            if let Err(e) = self.save_document(&path) {
+                eprintln!("ERROR: Failed to save document: {}", e);
+            } else {
+                println!("DEBUG: Successfully saved layout to {:?}", path);
+                self.current_file_path = Some(path.clone());
+                self.last_saved_document = self.get_current_document();
+                self.add_recent_file(path);
+            }
+        }
+    }
+
+    fn load_document(&mut self, path: &std::path::Path) -> std::io::Result<()> {
+        let file = std::fs::File::open(path)?;
+        let doc: LayoutDocument = serde_json::from_reader(file)?;
+        
+        self.page_w = doc.page_w;
+        self.page_h = doc.page_h;
+        self.page_color = doc.page_color;
+        self.margin_enabled = doc.margin_enabled;
+        self.margin_x = doc.margin_x;
+        self.margin_y = doc.margin_y;
+        self.word_processor_enabled = doc.word_processor_enabled;
+        self.wp_text_box.text = doc.wp_text.clone();
+        self.wp_text_box.edit_buffer = doc.wp_text;
+        self.elements = doc.elements;
+
+        self.toggle_margin.set_toggled(self.margin_enabled);
+        self.toggle_word_processor.set_toggled(self.word_processor_enabled);
+        
+        let r = (self.page_color[0] * 255.0).clamp(0.0, 255.0) as u8;
+        let g = (self.page_color[1] * 255.0).clamp(0.0, 255.0) as u8;
+        let b = (self.page_color[2] * 255.0).clamp(0.0, 255.0) as u8;
+        self.page_color_selector.color = [r, g, b];
+
+        self.grid_color = doc.grid_color;
+        self.grid_size = doc.grid_size;
+        self.margin_color = doc.margin_color;
+
+        let gr = (self.grid_color[0] * 255.0).clamp(0.0, 255.0) as u8;
+        let gg = (self.grid_color[1] * 255.0).clamp(0.0, 255.0) as u8;
+        let gb = (self.grid_color[2] * 255.0).clamp(0.0, 255.0) as u8;
+        self.grid_color_selector.color = [gr, gg, gb];
+        self.spinbox_grid_size.value = (self.grid_size * 10.0).round() as i32;
+
+        let mr = (self.margin_color[0] * 255.0).clamp(0.0, 255.0) as u8;
+        let mg = (self.margin_color[1] * 255.0).clamp(0.0, 255.0) as u8;
+        let mb = (self.margin_color[2] * 255.0).clamp(0.0, 255.0) as u8;
+        self.margin_color_selector.color = [mr, mg, mb];
+
+        self.margin_thickness = doc.margin_thickness;
+        self.spinbox_margin_thickness.value = self.margin_thickness.round() as i32;
+
+        self.grid_enabled = doc.grid_enabled;
+        self.toggle_grid.set_toggled(doc.grid_enabled);
+        self.label_grid_snap.set_toggled(doc.grid_enabled);
+        self.dropdown_grid_units.selected = doc.grid_units;
+        self.slider_zoom.set_value(doc.zoom);
+        self.toggle_rulers.set_toggled(doc.rulers_enabled);
+        self.dropdown_units.selected = doc.ruler_units;
+
+        let mut preset_idx = PRESETS.len() - 1; // Custom
+        for (i, preset) in PRESETS.iter().enumerate() {
+            if (preset.w - self.page_w).abs() < 1.0 && (preset.h - self.page_h).abs() < 1.0 {
+                preset_idx = i;
+                break;
+            }
+        }
+        self.dropdown_presets.selected = preset_idx;
+
+        self.sync_page_units();
+        self.rebuild_layers_tab_widgets();
+        self.sync_sidebar_fields();
+        self.needs_rebuild = true;
+
+        Ok(())
+    }
+
+    fn perform_open(&mut self) {
+        let path_opt = std::process::Command::new("/home/lsgalante/.local/bin/clear-filesystem-interface")
+            .arg("--select")
+            .output()
+            .or_else(|_| {
+                std::process::Command::new("clear-filesystem-interface")
+                    .arg("--select")
+                    .output()
+            })
+            .ok()
+            .and_then(|output| {
+                if output.status.success() {
+                    let stdout = String::from_utf8_lossy(&output.stdout);
+                    let trimmed = stdout.trim();
+                    if !trimmed.is_empty() {
+                        Some(std::path::PathBuf::from(trimmed))
+                    } else {
+                        None
+                    }
+                } else {
+                    None
+                }
+            });
+
+        if let Some(path) = path_opt {
+            self.selected_idx = None;
+            self.dragging = None;
+            self.pan_x = 0.0;
+            self.pan_y = 0.0;
+            if let Err(e) = self.load_document(&path) {
+                eprintln!("ERROR: Failed to load document: {}", e);
+            } else {
+                println!("DEBUG: Successfully loaded layout from {:?}", path);
+                self.current_file_path = Some(path.clone());
+                self.last_saved_document = self.get_current_document();
+                self.add_recent_file(path);
+            }
+        }
+    }
+
     fn sync_page_units(&mut self) {
         let unit_idx = self.dropdown_margin_units.selected;
         let px_per_unit = match unit_idx {
@@ -215,8 +675,377 @@ impl LayoutApp {
     }
 
     fn rebuild_text_items(&mut self) {
-        // Sync labels with current state
+        let font_system = &mut self.font_system;
+        let selected_page = self.paginator.selected_page();
+        let word_processor_enabled = self.word_processor_enabled;
+        
+        match selected_page {
+            0 => {
+                self.btn_new_doc.prepare_text(font_system);
+                self.btn_open.prepare_text(font_system);
+                for btn in &mut self.recent_files_buttons {
+                    btn.prepare_text(font_system);
+                }
+                self.btn_save.prepare_text(font_system);
+                self.btn_save_as.prepare_text(font_system);
+                self.btn_exit.prepare_text(font_system);
+            }
+            1 => {
+                self.dropdown_margin_units.prepare_text(font_system);
+                self.dropdown_presets.prepare_text(font_system);
+                self.slider_page_x.prepare_text(font_system);
+                self.slider_page_y.prepare_text(font_system);
+                self.page_color_selector.prepare_text(font_system);
+                self.toggle_margin.prepare_text(font_system);
+                self.toggle_word_processor.prepare_text(font_system);
+                self.slider_margin_x.prepare_text(font_system);
+                self.slider_margin_y.prepare_text(font_system);
+            }
+            2 => {
+                if word_processor_enabled {
+                    self.font_selector.prepare_text(font_system);
+                    self.sidebar_size.prepare_text(font_system);
+                    self.slider_r.prepare_text(font_system);
+                    self.slider_g.prepare_text(font_system);
+                    self.slider_b.prepare_text(font_system);
+                } else if self.selected_idx.is_some() {
+                    self.dropdown_align_h.prepare_text(font_system);
+                    self.dropdown_align_v.prepare_text(font_system);
+
+                    let (is_text, is_vector) = match self.selected_idx.map(|idx| &self.elements[idx]) {
+                        Some(Element::Text { .. }) => (true, false),
+                        Some(Element::Vector { .. }) => (false, true),
+                        _ => (false, false),
+                    };
+                    if is_text {
+                        self.sidebar_x.prepare_text(font_system);
+                        self.sidebar_y.prepare_text(font_system);
+                        self.sidebar_w.prepare_text(font_system);
+                        self.sidebar_h.prepare_text(font_system);
+                        self.sidebar_text.prepare_text(font_system);
+                        self.font_selector.prepare_text(font_system);
+                        self.toggle_multiline.prepare_text(font_system);
+                        self.dropdown_text_align_h.prepare_text(font_system);
+                        self.dropdown_text_align_v.prepare_text(font_system);
+                        self.sidebar_size.prepare_text(font_system);
+                        self.slider_r.prepare_text(font_system);
+                        self.slider_g.prepare_text(font_system);
+                        self.slider_b.prepare_text(font_system);
+                    } else if is_vector {
+                        self.sidebar_x.prepare_text(font_system);
+                        self.sidebar_y.prepare_text(font_system);
+                        self.sidebar_w.prepare_text(font_system);
+                        self.sidebar_h.prepare_text(font_system);
+                        self.sidebar_size.prepare_text(font_system);
+                        self.dropdown_line_cap.prepare_text(font_system);
+                        self.slider_r.prepare_text(font_system);
+                        self.slider_g.prepare_text(font_system);
+                        self.slider_b.prepare_text(font_system);
+                    } else {
+                        self.sidebar_x.prepare_text(font_system);
+                        self.sidebar_y.prepare_text(font_system);
+                        self.sidebar_w.prepare_text(font_system);
+                        self.sidebar_h.prepare_text(font_system);
+                        self.slider_r.prepare_text(font_system);
+                        self.slider_g.prepare_text(font_system);
+                        self.slider_b.prepare_text(font_system);
+                    }
+                }
+            }
+            3 => {
+                self.btn_add_text.prepare_text(font_system);
+                self.btn_add_rect.prepare_text(font_system);
+                self.btn_add_banner.prepare_text(font_system);
+                self.btn_add_vector.prepare_text(font_system);
+            }
+            4 => {
+                self.toggle_grid.prepare_text(font_system);
+                self.grid_color_selector.prepare_text(font_system);
+                self.spinbox_grid_size.prepare_text(font_system);
+                self.label_grid_snap.prepare_text(font_system);
+                self.slider_zoom.prepare_text(font_system);
+                self.toggle_rulers.prepare_text(font_system);
+                self.dropdown_units.prepare_text(font_system);
+                self.margin_color_selector.prepare_text(font_system);
+                self.spinbox_margin_thickness.prepare_text(font_system);
+                self.dropdown_grid_units.prepare_text(font_system);
+            }
+            5 => {
+                for btn in &mut self.layer_buttons {
+                    btn.prepare_text(font_system);
+                }
+            }
+            _ => {}
+        }
+        
+        self.wp_text_box.prepare_text(font_system);
+
+        self.sidebar_quads.clear();
+        self.text_items.clear();
+
+        // 1. Populate sidebar page views into PageContent
+        let mut pc = PageContent::new();
+        let ui_frame = UiFrame::start(0.0);
+
+        let sidebar_w = self.paginator.sidebar_w();
+        let cx = sidebar_w;
+        let cy = 16.0;
+        let cw = 280.0 - sidebar_w;
+
+        match self.paginator.selected_page() {
+            0 => {
+                let mut sec = Section::new(&mut pc, cx, cy, cw, "File Operations");
+                let col_w = cw - 40.0;
+                sec.widget(&mut pc, &mut self.btn_new_doc, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.btn_open, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                
+                sec.text(&mut pc, "Recent Files", 12.0, 0.0, 11.0, [0.83, 0.83, 0.83, 1.0]);
+                sec.spacing(16.0);
+
+                let list_h = 100.0;
+                let list_x = sec.ax(12.0);
+                let list_y = sec.ay();
+                sec.widget(&mut pc, &mut self.recent_files_list, 12.0, col_w, list_h);
+
+                self.recent_files_list.update_bounds(self.recent_files.len(), list_y, list_h);
+
+                let btn_h = 22.0;
+                let inner_x = list_x + 4.0;
+                let inner_w = col_w - 16.0;
+
+                for (idx, btn) in self.recent_files_buttons.iter_mut().enumerate() {
+                    if let Some(draw_y) = self.recent_files_list.get_item_draw_y(idx, 0.0) {
+                        clear_ui::layout::render_widget(&mut pc, btn, inner_x, draw_y, inner_w, btn_h);
+                    } else {
+                        btn.set_rect(-9999.0, -9999.0, 0.0, 0.0);
+                    }
+                }
 
+                if self.recent_files.is_empty() {
+                    pc.text("No recent files", list_x + 12.0, list_y + 16.0, 11.0, [0.55, 0.55, 0.60, 1.0]);
+                }
+
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.btn_save, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.btn_save_as, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.btn_exit, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.finish(&mut pc);
+            }
+            1 => {
+                let mut sec = Section::new(&mut pc, cx, cy, cw, "Document Size");
+                let col_w = cw - 40.0;
+                sec.widget(&mut pc, &mut self.dropdown_presets, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.slider_page_x, 12.0, col_w, 18.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.slider_page_y, 12.0, col_w, 18.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.page_color_selector, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                let next_y = sec.finish(&mut pc);
+
+                let mut sec2 = Section::new(&mut pc, cx, next_y, cw, "Margins & Mode");
+                sec2.widget(&mut pc, &mut self.toggle_margin, 12.0, col_w, 26.0);
+                sec2.spacing(12.0);
+                sec2.widget(&mut pc, &mut self.dropdown_margin_units, 12.0, col_w, 26.0);
+                sec2.spacing(12.0);
+                sec2.widget(&mut pc, &mut self.slider_margin_x, 12.0, col_w, 18.0);
+                sec2.spacing(12.0);
+                sec2.widget(&mut pc, &mut self.slider_margin_y, 12.0, col_w, 18.0);
+                sec2.spacing(12.0);
+                sec2.widget(&mut pc, &mut self.toggle_word_processor, 12.0, col_w, 26.0);
+                sec2.spacing(12.0);
+                sec2.finish(&mut pc);
+            }
+            2 => {
+                let col_w = cw - 40.0;
+                if self.word_processor_enabled {
+                    let mut sec = Section::new(&mut pc, cx, cy, cw, "Word Processor");
+                    sec.widget(&mut pc, &mut self.font_selector, 12.0, col_w, 26.0);
+                    sec.spacing(12.0);
+                    sec.widget(&mut pc, &mut self.sidebar_size, 12.0, col_w, 26.0);
+                    sec.spacing(12.0);
+                    sec.widget(&mut pc, &mut self.slider_r, 12.0, col_w, 18.0);
+                    sec.spacing(12.0);
+                    sec.widget(&mut pc, &mut self.slider_g, 12.0, col_w, 18.0);
+                    sec.spacing(12.0);
+                    sec.widget(&mut pc, &mut self.slider_b, 12.0, col_w, 18.0);
+                    sec.spacing(12.0);
+                    sec.finish(&mut pc);
+                } else if let Some(idx) = self.selected_idx {
+                    let (is_text, is_vector) = match &self.elements[idx] {
+                        Element::Text { .. } => (true, false),
+                        Element::Vector { .. } => (false, true),
+                        _ => (false, false),
+                    };
+
+                    let mut sec = Section::new(&mut pc, cx, cy, cw, "Geometry");
+                    sec.widget(&mut pc, &mut self.sidebar_x, 12.0, col_w, 26.0);
+                    sec.spacing(16.0);
+                    sec.widget(&mut pc, &mut self.sidebar_y, 12.0, col_w, 26.0);
+                    sec.spacing(16.0);
+                    sec.widget(&mut pc, &mut self.sidebar_w, 12.0, col_w, 26.0);
+                    sec.spacing(16.0);
+                    sec.widget(&mut pc, &mut self.sidebar_h, 12.0, col_w, 26.0);
+                    sec.spacing(12.0);
+                    let next_y = sec.finish(&mut pc);
+
+                    let mut sec_align = Section::new(&mut pc, cx, next_y, cw, "Alignment");
+                    sec_align.widget(&mut pc, &mut self.dropdown_align_h, 12.0, col_w, 26.0);
+                    sec_align.spacing(12.0);
+                    sec_align.widget(&mut pc, &mut self.dropdown_align_v, 12.0, col_w, 26.0);
+                    let next_y = sec_align.finish(&mut pc);
+
+                    if is_text {
+                        let mut sec2 = Section::new(&mut pc, cx, next_y, cw, "Text Properties");
+                        sec2.widget(&mut pc, &mut self.sidebar_text, 12.0, col_w, 26.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.toggle_multiline, 12.0, col_w, 26.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.font_selector, 12.0, col_w, 26.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.sidebar_size, 12.0, col_w, 26.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.slider_r, 12.0, col_w, 18.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.slider_g, 12.0, col_w, 18.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.slider_b, 12.0, col_w, 18.0);
+                        sec2.spacing(12.0);
+                        let next_y_align = sec2.finish(&mut pc);
+
+                        let mut sec_text_align = Section::new(&mut pc, cx, next_y_align, cw, "Text Alignment");
+                        sec_text_align.widget(&mut pc, &mut self.dropdown_text_align_h, 12.0, col_w, 26.0);
+                        sec_text_align.spacing(12.0);
+                        sec_text_align.widget(&mut pc, &mut self.dropdown_text_align_v, 12.0, col_w, 26.0);
+                        sec_text_align.finish(&mut pc);
+                    } else if is_vector {
+                        let mut sec2 = Section::new(&mut pc, cx, next_y, cw, "Line Properties");
+                        sec2.widget(&mut pc, &mut self.sidebar_size, 12.0, col_w, 26.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.dropdown_line_cap, 12.0, col_w, 26.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.slider_r, 12.0, col_w, 18.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.slider_g, 12.0, col_w, 18.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.slider_b, 12.0, col_w, 18.0);
+                        sec2.spacing(12.0);
+                        sec2.finish(&mut pc);
+                    } else {
+                        let mut sec2 = Section::new(&mut pc, cx, next_y, cw, "Fill Color");
+                        sec2.widget(&mut pc, &mut self.slider_r, 12.0, col_w, 18.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.slider_g, 12.0, col_w, 18.0);
+                        sec2.spacing(12.0);
+                        sec2.widget(&mut pc, &mut self.slider_b, 12.0, col_w, 18.0);
+                        sec2.spacing(12.0);
+                        sec2.finish(&mut pc);
+                    }
+                } else {
+                    let mut sec = Section::new(&mut pc, cx, cy, cw, "Properties");
+                    sec.widget(&mut pc, &mut self.label_sel_status, 12.0, col_w, 18.0);
+                    sec.spacing(8.0);
+                    sec.widget(&mut pc, &mut self.label_sel_desc1, 12.0, col_w, 14.0);
+                    sec.spacing(6.0);
+                    sec.widget(&mut pc, &mut self.label_sel_desc2, 12.0, col_w, 14.0);
+                    sec.spacing(12.0);
+                    sec.finish(&mut pc);
+                }
+            }
+            3 => {
+                let mut sec = Section::new(&mut pc, cx, cy, cw, "Add Elements");
+                let col_w = cw - 40.0;
+                sec.widget(&mut pc, &mut self.btn_add_text, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.btn_add_rect, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.btn_add_banner, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.btn_add_vector, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.label_total_elements, 12.0, col_w, 18.0);
+                sec.spacing(12.0);
+                sec.finish(&mut pc);
+            }
+            4 => {
+                let mut sec = Section::new(&mut pc, cx, cy, cw, "Grid");
+                let col_w = cw - 40.0;
+                sec.widget(&mut pc, &mut self.toggle_grid, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.grid_color_selector, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.spinbox_grid_size, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.label_grid_snap, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                sec.widget(&mut pc, &mut self.dropdown_grid_units, 12.0, col_w, 26.0);
+                sec.spacing(12.0);
+                let next_y = sec.finish(&mut pc);
+
+                let mut sec_zoom = Section::new(&mut pc, cx, next_y, cw, "Zoom");
+                sec_zoom.widget(&mut pc, &mut self.slider_zoom, 12.0, col_w, 18.0);
+                sec_zoom.spacing(12.0);
+                let next_y = sec_zoom.finish(&mut pc);
+
+                let mut sec_margins = Section::new(&mut pc, cx, next_y, cw, "Margins");
+                sec_margins.widget(&mut pc, &mut self.margin_color_selector, 12.0, col_w, 26.0);
+                sec_margins.spacing(12.0);
+                sec_margins.widget(&mut pc, &mut self.spinbox_margin_thickness, 12.0, col_w, 26.0);
+                sec_margins.spacing(12.0);
+                let next_y = sec_margins.finish(&mut pc);
+
+                let mut sec2 = Section::new(&mut pc, cx, next_y, cw, "Rulers");
+                sec2.widget(&mut pc, &mut self.toggle_rulers, 12.0, col_w, 26.0);
+                sec2.spacing(12.0);
+                sec2.widget(&mut pc, &mut self.dropdown_units, 12.0, col_w, 26.0);
+                sec2.spacing(12.0);
+                sec2.finish(&mut pc);
+            }
+            5 => {
+                let mut sec = Section::new(&mut pc, cx, cy, cw, "Layers List");
+                let col_w = cw - 40.0;
+                if self.layer_buttons.is_empty() {
+                    let mut label_no_layers = Label::new("No elements found").with_color([0x83, 0x83, 0x8a]);
+                    sec.widget(&mut pc, &mut label_no_layers, 12.0, col_w, 18.0);
+                    sec.spacing(12.0);
+                } else {
+                    for btn in &mut self.layer_buttons {
+                        sec.widget(&mut pc, &mut **btn, 12.0, col_w, 26.0);
+                        sec.spacing(8.0);
+                    }
+                }
+                sec.finish(&mut pc);
+            }
+            _ => {}
+        }
+
+        ui_frame.finish(&mut pc);
+
+        // Store the sidebar quads
+        for (c, x, y, w, h) in pc.rects {
+            self.sidebar_quads.push((x, y, w, h, c));
+        }
+
+        // Convert pc.texts to glyphon text items
+        for (text, size, x, y, color, font, bounds) in pc.texts {
+            self.text_items.push(TextItem {
+                buffer: make_text_buffer_with_font(&mut self.font_system, &text, size, font.as_deref()),
+                x,
+                y,
+                color: glyphon::Color::rgb(
+                    (color[0] * 255.0).clamp(0.0, 255.0) as u8,
+                    (color[1] * 255.0).clamp(0.0, 255.0) as u8,
+                    (color[2] * 255.0).clamp(0.0, 255.0) as u8,
+                ),
+                bounds,
+            });
+        }
 
         if let Some(idx) = self.selected_idx {
             self.label_sel_status.set_text(&format!("Selected Element #{}", idx + 1));
@@ -230,23 +1059,32 @@ impl LayoutApp {
             self.label_sel_desc2.set_text("to edit properties.");
         }
 
-        self.label_grid_snap.set_text(&format!("Grid Snapping: {}", if self.grid_enabled { "ON (20px)" } else { "OFF" }));
+        let snap_suffix = match self.dropdown_grid_units.selected {
+            0 => "20px",
+            1 => "0.25in",
+            2 => "0.5cm",
+            3 => "5mm",
+            _ => "20px",
+        };
+        self.label_grid_snap.set_label(&format!(
+            "Grid Snapping: {}",
+            if self.grid_enabled {
+                format!("ON ({})", snap_suffix)
+            } else {
+                "OFF".to_string()
+            }
+        ));
         self.label_total_elements.set_text(&format!("Total Elements: {}", self.elements.len()));
 
-        self.text_items.clear();
-        
         let mut labels = Vec::new();
 
         let canvas_w = self.width as f32 - 280.0;
-        let canvas_h = self.height as f32 - 26.0;
+        let canvas_h = self.height as f32;
         let zoom = self.render_zoom();
         let page_w = self.page_w * zoom;
         let page_h = self.page_h * zoom;
         let page_x = 280.0 + (canvas_w - page_w) / 2.0 + self.pan_x;
-        let page_y = 26.0 + (canvas_h - page_h) / 2.0 + self.pan_y;
-        
-        // 1. MenuBar text labels
-        labels.extend(self.menu_bar.text_labels());
+        let page_y = (canvas_h - page_h) / 2.0 + self.pan_y;
         
         // 2. Paginator sidebar tabs
         labels.extend(self.paginator.text_labels());
@@ -255,23 +1093,6 @@ impl LayoutApp {
             let _ = writeln!(file, "rebuild_text_items: labels={:?}", labels.iter().map(|l| &l.text).collect::<Vec<_>>());
         }
         
-        // 3. Collect and add active page popover labels
-        let mut collector = clear_ui::layout::PopoverCollector::new();
-        self.paginator.render_popover(&mut collector);
-        for (text, size, x, y, color, _font) in collector.texts {
-            labels.push(TextLabel {
-                text,
-                x,
-                y,
-                font_size: size,
-                color: [
-                    (color[0] * 255.0).clamp(0.0, 255.0) as u8,
-                    (color[1] * 255.0).clamp(0.0, 255.0) as u8,
-                    (color[2] * 255.0).clamp(0.0, 255.0) as u8,
-                ],
-            });
-        }
-
         if self.toggle_rulers.toggled() {
             let unit_idx = self.dropdown_units.selected;
             let (px_per_unit, tick_step, label_step, precision) = match unit_idx {
@@ -322,10 +1143,16 @@ impl LayoutApp {
         // 5. Canvas Element Labels (drawn relative to the paper sheet)
         if self.word_processor_enabled {
             let font_family = self.wp_text_box.font_family.clone();
-            for label in self.wp_text_box.text_labels() {
+            for (label, bounds) in self.wp_text_box.text_labels_with_bounds() {
                 let metrics = Metrics::new(label.font_size, label.font_size * 1.4);
                 let mut buf = Buffer::new(&mut self.font_system, metrics);
-                let attrs = Attrs::new().family(glyphon::Family::Name(&font_family));
+                let family_val = match font_family.as_str() {
+                    "monospace" => glyphon::Family::Monospace,
+                    "sans-serif" => glyphon::Family::SansSerif,
+                    "serif" => glyphon::Family::Serif,
+                    _ => glyphon::Family::Name(&font_family),
+                };
+                let attrs = Attrs::new().family(family_val);
                 buf.set_text(&mut self.font_system, &label.text, attrs, glyphon::Shaping::Advanced);
                 buf.shape_until_scroll(&mut self.font_system, true);
                 self.text_items.push(TextItem {
@@ -333,14 +1160,13 @@ impl LayoutApp {
                     x: label.x,
                     y: label.y,
                     color: glyphon::Color::rgb(label.color[0], label.color[1], label.color[2]),
+                    bounds,
                 });
             }
         } else {
             for (idx, element) in self.elements.iter().enumerate() {
                 match element {
-                    Element::Text { text, x, y, w: _, h: _, font_size, color, font_family } => {
-                        let label_x = page_x + *x * zoom + 8.0 * zoom;
-                        let label_y = page_y + *y * zoom + 6.0 * zoom;
+                    Element::Text { text, x, y, w, h, font_size, color, font_family, align_h, align_v, multiline } => {
                         let label_font_size = *font_size * zoom;
                         let label_color = [
                             (color[0] * 255.0).clamp(0.0, 255.0) as u8,
@@ -350,14 +1176,53 @@ impl LayoutApp {
 
                         let metrics = Metrics::new(label_font_size, label_font_size * 1.4);
                         let mut buf = Buffer::new(&mut self.font_system, metrics);
-                        let attrs = Attrs::new().family(glyphon::Family::Name(font_family));
+                        let family_val = match font_family.as_str() {
+                            "monospace" => glyphon::Family::Monospace,
+                            "sans-serif" => glyphon::Family::SansSerif,
+                            "serif" => glyphon::Family::Serif,
+                            _ => glyphon::Family::Name(font_family),
+                        };
+                        let attrs = Attrs::new().family(family_val);
                         buf.set_text(&mut self.font_system, text, attrs, glyphon::Shaping::Advanced);
+                        
+                        let text_w = (*w * zoom - 16.0 * zoom).max(0.0);
+                        let text_h = (*h * zoom - 12.0 * zoom).max(0.0);
+                        let text_w_opt = if *multiline { Some(text_w) } else { None };
+                        buf.set_size(&mut self.font_system, text_w_opt, Some(text_h));
+                        
+                        let align_val = match align_h {
+                            TextAlignH::Left => glyphon::cosmic_text::Align::Left,
+                            TextAlignH::Center => glyphon::cosmic_text::Align::Center,
+                            TextAlignH::Right => glyphon::cosmic_text::Align::Right,
+                        };
+                        for line in &mut buf.lines {
+                            line.set_align(Some(align_val));
+                        }
+                        
                         buf.shape_until_scroll(&mut self.font_system, true);
+
+                        // Calculate vertical alignment offset
+                        let mut layout_runs_count = 0;
+                        for _ in buf.layout_runs() {
+                            layout_runs_count += 1;
+                        }
+                        let line_height = label_font_size * 1.4;
+                        let total_text_height = layout_runs_count as f32 * line_height;
+                        let vertical_offset = match align_v {
+                            TextAlignV::Middle => ((text_h - total_text_height) / 2.0).max(0.0),
+                            TextAlignV::Bottom => (text_h - total_text_height).max(0.0),
+                            TextAlignV::Top => 0.0,
+                        };
+
+                        let label_x = page_x + *x * zoom + 8.0 * zoom;
+                        let label_y = page_y + *y * zoom + 6.0 * zoom + vertical_offset;
+
                         self.text_items.push(TextItem {
                             buffer: buf,
                             x: label_x,
                             y: label_y,
                             color: glyphon::Color::rgb(label_color[0], label_color[1], label_color[2]),
+                            bounds: None,
                         });
                     }
                     Element::Shape { shape_type, x, y, w: _, h: _, color: _ } => {
@@ -373,6 +1238,15 @@ impl LayoutApp {
                             color: [0xee, 0xee, 0xf5],
                         });
                     }
+                    Element::Vector { x1, y1, .. } => {
+                        labels.push(TextLabel {
+                            text: format!("Line #{}", idx + 1),
+                            x: page_x + *x1 * zoom + 8.0 * zoom,
+                            y: page_y + *y1 * zoom + 6.0 * zoom,
+                            font_size: 11.0 * zoom,
+                            color: [0xee, 0xee, 0xf5],
+                        });
+                    }
                 }
             }
         }
@@ -387,66 +1261,44 @@ impl LayoutApp {
                 x: label.x,
                 y: label.y,
                 color: glyphon::Color::rgb(label.color[0], label.color[1], label.color[2]),
+                bounds: None,
             });
         }
     }
 
-    fn rebuild_element_tab_widgets(&mut self) {
-        self.paginator.clear_page_widgets(1);
-        
-        let self_ptr = self as *mut Self;
-        unsafe {
-            if self.word_processor_enabled {
-                (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).dropdown_font_family as *mut (dyn Widget + 'static));
-                (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_size as *mut (dyn Widget + 'static));
-                (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).slider_r as *mut (dyn Widget + 'static));
-                (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).slider_g as *mut (dyn Widget + 'static));
-                (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).slider_b as *mut (dyn Widget + 'static));
-            } else if let Some(idx) = self.selected_idx {
-                match &self.elements[idx] {
-                    Element::Text { .. } => {
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_x as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_y as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_w as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_h as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_text as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).dropdown_font_family as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_size as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).slider_r as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).slider_g as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).slider_b as *mut (dyn Widget + 'static));
-                    }
-                    Element::Shape { .. } => {
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_x as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_y as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_w as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).sidebar_h as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).slider_r as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).slider_g as *mut (dyn Widget + 'static));
-                        (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).slider_b as *mut (dyn Widget + 'static));
-                    }
+    fn rebuild_layers_tab_widgets(&mut self) {
+        self.layer_buttons.clear();
+        for (idx, element) in self.elements.iter().enumerate() {
+            let label = match element {
+                Element::Text { text, .. } => {
+                    let truncated: String = text.chars().take(20).collect();
+                    format!("{}. Text: \"{}\"", idx + 1, truncated)
                 }
-            } else {
-                (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).label_sel_status as *mut (dyn Widget + 'static));
-                (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).label_sel_desc1 as *mut (dyn Widget + 'static));
-                (*self_ptr).paginator.add_widget_to_page(1, &mut (*self_ptr).label_sel_desc2 as *mut (dyn Widget + 'static));
-            }
+                Element::Shape { shape_type, .. } => {
+                    let type_str = match shape_type {
+                        ShapeType::Rectangle => "Rectangle",
+                        ShapeType::Banner => "Banner",
+                    };
+                    format!("{}. {}", idx + 1, type_str)
+                }
+                Element::Vector { x1, y1, x2, y2, .. } => {
+                    format!("{}. Line: ({:.0},{:.0})->({:.0},{:.0})", idx + 1, x1, y1, x2, y2)
+                }
+            };
+            
+            let mut btn = Box::new(Button::new_list_row(0.0, 0.0, 224.0, 26.0).with_label(&label));
+            btn.selected = Some(idx) == self.selected_idx;
+            self.layer_buttons.push(btn);
         }
-        let (px, py, pw, ph) = self.paginator.rect();
-        self.paginator.set_rect(px, py, pw, ph);
     }
 
+
     fn sync_sidebar_fields(&mut self) {
         if self.word_processor_enabled {
             if !self.sidebar_size.editing {
                 self.sidebar_size.value = self.wp_base_font_size.round() as i32;
             }
-            let dropdown_idx = match self.wp_text_box.font_family.as_str() {
-                "sans-serif" => 1,
-                "serif" => 2,
-                _ => 0, // monospace
-            };
-            self.dropdown_font_family.selected = dropdown_idx;
+            self.font_selector.font_family = self.wp_text_box.font_family.clone();
 
             if let Some(rgb) = self.wp_text_box.text_color {
                 self.slider_r.set_value(rgb[0] as f32 / 255.0);
@@ -470,47 +1322,124 @@ impl LayoutApp {
             
             let element = &self.elements[idx];
             match element {
-                Element::Text { text, x, y, w, h, font_size, color, font_family } => {
+                Element::Text { text, x, y, w, h, font_size, color, font_family, align_h, align_v, multiline } => {
+                    self.sidebar_x.base_mut().map(|b| b.label = Some("X Position".to_string()));
+                    self.sidebar_y.base_mut().map(|b| b.label = Some("Y Position".to_string()));
+                    self.sidebar_w.base_mut().map(|b| b.label = Some("Width".to_string()));
+                    self.sidebar_h.base_mut().map(|b| b.label = Some("Height".to_string()));
+                    self.sidebar_size.base_mut().map(|b| b.label = Some("Text Size".to_string()));
+
                     if !self.sidebar_text.editing { self.sidebar_text.text = text.clone(); }
-                    if !self.sidebar_x.editing { self.sidebar_x.text = format!("{:.0}", x); }
-                    if !self.sidebar_y.editing { self.sidebar_y.text = format!("{:.0}", y); }
-                    if !self.sidebar_w.editing { self.sidebar_w.text = format!("{:.0}", w); }
-                    if !self.sidebar_h.editing { self.sidebar_h.text = format!("{:.0}", h); }
+                    if !self.sidebar_x.editing { self.sidebar_x.value = x.round() as i32; }
+                    if !self.sidebar_y.editing { self.sidebar_y.value = y.round() as i32; }
+                    if !self.sidebar_w.editing { self.sidebar_w.value = w.round() as i32; }
+                    if !self.sidebar_h.editing { self.sidebar_h.value = h.round() as i32; }
                     if !self.sidebar_size.editing { self.sidebar_size.value = font_size.round() as i32; }
                     
                     self.slider_r.set_value(color[0]);
                     self.slider_g.set_value(color[1]);
                     self.slider_b.set_value(color[2]);
 
-                    let dropdown_idx = match font_family.as_str() {
-                        "sans-serif" => 1,
-                        "serif" => 2,
-                        _ => 0, // monospace
+                    self.font_selector.font_family = font_family.clone();
+                    self.toggle_multiline.set_toggled(*multiline);
+
+                    self.dropdown_text_align_h.selected = match align_h {
+                        TextAlignH::Left => 0,
+                        TextAlignH::Center => 1,
+                        TextAlignH::Right => 2,
+                    };
+                    self.dropdown_text_align_v.selected = match align_v {
+                        TextAlignV::Top => 0,
+                        TextAlignV::Middle => 1,
+                        TextAlignV::Bottom => 2,
                     };
-                    self.dropdown_font_family.selected = dropdown_idx;
                 }
                 Element::Shape { shape_type: _, x, y, w, h, color } => {
+                    self.sidebar_x.base_mut().map(|b| b.label = Some("X Position".to_string()));
+                    self.sidebar_y.base_mut().map(|b| b.label = Some("Y Position".to_string()));
+                    self.sidebar_w.base_mut().map(|b| b.label = Some("Width".to_string()));
+                    self.sidebar_h.base_mut().map(|b| b.label = Some("Height".to_string()));
+
                     if !self.sidebar_text.editing { self.sidebar_text.text = "Shape Mode".to_string(); }
-                    if !self.sidebar_x.editing { self.sidebar_x.text = format!("{:.0}", x); }
-                    if !self.sidebar_y.editing { self.sidebar_y.text = format!("{:.0}", y); }
-                    if !self.sidebar_w.editing { self.sidebar_w.text = format!("{:.0}", w); }
-                    if !self.sidebar_h.editing { self.sidebar_h.text = format!("{:.0}", h); }
+                    if !self.sidebar_x.editing { self.sidebar_x.value = x.round() as i32; }
+                    if !self.sidebar_y.editing { self.sidebar_y.value = y.round() as i32; }
+                    if !self.sidebar_w.editing { self.sidebar_w.value = w.round() as i32; }
+                    if !self.sidebar_h.editing { self.sidebar_h.value = h.round() as i32; }
+                    
+                    self.slider_r.set_value(color[0]);
+                    self.slider_g.set_value(color[1]);
+                    self.slider_b.set_value(color[2]);
+                }
+                Element::Vector { x1, y1, x2, y2, stroke_width, color, line_cap } => {
+                    self.sidebar_x.base_mut().map(|b| b.label = Some("Start X".to_string()));
+                    self.sidebar_y.base_mut().map(|b| b.label = Some("Start Y".to_string()));
+                    self.sidebar_w.base_mut().map(|b| b.label = Some("End X".to_string()));
+                    self.sidebar_h.base_mut().map(|b| b.label = Some("End Y".to_string()));
+                    self.sidebar_size.base_mut().map(|b| b.label = Some("Thickness".to_string()));
+
+                    if !self.sidebar_text.editing { self.sidebar_text.text = "Line Mode".to_string(); }
+                    if !self.sidebar_x.editing { self.sidebar_x.value = x1.round() as i32; }
+                    if !self.sidebar_y.editing { self.sidebar_y.value = y1.round() as i32; }
+                    if !self.sidebar_w.editing { self.sidebar_w.value = x2.round() as i32; }
+                    if !self.sidebar_h.editing { self.sidebar_h.value = y2.round() as i32; }
+                    if !self.sidebar_size.editing { self.sidebar_size.value = stroke_width.round() as i32; }
+                    self.dropdown_line_cap.selected = match line_cap {
+                        LineCap::Arrow => 0,
+                        LineCap::Round => 1,
+                        LineCap::Flat => 2,
+                    };
                     
                     self.slider_r.set_value(color[0]);
                     self.slider_g.set_value(color[1]);
                     self.slider_b.set_value(color[2]);
                 }
             }
+
+            // Sync page alignment dropdowns based on current positions
+            let (ex, ey, ew, eh) = match element {
+                Element::Text { x, y, w, h, .. } => (*x, *y, *w, *h),
+                Element::Shape { x, y, w, h, .. } => (*x, *y, *w, *h),
+                Element::Vector { x1, y1, x2, y2, .. } => {
+                    let x = x1.min(*x2);
+                    let y = y1.min(*y2);
+                    let w = (x1 - x2).abs();
+                    let h = (y1 - y2).abs();
+                    (x, y, w, h)
+                }
+            };
+
+            let center_x = ((self.page_w - ew) / 2.0).round();
+            let right_x = (self.page_w - ew).round();
+            self.dropdown_align_h.selected = if (ex - 0.0).abs() < 0.1 {
+                1 // Left
+            } else if (ex - center_x).abs() < 0.1 {
+                2 // Center
+            } else if (ex - right_x).abs() < 0.1 {
+                3 // Right
+            } else {
+                0 // "--" (No alignment)
+            };
+
+            let middle_y = ((self.page_h - eh) / 2.0).round();
+            let bottom_y = (self.page_h - eh).round();
+            self.dropdown_align_v.selected = if (ey - 0.0).abs() < 0.1 {
+                1 // Top
+            } else if (ey - middle_y).abs() < 0.1 {
+                2 // Middle
+            } else if (ey - bottom_y).abs() < 0.1 {
+                3 // Bottom
+            } else {
+                0 // "--" (No alignment)
+            };
         }
     }
 
     fn apply_sidebar_changes(&mut self) {
         if self.word_processor_enabled {
-            let family_str = match self.dropdown_font_family.selected {
-                1 => "sans-serif",
-                2 => "serif",
-                _ => "monospace",
-            }.to_string();
+            let mut family_str = self.wp_text_box.font_family.clone();
+            if self.font_selector.take_change() {
+                family_str = self.font_selector.font_family.clone();
+            }
             self.wp_text_box.font_family = family_str;
 
             let size_val = if self.sidebar_size.editing {
@@ -526,10 +1455,48 @@ impl LayoutApp {
             self.wp_text_box.text_color = Some([r, g, b]);
         } else if let Some(idx) = self.selected_idx {
             let text_val = if self.sidebar_text.editing { self.sidebar_text.edit_buffer.clone() } else { self.sidebar_text.text.clone() };
-            let x_val = if self.sidebar_x.editing { &self.sidebar_x.edit_buffer } else { &self.sidebar_x.text }.parse::<f32>().unwrap_or(0.0);
-            let y_val = if self.sidebar_y.editing { &self.sidebar_y.edit_buffer } else { &self.sidebar_y.text }.parse::<f32>().unwrap_or(0.0);
-            let w_val = if self.sidebar_w.editing { &self.sidebar_w.edit_buffer } else { &self.sidebar_w.text }.parse::<f32>().unwrap_or(100.0);
-            let h_val = if self.sidebar_h.editing { &self.sidebar_h.edit_buffer } else { &self.sidebar_h.text }.parse::<f32>().unwrap_or(50.0);
+            let x_val = if self.sidebar_x.editing {
+                self.sidebar_x.edit_buffer.parse::<f32>().unwrap_or(0.0)
+            } else {
+                self.sidebar_x.value as f32
+            };
+            let y_val = if self.sidebar_y.editing {
+                self.sidebar_y.edit_buffer.parse::<f32>().unwrap_or(0.0)
+            } else {
+                self.sidebar_y.value as f32
+            };
+            let w_val = if self.sidebar_w.editing {
+                self.sidebar_w.edit_buffer.parse::<f32>().unwrap_or(100.0)
+            } else {
+                self.sidebar_w.value as f32
+            };
+            let h_val = if self.sidebar_h.editing {
+                self.sidebar_h.edit_buffer.parse::<f32>().unwrap_or(50.0)
+            } else {
+                self.sidebar_h.value as f32
+            };
+            
+            let is_vector = match &self.elements[idx] {
+                Element::Vector { .. } => true,
+                _ => false,
+            };
+            let (v_x2, v_y2) = if is_vector {
+                let nx2 = if self.sidebar_w.editing {
+                    self.sidebar_w.edit_buffer.parse::<f32>().unwrap_or(0.0)
+                } else {
+                    self.sidebar_w.value as f32
+                };
+                let ny2 = if self.sidebar_h.editing {
+                    self.sidebar_h.edit_buffer.parse::<f32>().unwrap_or(0.0)
+                } else {
+                    self.sidebar_h.value as f32
+                };
+                (nx2, ny2)
+            } else {
+                (0.0, 0.0)
+            };
+            let w_for_align = if is_vector { (v_x2 - x_val).abs() } else { w_val };
+            let h_for_align = if is_vector { (v_y2 - y_val).abs() } else { h_val };
             let size_val = if self.sidebar_size.editing {
                 self.sidebar_size.edit_buffer.parse::<f32>().unwrap_or(16.0)
             } else {
@@ -540,31 +1507,261 @@ impl LayoutApp {
             let g_val = self.slider_g.value();
             let b_val = self.slider_b.value();
 
-            let family_str = match self.dropdown_font_family.selected {
-                1 => "sans-serif",
-                2 => "serif",
-                _ => "monospace",
-            }.to_string();
+            let mut family_str = String::new();
+            if let Some(Element::Text { font_family, .. }) = self.elements.get(idx) {
+                family_str = font_family.clone();
+            }
+            if self.font_selector.take_change() {
+                family_str = self.font_selector.font_family.clone();
+            }
+            
+            let mut page_align_h = None;
+            if self.dropdown_align_h.take_change() {
+                page_align_h = Some(self.dropdown_align_h.selected);
+            }
+            let mut page_align_v = None;
+            if self.dropdown_align_v.take_change() {
+                page_align_v = Some(self.dropdown_align_v.selected);
+            }
+
+            let mut text_align_h = None;
+            if self.dropdown_text_align_h.take_change() {
+                text_align_h = Some(match self.dropdown_text_align_h.selected {
+                    1 => TextAlignH::Center,
+                    2 => TextAlignH::Right,
+                    _ => TextAlignH::Left,
+                });
+            }
+            let mut text_align_v = None;
+            if self.dropdown_text_align_v.take_change() {
+                text_align_v = Some(match self.dropdown_text_align_v.selected {
+                    1 => TextAlignV::Middle,
+                    2 => TextAlignV::Bottom,
+                    _ => TextAlignV::Top,
+                });
+            }
+
+            let mut final_x = x_val;
+            let mut final_y = y_val;
+
+            if let Some(sel_h) = page_align_h {
+                if sel_h == 1 {
+                    final_x = 0.0;
+                } else if sel_h == 2 {
+                    final_x = ((self.page_w - w_for_align) / 2.0).round();
+                } else if sel_h == 3 {
+                    final_x = (self.page_w - w_for_align).round();
+                }
+            }
+            if let Some(sel_v) = page_align_v {
+                if sel_v == 1 {
+                    final_y = 0.0;
+                } else if sel_v == 2 {
+                    final_y = ((self.page_h - h_for_align) / 2.0).round();
+                } else if sel_v == 3 {
+                    final_y = (self.page_h - h_for_align).round();
+                }
+            }
+
+            let mut final_x2 = v_x2;
+            let mut final_y2 = v_y2;
+            if is_vector {
+                let dx = final_x - x_val;
+                let dy = final_y - y_val;
+                final_x2 += dx;
+                final_y2 += dy;
+            }
             
             match &mut self.elements[idx] {
-                Element::Text { text, x, y, w, h, font_size, color, font_family } => {
+                Element::Text { text, x, y, w, h, font_size, color, font_family, align_h, align_v, multiline } => {
                     *text = text_val;
-                    *x = x_val;
-                    *y = y_val;
                     *w = w_val;
                     *h = h_val;
                     *font_size = size_val;
                     *color = [r_val, g_val, b_val, 1.0];
-                    *font_family = family_str;
+                    if !family_str.is_empty() {
+                        *font_family = family_str;
+                    }
+                    if let Some(ah) = text_align_h {
+                        *align_h = ah;
+                    }
+                    if let Some(av) = text_align_v {
+                        *align_v = av;
+                    }
+                    *multiline = self.toggle_multiline.toggled();
+                    *x = final_x;
+                    *y = final_y;
+                }
+                Element::Shape { shape_type: _, x, y, w, h, color } => {
+                    *w = w_val;
+                    *h = h_val;
+                    *color = [r_val, g_val, b_val, 1.0];
+                    *x = final_x;
+                    *y = final_y;
+                }
+                Element::Vector { x1, y1, x2, y2, stroke_width, color, line_cap } => {
+                    *x1 = final_x;
+                    *y1 = final_y;
+                    *x2 = final_x2;
+                    *y2 = final_y2;
+                    *stroke_width = size_val;
+                    *color = [r_val, g_val, b_val, 1.0];
+                    *line_cap = match self.dropdown_line_cap.selected {
+                        0 => LineCap::Arrow,
+                        1 => LineCap::Round,
+                        2 => LineCap::Flat,
+                        _ => LineCap::Arrow,
+                    };
+                }
+            }
+        }
+        self.rebuild_layers_tab_widgets();
+        self.sync_sidebar_fields();
+    }
+
+    fn active_page_widgets(&mut self) -> Vec<&mut dyn Widget> {
+        let mut list: Vec<&mut dyn Widget> = Vec::new();
+        match self.paginator.selected_page() {
+            0 => {
+                list.push(&mut self.btn_new_doc);
+                list.push(&mut self.btn_open);
+                list.push(&mut self.recent_files_list);
+                for btn in &mut self.recent_files_buttons {
+                    list.push(btn);
+                }
+                list.push(&mut self.btn_save);
+                list.push(&mut self.btn_save_as);
+                list.push(&mut self.btn_exit);
+            }
+            1 => {
+                list.push(&mut self.dropdown_margin_units);
+                list.push(&mut self.dropdown_presets);
+                list.push(&mut self.slider_page_x);
+                list.push(&mut self.slider_page_y);
+                list.push(&mut self.page_color_selector);
+                list.push(&mut self.toggle_margin);
+                list.push(&mut self.toggle_word_processor);
+                list.push(&mut self.slider_margin_x);
+                list.push(&mut self.slider_margin_y);
+            }
+            2 => {
+                if self.word_processor_enabled {
+                    list.push(&mut self.font_selector);
+                    list.push(&mut self.sidebar_size);
+                    list.push(&mut self.slider_r);
+                    list.push(&mut self.slider_g);
+                    list.push(&mut self.slider_b);
+                } else if self.selected_idx.is_some() {
+                    list.push(&mut self.dropdown_align_h);
+                    list.push(&mut self.dropdown_align_v);
+
+                    let (is_text, is_vector) = match self.selected_idx.map(|idx| &self.elements[idx]) {
+                        Some(Element::Text { .. }) => (true, false),
+                        Some(Element::Vector { .. }) => (false, true),
+                        _ => (false, false),
+                    };
+                    if is_text {
+                        list.push(&mut self.sidebar_x);
+                        list.push(&mut self.sidebar_y);
+                        list.push(&mut self.sidebar_w);
+                        list.push(&mut self.sidebar_h);
+                        list.push(&mut self.sidebar_text);
+                        list.push(&mut self.font_selector);
+                        list.push(&mut self.toggle_multiline);
+                        list.push(&mut self.dropdown_text_align_h);
+                        list.push(&mut self.dropdown_text_align_v);
+                        list.push(&mut self.sidebar_size);
+                        list.push(&mut self.slider_r);
+                        list.push(&mut self.slider_g);
+                        list.push(&mut self.slider_b);
+                    } else if is_vector {
+                        list.push(&mut self.sidebar_x);
+                        list.push(&mut self.sidebar_y);
+                        list.push(&mut self.sidebar_w);
+                        list.push(&mut self.sidebar_h);
+                        list.push(&mut self.sidebar_size);
+                        list.push(&mut self.dropdown_line_cap);
+                        list.push(&mut self.slider_r);
+                        list.push(&mut self.slider_g);
+                        list.push(&mut self.slider_b);
+                    } else {
+                        list.push(&mut self.sidebar_x);
+                        list.push(&mut self.sidebar_y);
+                        list.push(&mut self.sidebar_w);
+                        list.push(&mut self.sidebar_h);
+                        list.push(&mut self.slider_r);
+                        list.push(&mut self.slider_g);
+                        list.push(&mut self.slider_b);
+                    }
+                } else {
+                    list.push(&mut self.label_sel_status);
+                    list.push(&mut self.label_sel_desc1);
+                    list.push(&mut self.label_sel_desc2);
                 }
-                Element::Shape { shape_type: _, x, y, w, h, color } => {
-                    *x = x_val;
-                    *y = y_val;
-                    *w = w_val;
-                    *h = h_val;
-                    *color = [r_val, g_val, b_val, 1.0];
+            }
+            3 => {
+                list.push(&mut self.btn_add_text);
+                list.push(&mut self.btn_add_rect);
+                list.push(&mut self.btn_add_banner);
+                list.push(&mut self.btn_add_vector);
+                list.push(&mut self.label_total_elements);
+            }
+            4 => {
+                list.push(&mut self.toggle_grid);
+                list.push(&mut self.grid_color_selector);
+                list.push(&mut self.spinbox_grid_size);
+                list.push(&mut self.label_grid_snap);
+                list.push(&mut self.slider_zoom);
+                list.push(&mut self.toggle_rulers);
+                list.push(&mut self.dropdown_units);
+                list.push(&mut self.margin_color_selector);
+                list.push(&mut self.spinbox_margin_thickness);
+                list.push(&mut self.dropdown_grid_units);
+            }
+            5 => {
+                for btn in &mut self.layer_buttons {
+                    list.push(&mut **btn);
                 }
             }
+            _ => {}
+        }
+        list
+    }
+
+    pub fn get_current_document(&self) -> LayoutDocument {
+        LayoutDocument {
+            page_w: self.page_w,
+            page_h: self.page_h,
+            page_color: self.page_color,
+            margin_enabled: self.margin_enabled,
+            margin_x: self.margin_x,
+            margin_y: self.margin_y,
+            word_processor_enabled: self.word_processor_enabled,
+            wp_text: self.wp_text_box.text.clone(),
+            elements: self.elements.clone(),
+            grid_color: self.grid_color,
+            grid_size: self.spinbox_grid_size.value as f32 / 10.0,
+            margin_color: self.margin_color,
+            margin_thickness: self.margin_thickness,
+            grid_enabled: self.grid_enabled,
+            grid_units: self.dropdown_grid_units.selected,
+            zoom: self.slider_zoom.value(),
+            rulers_enabled: self.toggle_rulers.toggled(),
+            ruler_units: self.dropdown_units.selected,
+        }
+    }
+
+    pub fn has_unsaved_changes(&self) -> bool {
+        self.get_current_document() != self.last_saved_document
+    }
+
+    pub fn grid_spacing(&self) -> f32 {
+        match self.dropdown_grid_units.selected {
+            0 => 20.0,                    // Pixels
+            1 => 0.25 * 60.0,             // Inches
+            2 => 0.5 * 23.622047,         // Centimeters
+            3 => 5.0 * 2.3622047,         // Millimeters
+            _ => 20.0,
         }
     }
 }
@@ -573,71 +1770,32 @@ impl Application for LayoutApp {
     type Message = AppMessage;
 
     fn new(_qh: &QueueHandle<EngineState<Self>>, _sender: calloop::channel::Sender<Self::Message>) -> Self {
-        // Build the main MenuBar
-        let menu_bar = MenuBar::new(0.0, 0.0, 1024.0, 26.0)
-            .with_title("clear-layout")
-            .with_item("File", &["New Document", "Exit"])
-            .with_item("Insert", &["Add Text Box", "Add Rectangle", "Add Banner"])
-            .with_item("View", &["Toggle Grid"]);
+        clear_ui::scale::set_scale_factor(1.0);
+        let btn_new_doc = Button::new(0.0, 0.0, 240.0, 26.0).with_label("New Document");
+        let btn_open = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Open");
+        let btn_save = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Save");
+        let btn_save_as = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Save As");
+        let btn_exit = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Exit Application");
 
         // Build the sidebar Paginator
-        let paginator = Paginator::new(56.0, vec!["Page".to_string(), "Element".to_string(), "Canvas".to_string(), "View".to_string()])
+        let paginator = Paginator::new(56.0, vec![
+            "File".to_string(),
+            "Page".to_string(),
+            "Element".to_string(),
+            "Canvas".to_string(),
+            "Guides".to_string(),
+            "Layers".to_string(),
+        ])
             .with_tabs_at_top(false)
-            .with_tabs_rotated(true);
+            .with_tabs_rotated(true)
+            .with_sidebar_label("LAYOUT");
 
         // Default paper sheet sizing (Letter)
         let page_w = 510.0;
         let page_h = 660.0;
 
         // Initialize elements relative to the paper sheet top-left (0, 0)
-        let elements = vec![
-            Element::Text {
-                text: "Welcome to Clear Layout!".to_string(),
-                x: 40.0,
-                y: 50.0,
-                w: 400.0,
-                h: 40.0,
-                font_size: 20.0,
-                color: [0.3, 0.7, 1.0, 1.0],
-                font_family: "monospace".to_string(),
-            },
-            Element::Shape {
-                shape_type: ShapeType::Rectangle,
-                x: 40.0,
-                y: 100.0,
-                w: 430.0,
-                h: 4.0,
-                color: [0.2, 0.5, 0.9, 1.0],
-            },
-            Element::Text {
-                text: "This is a word processor and layout editor layout.".to_string(),
-                x: 40.0,
-                y: 130.0,
-                w: 430.0,
-                h: 30.0,
-                font_size: 14.0,
-                color: [0.8, 0.8, 0.85, 1.0],
-                font_family: "monospace".to_string(),
-            },
-            Element::Shape {
-                shape_type: ShapeType::Rectangle,
-                x: 40.0,
-                y: 190.0,
-                w: 120.0,
-                h: 80.0,
-                color: [0.15, 0.25, 0.4, 1.0],
-            },
-            Element::Text {
-                text: "Card Label".to_string(),
-                x: 50.0,
-                y: 205.0,
-                w: 100.0,
-                h: 20.0,
-                font_size: 11.0,
-                color: [0.9, 0.9, 0.9, 1.0],
-                font_family: "monospace".to_string(),
-            },
-        ];
+        let elements = vec![];
 
         // Create sidebar dropdown for page size presets
         let mut dropdown_presets = Dropdown::new(
@@ -668,15 +1826,53 @@ impl Application for LayoutApp {
             .with_text_color(Some([0x1a, 0x1a, 0x24]))
             .with_max_width(None);
 
-        let mut dropdown_font_family = Dropdown::new(
+        let mut font_selector = FontSelector::new("monospace".to_string()).with_label("Font");
+        font_selector.set_rect(0.0, 0.0, 240.0, 26.0);
+
+        let mut dropdown_text_align_h = Dropdown::new(
+            vec![
+                "Left".to_string(),
+                "Center".to_string(),
+                "Right".to_string(),
+            ],
+            0,
+        ).with_label("Horizontal Alignment");
+        dropdown_text_align_h.set_rect(0.0, 0.0, 240.0, 26.0);
+
+        let mut dropdown_text_align_v = Dropdown::new(
+            vec![
+                "Top".to_string(),
+                "Middle".to_string(),
+                "Bottom".to_string(),
+            ],
+            0,
+        ).with_label("Vertical Alignment");
+        dropdown_text_align_v.set_rect(0.0, 0.0, 240.0, 26.0);
+
+        let mut toggle_multiline = Toggle::new().with_label("Multiline Text");
+        toggle_multiline.set_rect(0.0, 0.0, 240.0, 26.0);
+
+        let mut dropdown_align_h = Dropdown::new(
+            vec![
+                "--".to_string(),
+                "Left".to_string(),
+                "Center".to_string(),
+                "Right".to_string(),
+            ],
+            0,
+        ).with_label("Horizontal Alignment");
+        dropdown_align_h.set_rect(0.0, 0.0, 240.0, 26.0);
+
+        let mut dropdown_align_v = Dropdown::new(
             vec![
-                "Monospace".to_string(),
-                "Sans-Serif".to_string(),
-                "Serif".to_string(),
+                "--".to_string(),
+                "Top".to_string(),
+                "Middle".to_string(),
+                "Bottom".to_string(),
             ],
             0,
-        ).with_label("Font Family");
-        dropdown_font_family.set_rect(0.0, 0.0, 240.0, 26.0);
+        ).with_label("Vertical Alignment");
+        dropdown_align_v.set_rect(0.0, 0.0, 240.0, 26.0);
 
         let mut dropdown_margin_units = Dropdown::new(
             vec![
@@ -694,15 +1890,25 @@ impl Application for LayoutApp {
         let mut slider_margin_y = Slider::new().with_range(0.0, 100.0).with_value(0.2).with_readout(true).with_label("Margin Height (Y)");
         slider_margin_y.set_rect(0.0, 0.0, 240.0, 18.0);
 
-        // Create sidebar textbox inputs
-        let mut sidebar_x = TextBox::new(String::new()).with_label("X Position");
-        sidebar_x.set_rect(0.0, 0.0, 110.0, 26.0);
-        let mut sidebar_y = TextBox::new(String::new()).with_label("Y Position");
-        sidebar_y.set_rect(0.0, 0.0, 110.0, 26.0);
-        let mut sidebar_w = TextBox::new(String::new()).with_label("Width");
-        sidebar_w.set_rect(0.0, 0.0, 110.0, 26.0);
-        let mut sidebar_h = TextBox::new(String::new()).with_label("Height");
-        sidebar_h.set_rect(0.0, 0.0, 110.0, 26.0);
+        // Create sidebar spinbox inputs
+        let mut sidebar_x = Spinbox::new(0, -2000, 2000, 1).with_label("X Position");
+        sidebar_x.set_rect(0.0, 0.0, 240.0, 26.0);
+        let mut sidebar_y = Spinbox::new(0, -2000, 2000, 1).with_label("Y Position");
+        sidebar_y.set_rect(0.0, 0.0, 240.0, 26.0);
+        let mut sidebar_w = Spinbox::new(100, -2000, 2000, 1).with_label("Width");
+        sidebar_w.set_rect(0.0, 0.0, 240.0, 26.0);
+        let mut sidebar_h = Spinbox::new(50, -2000, 2000, 1).with_label("Height");
+        sidebar_h.set_rect(0.0, 0.0, 240.0, 26.0);
+
+        let mut dropdown_line_cap = Dropdown::new(
+            vec![
+                "Arrow".to_string(),
+                "Round".to_string(),
+                "Flat".to_string(),
+            ],
+            0,
+        ).with_label("Line End Shape");
+        dropdown_line_cap.set_rect(0.0, 0.0, 240.0, 26.0);
         let mut sidebar_text = TextBox::new(String::new()).with_label("Text Content");
         sidebar_text.set_rect(0.0, 0.0, 240.0, 26.0);
         let mut sidebar_size = Spinbox::new(14, 4, 120, 1).with_label("Text Size");
@@ -719,11 +1925,33 @@ impl Application for LayoutApp {
         slider_zoom.set_rect(0.0, 0.0, 240.0, 18.0);
 
         // Page 1 Buttons
-        let btn_toggle_grid = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Toggle Grid");
-        let btn_clear_canvas = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Clear Canvas");
-        let btn_add_text = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Add Text Box");
-        let btn_add_rect = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Add Rectangle");
-        let btn_add_banner = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Add Banner");
+        let mut toggle_grid = Toggle::new().with_label("Toggle Grid");
+        toggle_grid.set_rect(0.0, 0.0, 240.0, 26.0);
+        toggle_grid.set_toggled(true);
+
+        let mut grid_color_selector = ColorSelector::new([51, 89, 153])
+            .with_label("Grid Color");
+        grid_color_selector.set_rect(0.0, 0.0, 240.0, 26.0);
+
+        let mut spinbox_grid_size = Spinbox::new(15, 5, 100, 1)
+            .with_decimals(1)
+            .with_label("Grid Dot Size (px)");
+        spinbox_grid_size.set_rect(0.0, 0.0, 240.0, 26.0);
+
+        let mut margin_color_selector = ColorSelector::new([51, 128, 217])
+            .with_label("Margin Guide Color");
+        margin_color_selector.set_rect(0.0, 0.0, 240.0, 26.0);
+
+        let mut spinbox_margin_thickness = Spinbox::new(1, 1, 20, 1)
+            .with_label("Margin Thickness (px)");
+        spinbox_margin_thickness.set_rect(0.0, 0.0, 240.0, 26.0);
+
+
+
+        let btn_add_text = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Text Box");
+        let btn_add_rect = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Rectangle");
+        let btn_add_banner = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Banner");
+        let btn_add_vector = Button::new(0.0, 0.0, 240.0, 26.0).with_label("Line");
 
         // Page 3 Buttons
         let mut toggle_rulers = Toggle::new().with_label("Show Rulers");
@@ -739,11 +1967,16 @@ impl Application for LayoutApp {
         ).with_label("Ruler Units");
         dropdown_units.set_rect(0.0, 0.0, 240.0, 26.0);
 
-        // Setup the new Label and SectionHeader widgets
-        let mut section_rulers = SectionHeader::new("RULERS");
-        section_rulers.set_rect(0.0, 0.0, 240.0, 26.0);
-
-
+        let mut dropdown_grid_units = Dropdown::new(
+            vec![
+                "Pixels (px)".to_string(),
+                "Inches (in)".to_string(),
+                "Centimeters (cm)".to_string(),
+                "Millimeters (mm)".to_string(),
+            ],
+            0,
+        ).with_label("Grid Units");
+        dropdown_grid_units.set_rect(0.0, 0.0, 240.0, 26.0);
 
         let mut label_sel_status = Label::new("No Selection").with_color([0x83, 0x83, 0x8a]);
         label_sel_status.set_rect(0.0, 0.0, 240.0, 18.0);
@@ -754,14 +1987,33 @@ impl Application for LayoutApp {
         let mut label_sel_desc2 = Label::new("to edit properties.").with_color([0x60, 0x60, 0x68]).with_font_size(10.0);
         label_sel_desc2.set_rect(0.0, 0.0, 240.0, 14.0);
 
-        let mut label_grid_snap = Label::new("Grid Snapping: ON (20px)");
-        label_grid_snap.set_rect(0.0, 0.0, 240.0, 18.0);
+        let mut label_grid_snap = Toggle::new().with_label("Grid Snapping: ON (20px)");
+        label_grid_snap.set_rect(0.0, 0.0, 240.0, 26.0);
+        label_grid_snap.set_toggled(true);
 
-        let mut label_total_elements = Label::new("Total Elements: 5");
+        let mut label_total_elements = Label::new("Total Elements: 0");
         label_total_elements.set_rect(0.0, 0.0, 240.0, 18.0);
 
+        let recent_files = Self::load_recent_files();
+        let recent_files_list = ScrollingList::new(22.0, 2.0);
+        let mut recent_files_buttons = Vec::new();
+        for file in &recent_files {
+            let label = file.file_name()
+                .map(|n| n.to_string_lossy().to_string())
+                .unwrap_or_else(|| file.to_string_lossy().to_string());
+            let btn = Button::new_list_row(0.0, 0.0, 0.0, 0.0).with_label(&label);
+            recent_files_buttons.push(btn);
+        }
+
         let mut app = Self {
-            menu_bar,
+            btn_new_doc,
+            btn_open,
+            recent_files,
+            recent_files_list,
+            recent_files_buttons,
+            btn_exit,
+            btn_save,
+            btn_save_as,
             paginator,
             elements,
             selected_idx: None,
@@ -795,7 +2047,13 @@ impl Application for LayoutApp {
             sidebar_h,
             sidebar_text,
             sidebar_size,
-            dropdown_font_family,
+            font_selector,
+            dropdown_text_align_h,
+            dropdown_text_align_v,
+            toggle_multiline,
+            dropdown_align_h,
+            dropdown_align_v,
+            dropdown_line_cap,
             wp_base_font_size: 14.0,
             
             slider_r,
@@ -803,16 +2061,23 @@ impl Application for LayoutApp {
             slider_b,
             slider_zoom,
  
-            btn_toggle_grid,
-            btn_clear_canvas,
+            toggle_grid,
+            grid_color_selector,
+            grid_color: [0.20, 0.35, 0.60, 0.8],
+            grid_size: 1.5,
+            spinbox_grid_size,
+            dropdown_grid_units,
+            margin_color_selector,
+            margin_color: [0.20, 0.50, 0.85, 0.35],
+            spinbox_margin_thickness,
+            margin_thickness: 1.0,
             btn_add_text,
             btn_add_rect,
             btn_add_banner,
+            btn_add_vector,
             toggle_rulers,
             dropdown_units,
 
-            section_rulers,
-
             label_sel_status,
             label_sel_desc1,
             label_sel_desc2,
@@ -824,10 +2089,32 @@ impl Application for LayoutApp {
             page_h,
             pan_x: 0.0,
             pan_y: 0.0,
-            widgets_registered: false,
+            sidebar_quads: Vec::new(),
+            current_file_path: None,
+            layer_buttons: Vec::new(),
+            last_saved_document: LayoutDocument {
+                page_w,
+                page_h,
+                page_color,
+                margin_enabled: false,
+                margin_x: 20.0,
+                margin_y: 20.0,
+                word_processor_enabled: false,
+                wp_text: String::new(),
+                elements: Vec::new(),
+                grid_color: [0.20, 0.35, 0.60, 0.8],
+                grid_size: 1.5,
+                margin_color: [0.20, 0.50, 0.85, 0.35],
+                margin_thickness: 1.0,
+                grid_enabled: true,
+                grid_units: 0,
+                zoom: 0.33333334,
+                rulers_enabled: false,
+                ruler_units: 0,
+            },
         };
 
-        app.rebuild_element_tab_widgets();
+        app.paginator.set_selected_page(2);
         app.sync_sidebar_fields();
         app.sync_page_units();
         app.rebuild_text_items();
@@ -835,8 +2122,19 @@ impl Application for LayoutApp {
     }
 
     fn settings(&self) -> WindowSettings {
+        let filename = match &self.current_file_path {
+            Some(path) => path.file_name()
+                .and_then(|n| n.to_str())
+                .unwrap_or("None"),
+            None => "None",
+        };
+        let unsaved_suffix = if self.has_unsaved_changes() {
+            " (Unsaved Changes)"
+        } else {
+            ""
+        };
         WindowSettings {
-            title: "Clear Layout Interface".to_string(),
+            title: format!("Clear Layout Interface - {}{}", filename, unsaved_suffix),
             app_id: "clear-layout-interface".to_string(),
             width: 1024,
             height: 768,
@@ -850,6 +2148,25 @@ impl Application for LayoutApp {
             AppMessage::Exit => {
                 *exit = true;
             }
+            AppMessage::Save => {
+                if let Some(ref path) = self.current_file_path {
+                    if let Err(e) = self.save_document(path) {
+                        eprintln!("ERROR: Failed to save document: {}", e);
+                    } else {
+                        println!("DEBUG: Successfully saved layout to {:?}", path);
+                        self.last_saved_document = self.get_current_document();
+                        self.add_recent_file(path.clone());
+                    }
+                } else {
+                    self.perform_save_as();
+                }
+            }
+            AppMessage::SaveAs => {
+                self.perform_save_as();
+            }
+            AppMessage::Open => {
+                self.perform_open();
+            }
             AppMessage::NewDocument => {
                 self.elements.clear();
                 self.selected_idx = None;
@@ -858,6 +2175,14 @@ impl Application for LayoutApp {
                 self.pan_y = 0.0;
                 self.page_color = [0.96, 0.96, 0.98, 1.0];
                 self.page_color_selector.color = [245, 245, 250];
+                self.grid_color = [0.20, 0.35, 0.60, 0.8];
+                self.grid_color_selector.color = [51, 89, 153];
+                self.grid_size = 1.5;
+                self.spinbox_grid_size.value = 15;
+                self.margin_color = [0.20, 0.50, 0.85, 0.35];
+                self.margin_color_selector.color = [51, 128, 217];
+                self.margin_thickness = 1.0;
+                self.spinbox_margin_thickness.value = 1;
                 self.margin_enabled = false;
                 self.margin_x = 20.0;
                 self.margin_y = 20.0;
@@ -874,14 +2199,25 @@ impl Application for LayoutApp {
                 self.dropdown_margin_units.selected = 0;
                 self.sync_page_units();
                 
+                self.grid_enabled = true;
+                self.toggle_grid.set_toggled(true);
+                self.label_grid_snap.set_toggled(true);
+                self.dropdown_grid_units.selected = 0;
+                self.slider_zoom.set_value(0.33333334);
+                self.toggle_rulers.set_toggled(false);
+                self.dropdown_units.selected = 0;
+                
                 self.toggle_word_processor.set_toggled(false);
                 self.word_processor_enabled = false;
                 self.wp_text_box.text = String::new();
                 self.wp_text_box.edit_buffer = String::new();
                 self.wp_text_box.editing = false;
 
-                self.rebuild_element_tab_widgets();
+                self.current_file_path = None;
+
+                self.rebuild_layers_tab_widgets();
                 self.sync_sidebar_fields();
+                self.last_saved_document = self.get_current_document();
                 *needs_rebuild = true;
                 self.needs_rebuild = true;
             }
@@ -896,9 +2232,12 @@ impl Application for LayoutApp {
                     font_size: 14.0,
                     color: [0.0, 0.0, 0.0, 1.0],
                     font_family: "monospace".to_string(),
+                    align_h: TextAlignH::Left,
+                    align_v: TextAlignV::Top,
+                    multiline: true,
                 });
                 self.selected_idx = Some(next_idx);
-                self.rebuild_element_tab_widgets();
+                self.rebuild_layers_tab_widgets();
                 self.sync_sidebar_fields();
                 *needs_rebuild = true;
                 self.needs_rebuild = true;
@@ -914,7 +2253,7 @@ impl Application for LayoutApp {
                     color: [0.2, 0.6, 0.4, 1.0],
                 });
                 self.selected_idx = Some(next_idx);
-                self.rebuild_element_tab_widgets();
+                self.rebuild_layers_tab_widgets();
                 self.sync_sidebar_fields();
                 *needs_rebuild = true;
                 self.needs_rebuild = true;
@@ -930,13 +2269,25 @@ impl Application for LayoutApp {
                     color: [0.8, 0.4, 0.2, 1.0],
                 });
                 self.selected_idx = Some(next_idx);
-                self.rebuild_element_tab_widgets();
+                self.rebuild_layers_tab_widgets();
                 self.sync_sidebar_fields();
                 *needs_rebuild = true;
                 self.needs_rebuild = true;
             }
-            AppMessage::ToggleGrid => {
-                self.grid_enabled = !self.grid_enabled;
+            AppMessage::AddVector => {
+                let next_idx = self.elements.len();
+                self.elements.push(Element::Vector {
+                    x1: 40.0,
+                    y1: 100.0,
+                    x2: 240.0,
+                    y2: 100.0,
+                    stroke_width: 4.0,
+                    color: [0.2, 0.4, 0.8, 1.0],
+                    line_cap: LineCap::Arrow,
+                });
+                self.selected_idx = Some(next_idx);
+                self.rebuild_layers_tab_widgets();
+                self.sync_sidebar_fields();
                 *needs_rebuild = true;
                 self.needs_rebuild = true;
             }
@@ -948,6 +2299,16 @@ impl Application for LayoutApp {
             *needs_rebuild = true;
             self.needs_rebuild = true;
         }
+        let mut widget_rebuild = false;
+        for w in self.active_page_widgets() {
+            if w.tick(dt) {
+                widget_rebuild = true;
+            }
+        }
+        if widget_rebuild {
+            *needs_rebuild = true;
+            self.needs_rebuild = true;
+        }
         let _ = self.page_color_selector.tick(dt);
         let r = self.page_color_selector.color[0] as f32 / 255.0;
         let g = self.page_color_selector.color[1] as f32 / 255.0;
@@ -959,6 +2320,66 @@ impl Application for LayoutApp {
             self.needs_rebuild = true;
         }
 
+        let mut new_grid_enabled = self.grid_enabled;
+        if self.toggle_grid.toggled() != self.grid_enabled {
+            new_grid_enabled = self.toggle_grid.toggled();
+        } else if self.label_grid_snap.toggled() != self.grid_enabled {
+            new_grid_enabled = self.label_grid_snap.toggled();
+        }
+
+        if self.grid_enabled != new_grid_enabled {
+            self.grid_enabled = new_grid_enabled;
+            self.toggle_grid.set_toggled(new_grid_enabled);
+            self.label_grid_snap.set_toggled(new_grid_enabled);
+            self.sync_sidebar_fields();
+            *needs_rebuild = true;
+            self.needs_rebuild = true;
+        }
+
+        let _ = self.grid_color_selector.tick(dt);
+        let gr = self.grid_color_selector.color[0] as f32 / 255.0;
+        let gg = self.grid_color_selector.color[1] as f32 / 255.0;
+        let gb = self.grid_color_selector.color[2] as f32 / 255.0;
+        let new_grid_col = [gr, gg, gb, 0.8];
+        if self.grid_color != new_grid_col {
+            self.grid_color = new_grid_col;
+            *needs_rebuild = true;
+            self.needs_rebuild = true;
+        }
+
+        let new_grid_size = if self.spinbox_grid_size.editing {
+            self.spinbox_grid_size.edit_buffer.parse::<f32>().unwrap_or(1.5)
+        } else {
+            self.spinbox_grid_size.value as f32 / 10.0
+        };
+        if self.grid_size != new_grid_size {
+            self.grid_size = new_grid_size;
+            *needs_rebuild = true;
+            self.needs_rebuild = true;
+        }
+
+        let _ = self.margin_color_selector.tick(dt);
+        let mr = self.margin_color_selector.color[0] as f32 / 255.0;
+        let mg = self.margin_color_selector.color[1] as f32 / 255.0;
+        let mb = self.margin_color_selector.color[2] as f32 / 255.0;
+        let new_margin_col = [mr, mg, mb, 0.35];
+        if self.margin_color != new_margin_col {
+            self.margin_color = new_margin_col;
+            *needs_rebuild = true;
+            self.needs_rebuild = true;
+        }
+
+        let new_margin_thickness = if self.spinbox_margin_thickness.editing {
+            self.spinbox_margin_thickness.edit_buffer.parse::<f32>().unwrap_or(1.0)
+        } else {
+            self.spinbox_margin_thickness.value as f32
+        };
+        if self.margin_thickness != new_margin_thickness {
+            self.margin_thickness = new_margin_thickness;
+            *needs_rebuild = true;
+            self.needs_rebuild = true;
+        }
+
         // Preset dropdown selection change
         if self.dropdown_presets.take_change() {
             let sel = self.dropdown_presets.selected;
@@ -989,6 +2410,13 @@ impl Application for LayoutApp {
             self.needs_rebuild = true;
         }
 
+        // Grid units dropdown change
+        if self.dropdown_grid_units.take_change() {
+            self.sync_sidebar_fields();
+            *needs_rebuild = true;
+            self.needs_rebuild = true;
+        }
+
         let unit_idx = self.dropdown_margin_units.selected;
         let px_per_unit = match unit_idx {
             0 => 1.0,           // Pixels
@@ -1047,7 +2475,6 @@ impl Application for LayoutApp {
             } else {
                 self.wp_text_box.unfocus();
             }
-            self.rebuild_element_tab_widgets();
             self.sync_sidebar_fields();
             *needs_rebuild = true;
             self.needs_rebuild = true;
@@ -1057,72 +2484,36 @@ impl Application for LayoutApp {
     fn view(&mut self, quads: &mut Vec<(f32, f32, f32, f32, [f32; 4])>, size: LogicalSize, scale: f64) {
         let size_changed = self.width != size.width as u32 || self.height != size.height as u32 || self.scale_factor != scale;
         if self.needs_rebuild || size_changed {
-            if !self.widgets_registered {
-                let self_ptr = self as *mut Self;
-                unsafe {
-                    (*self_ptr).paginator.add_widget_to_page(0, &mut (*self_ptr).dropdown_margin_units as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(0, &mut (*self_ptr).dropdown_presets as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(0, &mut (*self_ptr).slider_page_x as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(0, &mut (*self_ptr).slider_page_y as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(0, &mut (*self_ptr).page_color_selector as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(0, &mut (*self_ptr).toggle_margin as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(0, &mut (*self_ptr).toggle_word_processor as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(0, &mut (*self_ptr).slider_margin_x as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(0, &mut (*self_ptr).slider_margin_y as *mut (dyn Widget + 'static));
-
-
-                    // Page 1 (Element) widgets are registered dynamically via rebuild_element_tab_widgets()
-
-                    (*self_ptr).paginator.add_widget_to_page(2, &mut (*self_ptr).btn_toggle_grid as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(2, &mut (*self_ptr).btn_clear_canvas as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(2, &mut (*self_ptr).btn_add_text as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(2, &mut (*self_ptr).btn_add_rect as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(2, &mut (*self_ptr).btn_add_banner as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(2, &mut (*self_ptr).label_grid_snap as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(2, &mut (*self_ptr).label_total_elements as *mut (dyn Widget + 'static));
-
-                    (*self_ptr).paginator.add_widget_to_page(3, &mut (*self_ptr).slider_zoom as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(3, &mut (*self_ptr).section_rulers as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(3, &mut (*self_ptr).toggle_rulers as *mut (dyn Widget + 'static));
-                    (*self_ptr).paginator.add_widget_to_page(3, &mut (*self_ptr).dropdown_units as *mut (dyn Widget + 'static));
-                }
-                self.widgets_registered = true;
-            }
-
             self.width = size.width as u32;
             self.height = size.height as u32;
             self.scale_factor = scale;
             
-            // Layout MenuBar at the top
-            self.menu_bar.set_rect(0.0, 0.0, size.width, 26.0);
-            
             // Set paginator bounds in the sidebar region
-            self.paginator.set_rect(0.0, 26.0, 280.0, size.height - 26.0);
+            clear_ui::scale::set_scale_factor(scale as f32);
+            self.paginator.set_rect(0.0, 0.0, 280.0, size.height as f32);
             
+            self.rebuild_layers_tab_widgets();
             self.rebuild_text_items();
             self.needs_rebuild = false;
         }
  
-        // 1. Render Paginator Sidebar (includes backgrounds and active tab sliding container)
-        quads.extend(self.paginator.extra_quads());
-        if let Some(hq) = self.paginator.highlight_quad() {
-            quads.push(hq);
-        }
- 
-        // Divider between Sidebar and Canvas
-        quads.push((280.0, 26.0, 1.0, self.height as f32 - 26.0, [0.20, 0.20, 0.25, 1.0]));
+
 
         // 3. Render Canvas & centered paper sheet
         let canvas_w = self.width as f32 - 280.0;
-        let canvas_h = self.height as f32 - 26.0;
+        let canvas_h = self.height as f32;
         let zoom = self.render_zoom();
         
         // Centered Paper Position
         let page_x = 280.0 + (canvas_w - self.page_w * zoom) / 2.0 + self.pan_x;
-        let page_y = 26.0 + (canvas_h - self.page_h * zoom) / 2.0 + self.pan_y;
+        let page_y = (canvas_h - self.page_h * zoom) / 2.0 + self.pan_y;
 
         // Dark slate canvas backdrop
-        quads.push((280.0, 26.0, canvas_w, canvas_h, [0.12, 0.12, 0.15, 1.0]));
+        let mut canvas_bg = [0.12, 0.12, 0.15, 1.0];
+        if let Some(opacity) = clear_ui::color::read_opacity_if_configured() {
+            canvas_bg[3] = opacity;
+        }
+        quads.push((280.0, 0.0, canvas_w, canvas_h, canvas_bg));
 
         // Axis Rulers
         if self.toggle_rulers.toggled() {
@@ -1201,23 +2592,24 @@ impl Application for LayoutApp {
             let mw = (self.page_w - 2.0 * self.margin_x) * zoom;
             let mh = (self.page_h - 2.0 * self.margin_y) * zoom;
             if mw > 0.0 && mh > 0.0 {
-                let margin_col = [0.20, 0.50, 0.85, 0.35]; // Translucent blue margin line
-                quads.push((mx, my, mw, 1.0, margin_col));
-                quads.push((mx, my + mh - 1.0, mw, 1.0, margin_col));
-                quads.push((mx, my, 1.0, mh, margin_col));
-                quads.push((mx + mw - 1.0, my, 1.0, mh, margin_col));
+                let margin_col = self.margin_color;
+                let thick = self.margin_thickness;
+                quads.push((mx, my, mw, thick, margin_col));
+                quads.push((mx, my + mh - thick, mw, thick, margin_col));
+                quads.push((mx, my, thick, mh, margin_col));
+                quads.push((mx + mw - thick, my, thick, mh, margin_col));
             }
         }
 
         // 4. Snapping Grid inside the paper bounds
         if self.grid_enabled {
-            let spacing = 20.0 * zoom;
-            let dot_color = [0.20, 0.35, 0.60, 0.22];
+            let spacing = self.grid_spacing() * zoom;
             let mut cx = spacing;
+            let dot_size = (self.grid_size * zoom).max(1.0);
             while cx < self.page_w * zoom {
                 let mut cy = spacing;
                 while cy < self.page_h * zoom {
-                    quads.push((page_x + cx, page_y + cy, 1.5, 1.5, dot_color));
+                    quads.push((page_x + cx, page_y + cy, dot_size, dot_size, self.grid_color));
                     cy += spacing;
                 }
                 cx += spacing;
@@ -1267,6 +2659,7 @@ impl Application for LayoutApp {
                             }
                         }
                     }
+                    Element::Vector { .. } => {}
                 }
 
                 // Draw highlight border if selected
@@ -1274,6 +2667,13 @@ impl Application for LayoutApp {
                     let (ex, ey, ew, eh) = match element {
                         Element::Text { x, y, w, h, .. } => (*x, *y, *w, *h),
                         Element::Shape { x, y, w, h, .. } => (*x, *y, *w, *h),
+                        Element::Vector { x1, y1, x2, y2, .. } => {
+                            let x = x1.min(*x2);
+                            let y = y1.min(*y2);
+                            let w = (x1 - x2).abs();
+                            let h = (y1 - y2).abs();
+                            (x, y, w, h)
+                        }
                     };
                     let sel_col = [0.15, 0.45, 0.90, 1.0]; // Bright neon blue
                     quads.push((page_x + ex * zoom - 1.0, page_y + ey * zoom - 1.0, ew * zoom + 2.0, 1.0, sel_col));
@@ -1299,26 +2699,37 @@ impl Application for LayoutApp {
             }
         }
 
-        // Render Paginator active page popovers (e.g. presets and units dropdowns)
-        // This is done near the end of view() to ensure popovers overlap canvas elements
-        let mut collector = clear_ui::layout::PopoverCollector::new();
-        self.paginator.render_popover(&mut collector);
-        for (color, x, y, w, h) in collector.rects {
-            quads.push((x, y, w, h, color));
+        // Render Paginator Sidebar (includes backgrounds and active tab sliding container)
+        quads.extend(self.paginator.extra_quads());
+        if let Some(hq) = self.paginator.highlight_quad() {
+            quads.push(hq);
         }
+        quads.extend(self.sidebar_quads.iter().cloned());
 
-        // 6. MenuBar Background
-        let mb_color = self.menu_bar.color();
-        let (mb_x, mb_y, mb_w, mb_h) = self.menu_bar.rect();
-        quads.push((mb_x, mb_y, mb_w, mb_h, mb_color));
+        // Divider between Sidebar and Canvas
+        quads.push((280.0, 0.0, 1.0, self.height as f32, [0.20, 0.20, 0.25, 1.0]));
+    }
 
-        // Header Highlights for Open Menus
-        for menu in &self.menu_bar.menus {
-            if let Some(hq) = menu.highlight_quad() {
-                quads.push(hq);
+    fn view_vectors(&mut self, vectors: &mut Vec<(f32, f32, f32, f32, f32, [f32; 4], LineCap)>, _size: LogicalSize, _scale: f64) {
+        if self.word_processor_enabled {
+            return;
+        }
+        let zoom = self.render_zoom();
+        let canvas_w = self.width as f32 - 280.0;
+        let canvas_h = self.height as f32;
+        let page_x = 280.0 + (canvas_w - self.page_w * zoom) / 2.0 + self.pan_x;
+        let page_y = (canvas_h - self.page_h * zoom) / 2.0 + self.pan_y;
+
+        for element in &self.elements {
+            if let Element::Vector { x1, y1, x2, y2, stroke_width, color, line_cap } = element {
+                let vx1 = page_x + *x1 * zoom;
+                let vy1 = page_y + *y1 * zoom;
+                let vx2 = page_x + *x2 * zoom;
+                let vy2 = page_y + *y2 * zoom;
+                let vthickness = *stroke_width * zoom;
+                vectors.push((vx1, vy1, vx2, vy2, vthickness, *color, *line_cap));
             }
         }
-        quads.extend(self.menu_bar.extra_quads());
     }
 
     fn text_items(&self) -> &[TextItem] {
@@ -1330,58 +2741,67 @@ impl Application for LayoutApp {
         let px = pos.x as f32;
         let py = pos.y as f32;
 
-        if self.menu_bar.is_menu_open() || self.menu_bar.hit_test(px, py) {
-            if self.menu_bar.on_cursor_moved(px, py) {
-                changed = true;
+        let sidebar_w = 280.0;
+        if px < sidebar_w {
+            if self.paginator.cursor_moved(px, py) { changed = true; }
+            for w in self.active_page_widgets() {
+                if w.cursor_moved(px, py) { changed = true; }
+            }
+            if self.paginator.selected_page() == 2 && changed {
+                self.apply_sidebar_changes();
             }
         } else {
-            let sidebar_w = 280.0;
-            if px < sidebar_w {
-                if self.paginator.on_cursor_moved(px, py) { changed = true; }
-                if self.paginator.selected_page() == 1 && changed {
-                    self.apply_sidebar_changes();
+            // Clear hover state on sidebar widgets if mouse moves to canvas
+            if self.paginator.cursor_moved(px, py) { changed = true; }
+            for w in self.active_page_widgets() {
+                if w.cursor_moved(px, py) { changed = true; }
+            }
+
+            // Compute centering coordinates for canvas elements
+            let canvas_w = self.width as f32 - 280.0;
+            let canvas_h = self.height as f32;
+            let zoom = self.render_zoom();
+            let page_w = self.page_w * zoom;
+            let page_h = self.page_h * zoom;
+            let page_x = 280.0 + (canvas_w - page_w) / 2.0 + self.pan_x;
+            let page_y = (canvas_h - page_h) / 2.0 + self.pan_y;
+            
+            let cx = (px - page_x) / zoom;
+            let cy = (py - page_y) / zoom;
+
+            if self.word_processor_enabled {
+                if self.wp_text_box.on_cursor_moved(px, py) {
+                    changed = true;
                 }
-            } else {
-                // Compute centering coordinates for canvas elements
-                let canvas_w = self.width as f32 - 280.0;
-                let canvas_h = self.height as f32 - 26.0;
-                let zoom = self.render_zoom();
-                let page_w = self.page_w * zoom;
-                let page_h = self.page_h * zoom;
-                let page_x = 280.0 + (canvas_w - page_w) / 2.0 + self.pan_x;
-                let page_y = 26.0 + (canvas_h - page_h) / 2.0 + self.pan_y;
+            } else if let Some((idx, ox, oy)) = self.dragging {
+                let mut new_x = cx - ox;
+                let mut new_y = cy - oy;
                 
-                let cx = (px - page_x) / zoom;
-                let cy = (py - page_y) / zoom;
-
-                if self.word_processor_enabled {
-                    if self.wp_text_box.on_cursor_moved(px, py) {
-                        changed = true;
+                if self.grid_enabled {
+                    let spacing = self.grid_spacing();
+                    new_x = (new_x / spacing).round() * spacing;
+                    new_y = (new_y / spacing).round() * spacing;
+                }
+                
+                match &mut self.elements[idx] {
+                    Element::Text { x, y, .. } => {
+                        *x = new_x;
+                        *y = new_y;
                     }
-                } else if let Some((idx, ox, oy)) = self.dragging {
-                    let mut new_x = cx - ox;
-                    let mut new_y = cy - oy;
-                    
-                    if self.grid_enabled {
-                        new_x = (new_x / 20.0).round() * 20.0;
-                        new_y = (new_y / 20.0).round() * 20.0;
+                    Element::Shape { x, y, .. } => {
+                        *x = new_x;
+                        *y = new_y;
                     }
-                    
-                    match &mut self.elements[idx] {
-                        Element::Text { x, y, .. } => {
-                            *x = new_x;
-                            *y = new_y;
-                        }
-                        Element::Shape { x, y, .. } => {
-                            *x = new_x;
-                            *y = new_y;
-                        }
+                    Element::Vector { x1, y1, x2, y2, .. } => {
+                        let dx = new_x - *x1;
+                        let dy = new_y - *y1;
+                        *x1 = new_x;
+                        *y1 = new_y;
+                        *x2 += dx;
+                        *y2 += dy;
                     }
-                    self.sync_sidebar_fields();
-                    changed = true;
                 }
-            }
-            if self.menu_bar.on_cursor_moved(px, py) {
+                self.sync_sidebar_fields();
                 changed = true;
             }
         }
@@ -1398,130 +2818,206 @@ impl Application for LayoutApp {
         let px = pos.x as f32;
         let py = pos.y as f32;
 
-        if self.menu_bar.is_menu_open() || self.menu_bar.hit_test(px, py) {
-            if self.menu_bar.mouse_input(button, state, px, py) {
+        let sidebar_w = 280.0;
+        if px < sidebar_w {
+            let old_page = self.paginator.selected_page();
+            let pag_mouse = self.paginator.mouse_input(button, state, px, py);
+            if pag_mouse {
                 changed = true;
-                if let Some((menu_idx, item_idx)) = self.menu_bar.menu_click() {
-                    match (menu_idx, item_idx) {
-                        (0, 0) => msg_out = Some(AppMessage::NewDocument),
-                        (0, 1) => msg_out = Some(AppMessage::Exit),
-                        (1, 0) => msg_out = Some(AppMessage::AddText),
-                        (1, 1) => msg_out = Some(AppMessage::AddRectangle),
-                        (1, 2) => msg_out = Some(AppMessage::AddBanner),
-                        (2, 0) => msg_out = Some(AppMessage::ToggleGrid),
-                        _ => {}
+                if self.paginator.take_click() {
+                    let new_page = self.paginator.selected_page();
+                    self.paginator.set_selected_page(old_page);
+                    for w in self.active_page_widgets() {
+                        w.unfocus();
                     }
+                    self.apply_sidebar_changes();
+                    self.paginator.set_selected_page(new_page);
                 }
-            }
-            if state == ElementState::Pressed && !self.menu_bar.hit_test(px, py) {
-                self.menu_bar.unfocus();
-                changed = true;
-            }
-        } else {
-            let sidebar_w = 280.0;
-            if px < sidebar_w {
-                if self.paginator.mouse_input(button, state, px, py) {
-                    changed = true;
-                    if self.paginator.take_click() {
-                        self.dropdown_presets.unfocus();
-                        self.slider_page_x.unfocus();
-                        self.slider_page_y.unfocus();
-                        self.dropdown_units.unfocus();
-                        self.page_color_selector.unfocus();
-                        self.toggle_margin.unfocus();
-                        self.toggle_word_processor.unfocus();
-                        self.dropdown_margin_units.unfocus();
-                        self.slider_margin_x.unfocus();
-                        self.slider_margin_y.unfocus();
-                        self.sidebar_x.unfocus();
-                        self.sidebar_y.unfocus();
-                        self.sidebar_w.unfocus();
-                        self.sidebar_h.unfocus();
-                        self.sidebar_text.unfocus();
-                        self.sidebar_size.unfocus();
-                    } else {
-                        let active_page = self.paginator.selected_page();
-                        if active_page == 0 {
-                            let _ = self.toggle_margin.take_click();
-                            let _ = self.toggle_word_processor.take_click();
-                        } else if active_page == 1 {
-                            self.apply_sidebar_changes();
-                        } else if active_page == 2 {
-                            if state == ElementState::Released {
-                                if self.btn_toggle_grid.take_click() {
-                                    msg_out = Some(AppMessage::ToggleGrid);
-                                }
-                                if self.btn_clear_canvas.take_click() {
-                                    msg_out = Some(AppMessage::NewDocument);
-                                }
-                                if self.btn_add_text.take_click() {
-                                    msg_out = Some(AppMessage::AddText);
-                                }
-                                if self.btn_add_rect.take_click() {
-                                    msg_out = Some(AppMessage::AddRectangle);
-                                }
-                                if self.btn_add_banner.take_click() {
-                                    msg_out = Some(AppMessage::AddBanner);
-                                }
+            } else {
+                if state == ElementState::Pressed {
+                    let mut hit_any = false;
+                    let mut widgets = self.active_page_widgets();
+                    let mut focus_idx = None;
+                    for (idx, w) in widgets.iter().enumerate() {
+                        if w.hit_test(px, py) {
+                            focus_idx = Some(idx);
+                            hit_any = true;
+                            break;
+                        }
+                    }
+                    if hit_any {
+                        for (idx, w) in widgets.iter_mut().enumerate() {
+                            if Some(idx) == focus_idx {
+                                w.focus();
+                            } else {
+                                w.unfocus();
                             }
-                        } else if active_page == 3 {
-                            let _ = self.toggle_rulers.take_click();
+                        }
+                    } else {
+                        for w in widgets.iter_mut() {
+                            w.unfocus();
                         }
                     }
                 }
-            } else {
-                // Compute centering coordinates for canvas elements
-                let canvas_w = self.width as f32 - 280.0;
-                let canvas_h = self.height as f32 - 26.0;
-                let zoom = self.render_zoom();
-                let page_w = self.page_w * zoom;
-                let page_h = self.page_h * zoom;
-                let page_x = 280.0 + (canvas_w - page_w) / 2.0 + self.pan_x;
-                let page_y = 26.0 + (canvas_h - page_h) / 2.0 + self.pan_y;
-                
-                let cx = (px - page_x) / zoom;
-                let cy = (py - page_y) / zoom;
 
-                if self.word_processor_enabled {
-                    if self.wp_text_box.mouse_input(button, state, px, py) {
-                        changed = true;
-                    } else if state == ElementState::Pressed {
-                        self.wp_text_box.unfocus();
+                for w in self.active_page_widgets() {
+                    if w.mouse_input(button, state, px, py) {
                         changed = true;
                     }
-                } else if state == ElementState::Pressed {
-                    let mut found = None;
-                    for (idx, element) in self.elements.iter().enumerate().rev() {
-                        let (ex, ey, ew, eh) = match element {
-                            Element::Text { x, y, w, h, .. } => (*x, *y, *w, *h),
-                            Element::Shape { x, y, w, h, .. } => (*x, *y, *w, *h),
-                        };
-                        if cx >= ex && cx <= ex + ew && cy >= ey && cy <= ey + eh {
-                            found = Some(idx);
-                            break;
+                }
+
+                if self.paginator.selected_page() == 2 {
+                    self.apply_sidebar_changes();
+                }
+
+                let active_page = self.paginator.selected_page();
+                if active_page == 0 {
+                    if state == ElementState::Released {
+                        if self.btn_new_doc.take_click() {
+                            msg_out = Some(AppMessage::NewDocument);
+                        }
+                        if self.btn_open.take_click() {
+                            msg_out = Some(AppMessage::Open);
+                        }
+                        let mut clicked_file = None;
+                        for (i, btn) in self.recent_files_buttons.iter_mut().enumerate() {
+                            if btn.take_click() {
+                                clicked_file = Some(self.recent_files[i].clone());
+                            }
+                        }
+                        if let Some(path) = clicked_file {
+                            self.selected_idx = None;
+                            self.dragging = None;
+                            self.pan_x = 0.0;
+                            self.pan_y = 0.0;
+                            if let Err(e) = self.load_document(&path) {
+                                eprintln!("ERROR: Failed to load document: {}", e);
+                            } else {
+                                println!("DEBUG: Successfully loaded layout from {:?}", path);
+                                self.current_file_path = Some(path.clone());
+                                self.last_saved_document = self.get_current_document();
+                                self.add_recent_file(path);
+                            }
+                        }
+                        if self.btn_save.take_click() {
+                            msg_out = Some(AppMessage::Save);
+                        }
+                        if self.btn_save_as.take_click() {
+                            msg_out = Some(AppMessage::SaveAs);
+                        }
+                        if self.btn_exit.take_click() {
+                            msg_out = Some(AppMessage::Exit);
+                        }
+                    }
+                } else if active_page == 1 {
+                    let _ = self.toggle_margin.take_click();
+                    let _ = self.toggle_word_processor.take_click();
+
+                } else if active_page == 3 {
+                    if state == ElementState::Released {
+                        if self.btn_add_text.take_click() {
+                            msg_out = Some(AppMessage::AddText);
+                        }
+                        if self.btn_add_rect.take_click() {
+                            msg_out = Some(AppMessage::AddRectangle);
+                        }
+                        if self.btn_add_banner.take_click() {
+                            msg_out = Some(AppMessage::AddBanner);
+                        }
+                        if self.btn_add_vector.take_click() {
+                            msg_out = Some(AppMessage::AddVector);
+                        }
+                    }
+                } else if active_page == 4 {
+                    let _ = self.toggle_grid.take_click();
+                    let _ = self.grid_color_selector.take_click();
+                    let _ = self.label_grid_snap.take_click();
+                    let _ = self.toggle_rulers.take_click();
+                    let _ = self.margin_color_selector.take_click();
+                } else if active_page == 5 {
+                    if state == ElementState::Released {
+                        let mut clicked_idx = None;
+                        for (idx, btn) in self.layer_buttons.iter_mut().enumerate() {
+                            if btn.take_click() {
+                                clicked_idx = Some(idx);
+                            }
+                        }
+                        if let Some(idx) = clicked_idx {
+                            self.selected_idx = Some(idx);
+                            self.sync_sidebar_fields();
+                            self.rebuild_layers_tab_widgets();
+                            changed = true;
                         }
                     }
+                }
+            }
+        } else {
+            // Compute centering coordinates for canvas elements
+            let canvas_w = self.width as f32 - 280.0;
+            let canvas_h = self.height as f32;
+            let zoom = self.render_zoom();
+            let page_w = self.page_w * zoom;
+            let page_h = self.page_h * zoom;
+            let page_x = 280.0 + (canvas_w - page_w) / 2.0 + self.pan_x;
+            let page_y = (canvas_h - page_h) / 2.0 + self.pan_y;
+            
+            let cx = (px - page_x) / zoom;
+            let cy = (py - page_y) / zoom;
 
-                    if let Some(idx) = found {
-                        self.selected_idx = Some(idx);
-                        let (ex, ey) = match &self.elements[idx] {
-                            Element::Text { x, y, .. } => (*x, *y),
-                            Element::Shape { x, y, .. } => (*x, *y),
-                        };
-                        self.dragging = Some((idx, cx - ex, cy - ey));
-                        self.rebuild_element_tab_widgets();
-                        self.sync_sidebar_fields();
-                        changed = true;
-                    } else {
-                        self.selected_idx = None;
-                        self.dragging = None;
-                        self.rebuild_element_tab_widgets();
-                        self.sync_sidebar_fields();
-                        changed = true;
+            if self.word_processor_enabled {
+                if self.wp_text_box.mouse_input(button, state, px, py) {
+                    changed = true;
+                } else if state == ElementState::Pressed {
+                    self.wp_text_box.unfocus();
+                    changed = true;
+                }
+            } else if state == ElementState::Pressed {
+                let mut found = None;
+                for (idx, element) in self.elements.iter().enumerate().rev() {
+                    match element {
+                        Element::Text { x, y, w, h, .. } => {
+                            if cx >= *x && cx <= *x + *w && cy >= *y && cy <= *y + *h {
+                                found = Some(idx);
+                                break;
+                            }
+                        }
+                        Element::Shape { x, y, w, h, .. } => {
+                            if cx >= *x && cx <= *x + *w && cy >= *y && cy <= *y + *h {
+                                found = Some(idx);
+                                break;
+                            }
+                        }
+                        Element::Vector { x1, y1, x2, y2, stroke_width, .. } => {
+                            let dist = point_to_line_segment_distance(cx, cy, *x1, *y1, *x2, *y2);
+                            let select_tolerance = (stroke_width * 1.5).max(10.0);
+                            if dist <= select_tolerance {
+                                found = Some(idx);
+                                break;
+                            }
+                        }
                     }
-                } else if state == ElementState::Released {
+                }
+
+                if let Some(idx) = found {
+                    self.selected_idx = Some(idx);
+                    let (ex, ey) = match &self.elements[idx] {
+                        Element::Text { x, y, .. } => (*x, *y),
+                        Element::Shape { x, y, .. } => (*x, *y),
+                        Element::Vector { x1, y1, .. } => (*x1, *y1),
+                    };
+                    self.dragging = Some((idx, cx - ex, cy - ey));
+                    self.rebuild_layers_tab_widgets();
+                    self.sync_sidebar_fields();
+                    changed = true;
+                } else {
+                    self.selected_idx = None;
                     self.dragging = None;
+                    self.rebuild_layers_tab_widgets();
+                    self.sync_sidebar_fields();
+                    changed = true;
                 }
+            } else if state == ElementState::Released {
+                self.dragging = None;
             }
         }
 
@@ -1537,8 +3033,17 @@ impl Application for LayoutApp {
         let px = pos.x as f32;
         let py = pos.y as f32;
         if px < 280.0 {
+            let mut wheel_handled = false;
+            for w in self.active_page_widgets() {
+                if w.mouse_wheel(delta, px, py) {
+                    wheel_handled = true;
+                }
+            }
             if self.paginator.mouse_wheel(delta, px, py) {
-                if self.paginator.selected_page() == 1 {
+                wheel_handled = true;
+            }
+            if wheel_handled {
+                if self.paginator.selected_page() == 2 {
                     self.apply_sidebar_changes();
                 }
                 *needs_rebuild = true;
@@ -1557,6 +3062,16 @@ impl Application for LayoutApp {
     }
 
     fn handle_key_input(&mut self, event: &KeyEvent, needs_rebuild: &mut bool) -> Option<Self::Message> {
+        if event.state == ElementState::Pressed && event.ctrl {
+            if let Key::Character(ref s) = event.logical_key {
+                if s == "s" || s == "S" || s == "\u{13}" || s == "\x13" {
+                    *needs_rebuild = true;
+                    self.needs_rebuild = true;
+                    return Some(AppMessage::Save);
+                }
+            }
+        }
+
         let mut handled = false;
         
         if self.word_processor_enabled {
@@ -1565,14 +3080,37 @@ impl Application for LayoutApp {
             }
         }
 
+        for w in self.active_page_widgets() {
+            if w.focused() {
+                if w.keyboard_input(event) {
+                    handled = true;
+                }
+            }
+        }
+
         if self.paginator.keyboard_input(event) {
             handled = true;
             let active_page = self.paginator.selected_page();
-            if active_page == 1 {
+            if active_page == 2 {
                 self.apply_sidebar_changes();
             }
         }
 
+        if !handled && !self.word_processor_enabled && event.state == ElementState::Pressed {
+            if let Key::Named(NamedKey::Delete) = event.logical_key {
+                if let Some(idx) = self.selected_idx {
+                    if idx < self.elements.len() {
+                        self.elements.remove(idx);
+                        self.selected_idx = None;
+                        self.dragging = None;
+                        self.rebuild_layers_tab_widgets();
+                        self.sync_sidebar_fields();
+                        handled = true;
+                    }
+                }
+            }
+        }
+
         if handled {
             *needs_rebuild = true;
             self.needs_rebuild = true;