fn build_display_pane(title: &str, capture_path: &str) -> DisplayPaneWidgets {
    let root = gtk::Box::new(gtk::Orientation::Vertical, 10);
    root.add_css_class("display-card");
    root.set_hexpand(true);
    root.set_vexpand(false);

    let stream_status = gtk::Label::new(Some("Preview pending"));
    stream_status.add_css_class("status-line");
    stream_status.add_css_class("eye-inline-status");
    stream_status.set_halign(gtk::Align::Center);
    stream_status.set_valign(gtk::Align::Center);
    stream_status.set_hexpand(true);
    stream_status.set_xalign(0.5);
    stream_status.set_ellipsize(pango::EllipsizeMode::End);
    stream_status.set_single_line_mode(true);
    stream_status.set_width_chars(10);
    stream_status.set_max_width_chars(18);
    stream_status.set_tooltip_text(Some("Eye stream status."));

    let header_row = gtk::Box::new(gtk::Orientation::Horizontal, 8);
    header_row.set_hexpand(true);
    let title_label = gtk::Label::new(Some(title));
    title_label.add_css_class("title-4");
    title_label.set_halign(gtk::Align::Start);
    title_label.set_hexpand(true);
    let capture_label = gtk::Label::new(Some(capture_path));
    capture_label.add_css_class("dim-label");
    capture_label.set_halign(gtk::Align::End);
    capture_label.set_hexpand(false);
    capture_label.set_ellipsize(pango::EllipsizeMode::Start);
    header_row.append(&title_label);
    header_row.append(&capture_label);
    let header_overlay = gtk::Overlay::new();
    header_overlay.set_hexpand(true);
    header_overlay.set_child(Some(&header_row));
    header_overlay.add_overlay(&stream_status);
    header_overlay.set_clip_overlay(&stream_status, true);
    root.append(&header_overlay);

    let picture = gtk::Picture::new();
    picture.add_css_class("eye-preview-surface");
    picture.set_hexpand(true);
    picture.set_vexpand(true);
    picture.set_halign(gtk::Align::Fill);
    picture.set_valign(gtk::Align::Fill);
    picture.set_can_shrink(true);
    picture.set_keep_aspect_ratio(true);
    picture.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);

    let preview_frame = gtk::AspectFrame::new(0.5, 0.5, 16.0 / 9.0, false);
    preview_frame.add_css_class("eye-preview-surface");
    preview_frame.set_hexpand(true);
    preview_frame.set_vexpand(true);
    preview_frame.set_halign(gtk::Align::Fill);
    preview_frame.set_valign(gtk::Align::Fill);
    preview_frame.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);
    preview_frame.set_child(Some(&picture));

    let preview_placeholder = eye_placeholder_picture(title, false);
    preview_placeholder.add_css_class("display-placeholder-art");
    preview_placeholder.set_hexpand(true);
    preview_placeholder.set_vexpand(true);
    preview_placeholder.set_halign(gtk::Align::Center);
    preview_placeholder.set_valign(gtk::Align::Center);
    preview_placeholder.set_can_shrink(true);
    preview_placeholder.set_keep_aspect_ratio(true);
    preview_placeholder.set_sensitive(false);
    preview_placeholder.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);

    let preview_overlay = gtk::Overlay::new();
    preview_overlay.add_css_class("eye-preview-surface");
    preview_overlay.set_hexpand(true);
    preview_overlay.set_vexpand(true);
    preview_overlay.set_halign(gtk::Align::Fill);
    preview_overlay.set_valign(gtk::Align::Fill);
    preview_overlay.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);
    preview_overlay.set_child(Some(&preview_frame));
    preview_overlay.add_overlay(&preview_placeholder);
    preview_overlay.set_clip_overlay(&preview_placeholder, true);

    let preview_box = gtk::Box::new(gtk::Orientation::Vertical, 0);
    preview_box.set_hexpand(true);
    preview_box.set_vexpand(true);
    preview_box.set_halign(gtk::Align::Fill);
    preview_box.set_valign(gtk::Align::Fill);
    preview_box.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);
    preview_box.append(&preview_overlay);

    let window_placeholder = eye_placeholder_picture(title, true);
    window_placeholder.add_css_class("display-placeholder-art");
    window_placeholder.set_hexpand(true);
    window_placeholder.set_vexpand(true);
    window_placeholder.set_halign(gtk::Align::Center);
    window_placeholder.set_valign(gtk::Align::Center);
    window_placeholder.set_can_shrink(true);
    window_placeholder.set_keep_aspect_ratio(true);
    window_placeholder.set_sensitive(false);
    window_placeholder.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);

    let placeholder_overlay = gtk::Overlay::new();
    placeholder_overlay.add_css_class("eye-preview-surface");
    placeholder_overlay.set_hexpand(true);
    placeholder_overlay.set_vexpand(true);
    placeholder_overlay.set_halign(gtk::Align::Fill);
    placeholder_overlay.set_valign(gtk::Align::Fill);
    placeholder_overlay.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);
    let placeholder_frame = gtk::AspectFrame::new(0.5, 0.5, 16.0 / 9.0, false);
    placeholder_frame.add_css_class("eye-preview-surface");
    placeholder_frame.set_hexpand(true);
    placeholder_frame.set_vexpand(true);
    placeholder_frame.set_halign(gtk::Align::Fill);
    placeholder_frame.set_valign(gtk::Align::Fill);
    placeholder_frame.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);
    placeholder_overlay.set_child(Some(&placeholder_frame));
    placeholder_overlay.add_overlay(&window_placeholder);
    placeholder_overlay.set_clip_overlay(&window_placeholder, true);

    let placeholder_box = gtk::Box::new(gtk::Orientation::Vertical, 0);
    placeholder_box.set_hexpand(true);
    placeholder_box.set_vexpand(true);
    placeholder_box.set_halign(gtk::Align::Fill);
    placeholder_box.set_valign(gtk::Align::Fill);
    placeholder_box.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);
    placeholder_box.append(&placeholder_overlay);

    preview_placeholder.set_visible(picture.paintable().is_none());
    {
        let preview_placeholder = preview_placeholder.clone();
        picture.connect_paintable_notify(move |picture| {
            preview_placeholder.set_visible(picture.paintable().is_none());
        });
    }

    let stack = gtk::Stack::new();
    stack.set_hexpand(true);
    stack.set_vexpand(true);
    stack.add_named(&preview_box, Some("preview"));
    stack.add_named(&placeholder_box, Some("placeholder"));
    stack.set_visible_child_name("preview");
    root.append(&stack);

    let feed_source_combo = gtk::ComboBoxText::new();
    feed_source_combo.add_css_class("compact-combo");
    feed_source_combo.set_tooltip_text(Some("Eye source for this pane."));
    feed_source_combo.set_hexpand(true);
    feed_source_combo.set_size_request(0, -1);

    let capture_resolution_combo = gtk::ComboBoxText::new();
    capture_resolution_combo.add_css_class("compact-combo");
    capture_resolution_combo.set_tooltip_text(Some("Eye capture mode."));
    capture_resolution_combo.set_size_request(0, -1);
    capture_resolution_combo.set_hexpand(true);

    let breakout_combo = gtk::ComboBoxText::new();
    breakout_combo.add_css_class("compact-combo");
    breakout_combo.set_tooltip_text(Some("Breakout window size."));
    breakout_combo.set_size_request(0, -1);
    breakout_combo.set_hexpand(true);

    const EYE_CAPTURE_BUTTON_WIDTH: i32 = 54;
    let clip_button = gtk::Button::with_label("📷");
    stabilize_button(&clip_button, EYE_CAPTURE_BUTTON_WIDTH);
    clip_button.set_tooltip_text(Some("Capture a still image for this eye."));
    let record_button = gtk::Button::with_label("⏺");
    record_button.add_css_class("media-toggle");
    stabilize_button(&record_button, EYE_CAPTURE_BUTTON_WIDTH);
    record_button.set_tooltip_text(Some(
        "Record the feed currently routed into this eye block; click again to stop.",
    ));
    let record_audio_button = gtk::Button::with_label("🔇");
    record_audio_button.add_css_class("media-toggle");
    record_audio_button.add_css_class("media-toggle-split");
    stabilize_button(&record_audio_button, EYE_CAPTURE_BUTTON_WIDTH);
    record_audio_button.set_tooltip_text(Some(
        "Choose which audio tracks to bundle with the next recording.",
    ));
    let save_button = gtk::Button::with_label("📁");
    stabilize_button(&save_button, EYE_CAPTURE_BUTTON_WIDTH);
    save_button.set_tooltip_text(Some("Choose where this eye saves clips and recordings."));

    let action_button = gtk::Button::with_label("↗");
    stabilize_button(&action_button, EYE_CAPTURE_BUTTON_WIDTH);
    action_button.set_halign(gtk::Align::End);
    action_button.set_tooltip_text(Some("Open this eye in its own breakout window."));

    let footer_shell = gtk::Box::new(gtk::Orientation::Vertical, 6);
    footer_shell.set_vexpand(false);
    let controls_grid = gtk::Grid::new();
    controls_grid.set_column_spacing(8);
    controls_grid.set_row_spacing(8);
    controls_grid.set_hexpand(true);

    let feed_row = build_inline_combo_row("Feed", &feed_source_combo, 6);
    let capture_row = build_inline_combo_row("Capture", &capture_resolution_combo, 6);
    let breakout_row = build_inline_combo_row("Display", &breakout_combo, 6);
    let capture_actions = gtk::Box::new(gtk::Orientation::Horizontal, 6);
    capture_actions.set_hexpand(true);
    capture_actions.set_homogeneous(true);
    capture_actions.append(&clip_button);
    capture_actions.append(&record_button);
    capture_actions.append(&record_audio_button);
    capture_actions.append(&save_button);
    feed_row.set_hexpand(true);
    capture_row.set_hexpand(true);
    breakout_row.set_hexpand(true);
    controls_grid.attach(&feed_row, 0, 0, 1, 1);
    controls_grid.attach(&capture_row, 1, 0, 1, 1);
    controls_grid.attach(&action_button, 2, 0, 1, 1);
    controls_grid.attach(&breakout_row, 0, 1, 1, 1);
    controls_grid.attach(&capture_actions, 1, 1, 2, 1);
    footer_shell.append(&controls_grid);
    root.append(&footer_shell);

    DisplayPaneWidgets {
        root,
        stack,
        preview_frame,
        picture,
        stream_status,
        preview_placeholder,
        feed_source_combo,
        capture_resolution_combo,
        breakout_combo,
        clip_button,
        record_button,
        record_audio_button,
        save_button,
        action_button,
        preview_binding: Rc::new(RefCell::new(None)),
        title: title.to_string(),
    }
}

fn eye_placeholder_picture(title: &str, is_open: bool) -> gtk::Picture {
    let side = if title.contains("Left") { "left" } else { "right" };
    let state = if is_open { "open" } else { "closed" };
    let path = format!(
        "{}/assets/placeholders/eye_{}_{}.png",
        env!("CARGO_MANIFEST_DIR"),
        state,
        side,
    );

    let picture = gtk::Picture::new();
    if let Ok(texture) = gtk::gdk::Texture::from_filename(path) {
        picture.set_paintable(Some(&texture));
    }
    picture
}
