// Embedded cross-platform fonts (compile-time): terminal monospace + UI icons.
// Embedding means Windows / Linux / macOS all render the same glyphs without
// relying on Consolas / Segoe MDL2 Assets being installed.
//
// Cascadia Mono: full box-drawing + block-elements + braille (needed by btop
//   for its sparkline graphs; JetBrains Mono lacks braille → garbled output).
// Material Icons: open-source icon font replacing Windows-only Segoe MDL2 Assets.
import "fonts/CascadiaMono-Regular.ttf";
import "fonts/CascadiaMono-Bold.ttf";
import "fonts/MaterialIcons-Regular.ttf";

import { Theme } from "theme.slint";
import { Sidebar, DiskInfo, ProcessInfo } from "sidebar.slint";
import { TabBar, TabInfo } from "tabs.slint";
import { Welcome, SessionInfo, ConnectionFolderInfo } from "welcome.slint";
import { SessionDialog, SessionDraft } from "session_dialog.slint";
import { ConfirmDialog } from "confirm_dialog.slint";
import { TerminalView, TermSpan, TermMatch, CommandCategory, CommandItem } from "terminal_view.slint";
import { SftpEntry, SftpTreeNode } from "sftp_panel.slint";

export { SessionInfo, ConnectionFolderInfo, SessionDraft, TabInfo, SftpEntry, SftpTreeNode, CommandCategory, CommandItem, ProcessInfo }

// --- TerminalState ---------------------------------------------------------
// Per-terminal view-model exposed to Rust. A TabInfo has the metadata; the
// TerminalState carries the streaming log + status line. Kept as a parallel
// model so opening/closing tabs doesn't churn the log strings.
// One file-transfer record shown in the download manager.
export struct TransferInfo {
    id: string,
    name: string,
    detail: string,   // "2.3 MB/5.0 MB" | "已完成" | "失败"
    percent: float,   // 0.0..1.0
    state: int,       // 0 active / 1 done / 2 error
    is-upload: bool,
}

export struct TerminalState {
    id: string,
    tab-id: string,
    status: string,
    spans: [TermSpan],     // coloured runs of the visible terminal screen
    cursor-row: int,       // cursor cell on the grid
    cursor-col: int,
    rows-used: int,        // content rows, for viewport sizing
    is-alt-screen: bool,
    mouse-tracking: bool,
    find-matches: [TermMatch], // search-highlight rectangles
    selection: [TermMatch],    // drag-selection highlight rectangles

    // SFTP panel state
    sftp-path: string,
    sftp-entries: [SftpEntry],
    sftp-status: string,
    sftp-loading: bool,
    sftp-tree-nodes: [SftpTreeNode],
}

component ConfigButton inherits Rectangle {
    in property <string> label;
    in property <bool> primary: false;
    in property <bool> selected: false;
    in property <length> button-width: 84px;
    callback clicked();

    width: button-width;
    height: 30px;
    border-radius: Theme.radius-sm;
    border-width: primary ? 0px : 1px;
    border-color: selected ? Theme.accent : (touch.has-hover ? Theme.border-strong : Theme.border-subtle);
    background: primary
        ? (touch.has-hover ? Theme.accent-hover : Theme.accent)
        : selected
            ? Theme.bg-active
            : (touch.has-hover ? Theme.bg-hover : Theme.bg-elevated);

    touch := TouchArea {
        mouse-cursor: pointer;
        clicked => { root.clicked(); }
    }

    Text {
        width: parent.width;
        height: parent.height;
        text: root.label;
        color: root.primary ? #ffffff : Theme.text-primary;
        font-size: Theme.fs-sm;
        horizontal-alignment: center;
        vertical-alignment: center;
        overflow: elide;
    }
}

component ConfigTextField inherits Rectangle {
    in-out property <string> value;
    in property <length> field-width: 86px;

    width: field-width;
    height: 30px;
    border-radius: Theme.radius-sm;
    border-width: 1px;
    border-color: input.has-focus ? Theme.accent : Theme.border-subtle;
    background: Theme.bg-root;

    input := TextInput {
        x: 8px;
        width: parent.width - 16px;
        height: parent.height;
        text <=> root.value;
        color: Theme.text-primary;
        font-size: Theme.fs-sm;
        single-line: true;
        vertical-alignment: center;
    }
}

component ConfigValueBox inherits Rectangle {
    in property <string> value;
    in property <string> empty-text;

    height: 30px;
    border-radius: Theme.radius-sm;
    border-width: 1px;
    border-color: Theme.border-subtle;
    background: Theme.bg-root;

    Text {
        x: 10px;
        width: parent.width - 20px;
        height: parent.height;
        text: root.value == "" ? root.empty-text : root.value;
        color: root.value == "" ? Theme.text-muted : Theme.text-primary;
        font-size: Theme.fs-sm;
        overflow: elide;
        vertical-alignment: center;
    }
}

export component AppWindow inherits Window {
    title: "meatshell";
    icon: @image-url("../assets/icon.png");
    default-font-family: Theme.font-ui;
    min-width: 960px;
    min-height: 600px;
    preferred-width: 1200px;
    preferred-height: 760px;
    background: Theme.bg-root;

    // --- Sidebar data ------------------------------------------------------
    in property <string> connection-state: @tr("Not connected");
    in property <int> conn-state;                       // 0 gray / 1 green / 2 yellow
    in property <string> resource-title: @tr("Local resources");    // @tr("Local resources") | @tr("Server resources")
    in property <float> cpu-percent;
    in property <float> mem-percent;
    in property <float> swap-percent;
    in property <string> cpu-detail;
    in property <string> mem-detail;
    in property <string> swap-detail;
    // Network panel follows the active live session tab.
    in property <string> net-top-up;        // ↑ tx rate text
    in property <string> net-top-down;      // ↓ rx rate text
    in property <[float]> net-top-history;
    in property <[string]> net-ifaces;      // remote NIC names for the selector
    in property <string> net-selected;      // currently selected NIC
    in property <bool> net-show-selector;   // only on a live session tab
    in property <[DiskInfo]> disks;         // active tab's filesystem usage
    in property <[ProcessInfo]> processes;  // top resource consumers
    callback select-net-iface(string);

    // --- Top-right popups --------------------------------------------------
    in-out property <bool> download-open: false;  // download manager popup
    in-out property <bool> settings-open: false;  // settings menu popup
    in-out property <bool> config-open: false;    // app configuration dialog
    in-out property <bool> about-open: false;     // centered About dialog
    in property <string> download-dir;      // preset SFTP download folder ("" = ask)
    in property <[TransferInfo]> transfers; // download/upload records (newest first)
    in property <[CommandCategory]> command-categories;
    in property <[CommandItem]> command-items;
    in-out property <string> command-selected-category: "default";
    in-out property <string> command-selected-id;
    in-out property <string> command-category-draft;
    in-out property <string> command-edit-id;
    in-out property <string> command-edit-name;
    in-out property <string> command-edit-command;
    in-out property <bool> command-edit-append-cr: true;
    in-out property <string> command-param1-name;
    in-out property <string> command-param1-value;
    in-out property <string> command-param2-name;
    in-out property <string> command-param2-value;
    in-out property <string> command-param3-name;
    in-out property <string> command-param3-value;
    in-out property <string> command-param4-name;
    in-out property <string> command-param4-value;
    in-out property <string> command-param5-name;
    in-out property <string> command-param5-value;
    in property <[string]> about-libs;      // open-source libraries used
    in-out property <bool> lang-en: false;  // current UI language (false = 中文)
    // Two-way binding to Theme.dark — Rust reads/writes this property and
    // Slint propagates it to every widget that references Theme colours.
    in-out property <bool> dark-mode <=> Theme.dark;
    callback toggle-theme();               // flip dark ↔ light
    in-out property <length> sftp-panel-height: max(240px, root.height * 0.4); // default: files 2/5, terminal 3/5
    in-out property <length> terminal-font-size: 13px;
    in-out property <length> sftp-file-font-size: 16px;
    in-out property <length> sftp-name-column-width: 180px;
    in-out property <bool> sftp-name-width-manual: false;
    callback sftp-name-column-width-changed(float);
    callback sftp-name-column-auto();
    callback pick-download-dir();            // open a folder picker
    callback open-download-dir();            // reveal the folder in the OS
    callback clear-transfers();              // wipe the transfer history
    callback set-language(string);           // switch UI language ("zh" / "en")
    in-out property <string> max-tabs-text: "10";
    in-out property <string> terminal-font-size-text: "13";
    in-out property <string> sftp-font-size-text: "16";
    in-out property <string> background-path-text;
    in-out property <int> background-mode: 1; // 0 none, 1 terminal, 2 fullscreen
    in-out property <string> background-blur-text: "3";
    in-out property <string> terminal-opacity-text: "88";
    in-out property <string> ui-opacity-text: "72";
    in-out property <float> terminal-background-opacity: 0.88;
    in-out property <float> ui-background-opacity: 0.72;
    in-out property <bool> ui-debug-ids: false;
    in property <image> background-image;
    in-out property <string> config-dir-text;
    // WebDAV sync settings
    in-out property <bool> webdav-enabled: false;
    in-out property <string> webdav-url-text;
    in-out property <string> webdav-username-text;
    in-out property <string> webdav-password-text;
    in-out property <string> webdav-status-text;
    callback webdav-test-connection();
    callback webdav-push();
    callback webdav-pull();
    callback webdav-save-settings(bool, string, string, string);
    callback app-config-save(string, string, string, int, string, string, string, bool, string);
    callback app-config-pick-dir();
    callback app-background-pick();
    callback app-background-clear();
    callback debug-click(string, string);
    property <bool> fullscreen-background-active: root.background-mode == 2 && root.background-path-text != "";

    // --- Session list ------------------------------------------------------
    in property <[SessionInfo]> sessions;
    in property <[ConnectionFolderInfo]> connection-folders;
    in property <[string]> connection-folder-names;

    // --- Tabs --------------------------------------------------------------
    in property <[TabInfo]> tabs;
    in-out property <string> active-tab-id: "welcome";
    in-out property <int> tab-visible-start: 0;
    in property <[TerminalState]> terminals;

    // --- Dialog state ------------------------------------------------------
    in-out property <bool> dialog-open: false;
    in-out property <bool> dialog-editing: false;
    in-out property <string> dialog-id;
    in-out property <string> dialog-name;
    in-out property <string> dialog-group: "Default";
    in-out property <string> dialog-host;
    in-out property <string> dialog-port: "22";
    in-out property <string> dialog-user: "root";
    in-out property <string> dialog-auth: "password";
    in-out property <string> dialog-password;
    in-out property <string> dialog-key-path;
    in-out property <string> dialog-proxy;
    in-out property <string> dialog-kind: "ssh";
    in-out property <string> dialog-serial-port;
    in-out property <string> dialog-baud: "115200";
    in-out property <string> dialog-data-bits: "8";
    in-out property <string> dialog-stop-bits: "1";
    in-out property <string> dialog-parity: "none";
    in-out property <string> dialog-flow: "none";
    in-out property <bool> folder-dialog-open: false;
    in-out property <string> folder-dialog-mode: "create";
    in-out property <string> folder-edit-original;
    in-out property <string> folder-draft;
    in-out property <string> folder-error;

    // Delete-confirmation modal state (#28).
    in-out property <bool> confirm-delete-open: false;
    in-out property <string> confirm-delete-tab;
    in-out property <string> confirm-delete-path;

    // --- Callbacks up to Rust ---------------------------------------------
    callback new-session-clicked();
    callback connection-folder-create(string);
    callback connection-folder-rename(string, string);
    callback connection-folder-delete(string);
    callback connection-folder-toggle(string);
    callback session-move-folder(string, string);
    callback import-ssh-config();             // import hosts from ~/.ssh/config
    in-out property <string> ssh-import-hint;  // result text shown after import
    callback connect-session(string /* session-id */);
    callback edit-session(string /* session-id */);
    callback remove-session(string /* session-id */);
    callback session-dialog-submit(SessionDraft);
    callback session-dialog-cancel();
    callback session-dialog-pick-key();

    callback tab-selected(string);
    callback tab-closed(string);
    callback new-tab-clicked();
    callback previous-tab-clicked();
    callback next-tab-clicked();
    // Asks Rust to recompute the sidebar (status + resources) for whatever tab
    // is now active.  Fired on every active-tab change, UI- or code-driven.
    callback refresh-sidebar();
    changed active-tab-id => { root.refresh-sidebar(); }

    // Raw keystroke forwarding: Rust converts key+modifiers to PTY bytes.
    callback send-key(string /* tab-id */, string /* key */, bool /* ctrl */, bool /* alt */, bool /* shift */);
    // Notifies Rust of a PTY resize (pixel dimensions; Rust converts to cols/rows).
    callback terminal-resize(string /* tab-id */, float /* width-px */, float /* height-px */);

    // --- SFTP callbacks ---------------------------------------------------
    // Navigate to a new remote directory (or ".." to go up).
    callback sftp-navigate(string /* tab-id */, string /* path */);
    // Trigger a download: Rust opens a save-folder dialog then transfers.
    callback sftp-download(string /* tab-id */, string /* remote-path */);
    // Trigger an upload: Rust opens a file-picker dialog then transfers.
    callback sftp-upload-clicked(string /* tab-id */, string /* remote-dir */);
    // Refresh the current directory listing.
    callback sftp-refresh(string /* tab-id */, string /* path */);
    // Toggle expand/collapse of a tree node (also navigates to that directory).
    callback sftp-tree-expand(string /* tab-id */, string /* path */);
    callback sftp-delete(string /* tab-id */, string /* path */);
    callback sftp-rename(string /* tab-id */, string /* path */, string /* new-name */);
    callback sftp-edit(string /* tab-id */, string /* path */);

    // --- Clipboard callbacks ----------------------------------------------
    // Paste clipboard text into the active terminal.
    callback paste-from-clipboard(string /* tab-id */);
    // Copy the current terminal screen buffer to the clipboard.
    callback copy-terminal-text(string /* tab-id */);
    // Clear a session's terminal buffer (its visible screen + scrollback).
    callback clear-terminal(string /* tab-id */);
    // Recompute search highlights for a session's visible screen.
    callback find-query-changed(string /* tab-id */, string /* query */);
    // Scroll a session's scrollback history by N lines (+ = up/older).
    callback terminal-scroll(string /* tab-id */, int /* delta-lines */);
    // Drag-selection lifecycle (grid row/col coordinates).
    callback term-select-start(string /* tab-id */, int /* row */, int /* col */);
    callback term-select-update(string /* tab-id */, int /* row */, int /* col */);
    callback term-select-end(string /* tab-id */);
    callback term-select-autoscroll(string /* tab-id */, int /* dir */);
    callback command-category-select(string /* category-id */);
    callback command-category-add(string /* name */);
    callback command-category-rename(string /* category-id */, string /* name */);
    callback command-category-delete(string /* category-id */);
    callback command-new(string /* category-id */);
    callback command-select(string /* command-id */);
    callback command-save(string /* command-id */, string /* category-id */, string /* name */, string /* command */, bool /* append-cr */);
    callback command-delete(string /* command-id */);
    callback command-run(string /* tab-id */, string /* command-id */, string /* p1 */, string /* p2 */, string /* p3 */, string /* p4 */, string /* p5 */);
    callback command-move(string /* command-id */, string /* category-id */);
    callback terminal-mouse-event(string /* tab-id */, string /* kind */, int /* button */, int /* row */, int /* col */);

    if root.fullscreen-background-active : Image {
        width: parent.width;
        height: parent.height;
        source: root.background-image;
        image-fit: cover;
    }

    Rectangle {
        width: parent.width;
        height: parent.height;
        background: root.fullscreen-background-active
            ? Theme.bg-root.with-alpha(root.ui-background-opacity)
            : Theme.bg-root;
    }

    HorizontalLayout {
        spacing: 0;

        // Left sidebar
        Sidebar {
            app-background-active: root.fullscreen-background-active;
            ui-opacity: root.ui-background-opacity;
            connection-state: root.connection-state;
            conn-state: root.conn-state;
            resource-title: root.resource-title;
            cpu-percent: root.cpu-percent;
            mem-percent: root.mem-percent;
            swap-percent: root.swap-percent;
            cpu-detail: root.cpu-detail;
            mem-detail: root.mem-detail;
            swap-detail: root.swap-detail;
            net-top-up: root.net-top-up;
            net-top-down: root.net-top-down;
            net-top-history: root.net-top-history;
            net-ifaces: root.net-ifaces;
            net-selected: root.net-selected;
            net-show-selector: root.net-show-selector;
            disks: root.disks;
            processes: root.processes;
            select-net-iface(i) => { root.select-net-iface(i); }
        }

        // Right side: tabs + content
        VerticalLayout {
            spacing: 0;
            horizontal-stretch: 1;

            TabBar {
                app-background-active: root.fullscreen-background-active;
                ui-opacity: root.ui-background-opacity;
                tabs: root.tabs;
                active-id: root.active-tab-id;
                visible-start <=> root.tab-visible-start;
                tab-selected(id) => {
                    if root.ui-debug-ids { root.debug-click("tabbar", "tab-selected"); }
                    root.active-tab-id = id;
                    root.tab-selected(id);
                }
                tab-closed(id) => {
                    if root.ui-debug-ids { root.debug-click("tabbar", "tab-closed"); }
                    root.tab-closed(id);
                }
                new-tab() => {
                    if root.ui-debug-ids { root.debug-click("tabbar", "new-tab"); }
                    root.new-tab-clicked();
                }
                previous-tab() => {
                    if root.ui-debug-ids { root.debug-click("tabbar", "previous-tab"); }
                    root.previous-tab-clicked();
                }
                next-tab() => {
                    if root.ui-debug-ids { root.debug-click("tabbar", "next-tab"); }
                    root.next-tab-clicked();
                }
            }

            // Content area swaps based on active tab kind.  Children are
            // stacked, not laid out horizontally, so hidden terminal tabs never
            // reserve half of the workspace.
            Rectangle {
                vertical-stretch: 1;
                background: root.fullscreen-background-active
                    ? Theme.bg-root.with-alpha(root.ui-background-opacity)
                    : Theme.bg-root;
                clip: true;

                // Welcome tab
                if root.active-tab-id == "welcome" : Welcome {
                    width: parent.width;
                    height: parent.height;
                    app-background-active: root.fullscreen-background-active;
                    ui-opacity: root.ui-background-opacity;
                    sessions: root.sessions;
                    folders: root.connection-folders;
                    all-folder-names: root.connection-folder-names;
                    import-hint: root.ssh-import-hint;
                    debug-ids: false;
                    new-session => {
                        if root.ui-debug-ids { root.debug-click("welcome", "new-session"); }
                        root.new-session-clicked();
                    }
                    new-folder => {
                        if root.ui-debug-ids { root.debug-click("welcome", "new-folder"); }
                        root.folder-dialog-mode = "create";
                        root.folder-edit-original = "";
                        root.folder-draft = "";
                        root.folder-error = "";
                        root.folder-dialog-open = true;
                    }
                    rename-folder(name) => {
                        if root.ui-debug-ids { root.debug-click("welcome", "rename-folder"); }
                        root.folder-dialog-mode = "rename";
                        root.folder-edit-original = name;
                        root.folder-draft = name;
                        root.folder-error = "";
                        root.folder-dialog-open = true;
                    }
                    delete-folder(name) => {
                        if root.ui-debug-ids { root.debug-click("welcome", "delete-folder"); }
                        root.connection-folder-delete(name);
                    }
                    toggle-folder(name) => {
                        if root.ui-debug-ids { root.debug-click("welcome", "toggle-folder"); }
                        root.connection-folder-toggle(name);
                    }
                    move-session-folder(id, folder) => {
                        if root.ui-debug-ids { root.debug-click("welcome", "move-session-folder"); }
                        root.session-move-folder(id, folder);
                    }
                    import-ssh-config => {
                        if root.ui-debug-ids { root.debug-click("welcome", "import-ssh-config"); }
                        root.import-ssh-config();
                    }
                    connect-session(id) => {
                        if root.ui-debug-ids { root.debug-click("welcome", "connect-session"); }
                        root.connect-session(id);
                    }
                    edit-session(id) => {
                        if root.ui-debug-ids { root.debug-click("welcome", "edit-session"); }
                        root.edit-session(id);
                    }
                    remove-session(id) => {
                        if root.ui-debug-ids { root.debug-click("welcome", "remove-session"); }
                        root.remove-session(id);
                    }
                }

                // Terminal tabs.  Every terminal view fills the same workspace;
                // only the active tab is visible and allowed to emit resize
                // events from its own timer.
                for term[i] in root.terminals : TerminalView {
                    x: 0px;
                    y: 0px;
                    width: parent.width;
                    height: parent.height;
                    visible: term.tab-id == root.active-tab-id;
                    tab-id: term.id;
                    status-line: term.status;
                    spans: term.spans;
                    cursor-row: term.cursor-row;
                    cursor-col: term.cursor-col;
                    rows-used: term.rows-used;
                    is-alt-screen: term.is-alt-screen;
                    mouse-tracking: term.mouse-tracking;
                    find-matches: term.find-matches;
                    selection: term.selection;
                    sftp-panel-height <=> root.sftp-panel-height;
                    terminal-font-size: root.terminal-font-size;
                    click-debug-enabled: root.ui-debug-ids;
                    background-path: root.background-path-text;
                    background-mode: root.background-mode;
                    background-image: root.background-image;
                    app-background-active: root.fullscreen-background-active;
                    terminal-bg-opacity: root.terminal-background-opacity;
                    ui-opacity: root.ui-background-opacity;
                    sftp-file-font-size: root.sftp-file-font-size;
                    sftp-name-column-width <=> root.sftp-name-column-width;
                    sftp-name-width-manual <=> root.sftp-name-width-manual;
                    sftp-path: term.sftp-path;
                    sftp-entries: term.sftp-entries;
                    sftp-status: term.sftp-status;
                    sftp-loading: term.sftp-loading;
                    sftp-tree-nodes: term.sftp-tree-nodes;
                    command-categories: root.command-categories;
                    command-items: root.command-items;
                    command-selected-category <=> root.command-selected-category;
                    command-selected-id <=> root.command-selected-id;
                    command-category-draft <=> root.command-category-draft;
                    command-edit-id <=> root.command-edit-id;
                    command-edit-name <=> root.command-edit-name;
                    command-edit-command <=> root.command-edit-command;
                    command-edit-append-cr <=> root.command-edit-append-cr;
                    command-param1-name <=> root.command-param1-name;
                    command-param1-value <=> root.command-param1-value;
                    command-param2-name <=> root.command-param2-name;
                    command-param2-value <=> root.command-param2-value;
                    command-param3-name <=> root.command-param3-name;
                    command-param3-value <=> root.command-param3-value;
                    command-param4-name <=> root.command-param4-name;
                    command-param4-value <=> root.command-param4-value;
                    command-param5-name <=> root.command-param5-name;
                    command-param5-value <=> root.command-param5-value;
                    send-key(key, ctrl, alt, shift) => { root.send-key(term.id, key, ctrl, alt, shift) }
                    terminal-resize(w, h) => { root.terminal-resize(term.id, w, h) }
                    sftp-navigate(path) => { root.sftp-navigate(term.id, path); }
                    sftp-download(path) => { root.sftp-download(term.id, path); }
                    sftp-upload-clicked(dir) => { root.sftp-upload-clicked(term.id, dir); }
                    sftp-refresh(path) => { root.sftp-refresh(term.id, path); }
                    sftp-tree-expand(path) => { root.sftp-tree-expand(term.id, path); }
                    // Gate delete behind an in-app confirmation (#28): stash the
                    // target and open the modal; the real delete fires on confirm.
                    sftp-delete(path) => {
                        root.confirm-delete-tab = term.id;
                        root.confirm-delete-path = path;
                        root.confirm-delete-open = true;
                    }
                    sftp-rename(path, name) => { root.sftp-rename(term.id, path, name); }
                    sftp-edit(path) => { root.sftp-edit(term.id, path); }
                    sftp-name-column-width-changed(px) => { root.sftp-name-column-width-changed(px); }
                    sftp-name-column-auto() => { root.sftp-name-column-auto(); }
                    paste-from-clipboard() => { root.paste-from-clipboard(term.id); }
                    copy-terminal-text() => { root.copy-terminal-text(term.id); }
                    clear-terminal() => { root.clear-terminal(term.id); }
                    find-query-changed(q) => { root.find-query-changed(term.id, q); }
                    terminal-scroll(d) => { root.terminal-scroll(term.id, d); }
                    select-start(r, c) => { root.term-select-start(term.id, r, c); }
                    select-update(r, c) => { root.term-select-update(term.id, r, c); }
                    select-end() => { root.term-select-end(term.id); }
                    select-autoscroll(dir) => { root.term-select-autoscroll(term.id, dir); }
                    command-category-select(id) => { root.command-category-select(id); }
                    command-category-add(name) => { root.command-category-add(name); }
                    command-category-rename(id, name) => { root.command-category-rename(id, name); }
                    command-category-delete(id) => { root.command-category-delete(id); }
                    command-new(category) => { root.command-new(category); }
                    command-select(id) => { root.command-select(id); }
                    command-save(id, category, name, command, append_cr) => {
                        root.command-save(id, category, name, command, append_cr);
                    }
                    command-delete(id) => { root.command-delete(id); }
                    command-run(id, p1, p2, p3, p4, p5) => {
                        root.command-run(term.id, id, p1, p2, p3, p4, p5);
                    }
                    command-move(id, category) => { root.command-move(id, category); }
                    terminal-mouse-event(kind, button, row, col) => {
                        root.terminal-mouse-event(term.id, kind, button, row, col);
                    }
                    debug-click(parent, button) => { root.debug-click(parent, button); }
                }
            }
        }
    }

    // --- Top-right buttons: [☀/🌙 theme] [↓ download] [⚙ settings] ----------
    // Settings (gear) — far right.
    Rectangle {
        x: root.width - 34px;
        y: 8px;
        width: 26px;
        height: 26px;
        border-radius: Theme.radius-sm;
        background: gear-ta.has-hover || root.settings-open ? Theme.bg-hover : transparent;
        gear-ta := TouchArea {
            mouse-cursor: pointer;
        clicked => {
            if root.ui-debug-ids { root.debug-click("topbar", "settings"); }
            root.settings-open = !root.settings-open;
            root.download-open = false;
            root.config-open = false;
        }
        }
        Text {
            width: parent.width;
            height: parent.height;
            text: "\u{E8B8}";              // Material Icons settings (gear)
            font-family: "Material Icons";
            color: Theme.text-secondary;
            font-size: Theme.fs-md;
            horizontal-alignment: center;
            vertical-alignment: center;
        }
    }
    // Download manager — left of settings.
    Rectangle {
        x: root.width - 64px;
        y: 8px;
        width: 26px;
        height: 26px;
        border-radius: Theme.radius-sm;
        background: dl-ta.has-hover || root.download-open ? Theme.bg-hover : transparent;
        dl-ta := TouchArea {
            mouse-cursor: pointer;
            clicked => {
                if root.ui-debug-ids { root.debug-click("topbar", "downloads"); }
                root.download-open = !root.download-open;
                root.settings-open = false;
                root.config-open = false;
            }
        }
        Text {
            width: parent.width;
            height: parent.height;
            text: "\u{E2C4}";              // Material Icons file_download
            font-family: "Material Icons";
            color: Theme.text-secondary;
            font-size: Theme.fs-md;
            horizontal-alignment: center;
            vertical-alignment: center;
        }
    }
    // Theme toggle (sun = currently dark → click for light;
    //               moon = currently light → click for dark) — left of download.
    Rectangle {
        x: root.width - 94px;
        y: 8px;
        width: 26px;
        height: 26px;
        border-radius: Theme.radius-sm;
        background: theme-ta.has-hover ? Theme.bg-hover : transparent;
        theme-ta := TouchArea {
            mouse-cursor: pointer;
            clicked => {
                if root.ui-debug-ids { root.debug-click("topbar", "toggle-theme"); }
                root.toggle-theme();
            }
        }
        Text {
            width: parent.width;
            height: parent.height;
            // light_mode ☀ when dark (click → go light)
            // dark_mode  🌙 when light (click → go dark)
            text: Theme.dark ? "\u{E518}" : "\u{E51C}";
            font-family: "Material Icons";
            color: Theme.dark ? #f5c542 : #5856d6;  // amber sun / indigo moon
            font-size: Theme.fs-md;
            horizontal-alignment: center;
            vertical-alignment: center;
        }
    }

    // --- Download manager popup -------------------------------------------
    // Always present; toggled via `visible` (avoids destroying interactive
    // elements mid-event, which crashes when created/removed at the Window root).
    if root.download-open : TouchArea {
        width: parent.width;
        height: parent.height;
        clicked => { root.download-open = false; }
    }

    Rectangle {
        x: parent.width - 364px;
        y: 40px;
        width: 350px;
        height: 400px;
        visible: root.download-open;
        background: Theme.bg-panel;
        border-radius: Theme.radius-md;
        border-width: 1px;
        border-color: Theme.border-strong;
        drop-shadow-blur: 16px;
        drop-shadow-color: #00000070;

        // Swallow pointer events so right-clicks don't fall through to the
        // terminal's context menu underneath.
        TouchArea {}

        VerticalLayout {
            padding: 14px;
            spacing: 10px;

            HorizontalLayout {
                Text {
                    text: @tr("Download settings");
                    color: Theme.text-primary;
                    font-size: Theme.fs-md;
                    font-weight: 600;
                    horizontal-stretch: 1;
                    vertical-alignment: center;
                }
                Rectangle {
                    width: 20px; height: 20px;
                    border-radius: Theme.radius-sm;
                    background: close-ta.has-hover ? Theme.bg-hover : transparent;
                    close-ta := TouchArea {
                        mouse-cursor: pointer;
                        clicked => { root.download-open = false; }
                    }
                    Text { text: "\u{E5CD}"; font-family: "Material Icons";
                           color: Theme.text-secondary; font-size: Theme.fs-sm;
                           width: parent.width; height: parent.height;
                           horizontal-alignment: center; vertical-alignment: center; }
                }
            }

                Text {
                    text: @tr("Save downloads to:");
                    color: Theme.text-secondary;
                    font-size: Theme.fs-sm;
                }

                // Current path display
                Rectangle {
                    height: 26px;
                    background: Theme.bg-root;
                    border-radius: Theme.radius-sm;
                    Text {
                        x: 8px;
                        width: parent.width - 16px;
                        height: parent.height;
                        text: root.download-dir == "" ? @tr("(ask every time)") : root.download-dir;
                        color: root.download-dir == "" ? Theme.text-muted : Theme.text-primary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                }

                HorizontalLayout {
                    spacing: 8px;
                    alignment: end;

                    Rectangle {
                        width: 96px; height: 28px;
                        border-radius: Theme.radius-sm;
                        background: pick-ta.has-hover ? Theme.accent-hover : Theme.accent;
                        pick-ta := TouchArea {
                            mouse-cursor: pointer;
                            clicked => {
                                if root.ui-debug-ids { root.debug-click("downloads", "choose-folder"); }
                                root.pick-download-dir();
                            }
                        }
                        Text { text: @tr("Choose folder"); color: #ffffff; font-size: Theme.fs-sm;
                               width: parent.width; height: parent.height;
                               horizontal-alignment: center; vertical-alignment: center; }
                    }
                    Rectangle {
                        width: 76px; height: 28px;
                        border-radius: Theme.radius-sm;
                        background: open-ta.has-hover ? Theme.bg-hover : Theme.bg-elevated;
                        open-ta := TouchArea {
                            mouse-cursor: pointer;
                            clicked => {
                                if root.ui-debug-ids { root.debug-click("downloads", "open-folder"); }
                                root.open-download-dir();
                            }
                        }
                        Text { text: @tr("Open folder"); color: Theme.text-primary; font-size: Theme.fs-sm;
                               width: parent.width; height: parent.height;
                               horizontal-alignment: center; vertical-alignment: center; }
                    }
                }

                Rectangle { height: 1px; background: Theme.border-subtle; }

                // Transfer records (download/upload progress + history).
                HorizontalLayout {
                    Text {
                        text: @tr("Transfers");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        horizontal-stretch: 1;
                        vertical-alignment: center;
                    }
                    Rectangle {
                        width: 44px; height: 20px;
                        border-radius: Theme.radius-sm;
                        background: clr-ta.has-hover ? Theme.bg-hover : transparent;
                        clr-ta := TouchArea {
                            mouse-cursor: pointer;
                            clicked => {
                                if root.ui-debug-ids { root.debug-click("downloads", "clear-transfers"); }
                                root.clear-transfers();
                            }
                        }
                        Text { text: @tr("Clear"); color: Theme.text-muted; font-size: Theme.fs-xs;
                               width: parent.width; height: parent.height;
                               horizontal-alignment: center; vertical-alignment: center; }
                    }
                }

                Flickable {
                    vertical-stretch: 1;
                    viewport-width: self.width;
                    viewport-height: max(self.height, xfer-col.preferred-height);
                    xfer-col := VerticalLayout {
                        alignment: start;
                        spacing: 4px;

                        if root.transfers.length == 0 : Text {
                            text: @tr("No transfers yet");
                            color: Theme.text-muted;
                            font-size: Theme.fs-xs;
                        }

                        for t in root.transfers : Rectangle {
                            height: 36px;
                            border-radius: Theme.radius-sm;
                            background: root.fullscreen-background-active ? Theme.bg-root.with-alpha(root.ui-background-opacity) : Theme.bg-root;
                            VerticalLayout {
                                padding-left: 8px; padding-right: 8px;
                                padding-top: 4px; padding-bottom: 4px;
                                spacing: 3px;
                                HorizontalLayout {
                                    spacing: 4px;
                                    Text {
                                        text: (t.is-upload ? "↑ " : "↓ ") + t.name;
                                        color: Theme.text-primary;
                                        font-size: Theme.fs-xs;
                                        horizontal-stretch: 1;
                                        overflow: elide;
                                        vertical-alignment: center;
                                    }
                                    Text {
                                        text: t.detail;
                                        color: t.state == 2 ? Theme.danger
                                             : t.state == 1 ? Theme.success
                                             : Theme.text-muted;
                                        font-size: Theme.fs-xs;
                                        vertical-alignment: center;
                                    }
                                }
                                // progress bar
                                Rectangle {
                                    height: 4px;
                                    border-radius: 2px;
                                    background: Theme.bg-elevated;
                                    Rectangle {
                                        x: 0; y: 0; height: parent.height;
                                        width: parent.width * clamp(t.percent, 0.0, 1.0);
                                        border-radius: 2px;
                                        background: t.state == 2 ? Theme.danger
                                                  : t.state == 1 ? Theme.success
                                                  : Theme.accent;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

    // --- Settings menu popup (top-right) ----------------------------------
    Rectangle {
        x: parent.width - 196px;
        y: 40px;
        width: 198px;
        height: 134px;
        visible: root.settings-open;
        background: Theme.bg-panel;
        border-radius: Theme.radius-md;
        border-width: 1px;
        border-color: Theme.border-strong;
        drop-shadow-blur: 14px;
        drop-shadow-color: #00000060;

        TouchArea {}   // swallow events so they don't reach the terminal

        VerticalLayout {
            padding: 4px;
            spacing: 1px;
            // Import hosts from ~/.ssh/config.
            Rectangle {
                height: 28px;
                border-radius: Theme.radius-sm;
                background: import-ta.has-hover ? Theme.bg-hover : transparent;
                import-ta := TouchArea {
                    mouse-cursor: pointer;
                    clicked => {
                        if root.ui-debug-ids { root.debug-click("settings", "import-ssh-config"); }
                        root.settings-open = false;
                        root.import-ssh-config();
                    }
                }
                HorizontalLayout {
                    height: parent.height;
                    padding-left: 8px; spacing: 8px;
                    Text { width: 18px; height: parent.height; text: "\u{E890}"; font-family: "Material Icons"; // input/import
                           color: Theme.text-secondary; font-size: Theme.fs-sm;
                           horizontal-alignment: center; vertical-alignment: center; }
                    Text { text: @tr("Import ~/.ssh/config"); color: Theme.text-primary; font-size: Theme.fs-md;
                           height: parent.height; vertical-alignment: center; horizontal-stretch: 1; }
                }
            }
            // Language toggle: shows the language you'll switch TO.
            Rectangle {
                height: 28px;
                border-radius: Theme.radius-sm;
                background: lang-ta.has-hover ? Theme.bg-hover : transparent;
                lang-ta := TouchArea {
                    mouse-cursor: pointer;
                    clicked => {
                        if root.ui-debug-ids { root.debug-click("settings", "language"); }
                        root.settings-open = false;
                        root.set-language(root.lang-en ? "zh" : "en");
                    }
                }
                HorizontalLayout {
                    height: parent.height;
                    padding-left: 8px; spacing: 8px;
                    Text { width: 18px; height: parent.height; text: "\u{E894}"; font-family: "Material Icons"; // language/translate
                           color: Theme.text-secondary; font-size: Theme.fs-sm;
                           horizontal-alignment: center; vertical-alignment: center; }
                    Text { text: root.lang-en ? "切换到中文" : "Switch to English";
                           color: Theme.text-primary; font-size: Theme.fs-md;
                           height: parent.height; vertical-alignment: center; horizontal-stretch: 1; }
                }
            }
            Rectangle {
                height: 28px;
                border-radius: Theme.radius-sm;
                background: about-ta.has-hover ? Theme.bg-hover : transparent;
                about-ta := TouchArea {
                    mouse-cursor: pointer;
                    clicked => {
                        if root.ui-debug-ids { root.debug-click("settings", "about"); }
                        root.settings-open = false;
                        root.about-open = true;
                    }
                }
                HorizontalLayout {
                    height: parent.height;
                    padding-left: 8px; spacing: 8px;
                    Text { width: 18px; height: parent.height; text: "\u{E88E}"; font-family: "Material Icons"; // Info
                           color: Theme.text-secondary; font-size: Theme.fs-sm;
                           horizontal-alignment: center; vertical-alignment: center; }
                    Text { text: @tr("About"); color: Theme.text-primary; font-size: Theme.fs-md;
                           height: parent.height; vertical-alignment: center; horizontal-stretch: 1; }
                }
            }
            Rectangle {
                height: 28px;
                border-radius: Theme.radius-sm;
                background: config-ta.has-hover ? Theme.bg-hover : transparent;
                config-ta := TouchArea {
                    mouse-cursor: pointer;
                    clicked => {
                        if root.ui-debug-ids { root.debug-click("settings", "configuration"); }
                        root.settings-open = false;
                        root.config-open = true;
                    }
                }
                HorizontalLayout {
                    height: parent.height;
                    padding-left: 8px; spacing: 8px;
                    Text { width: 18px; height: parent.height; text: "\u{E8B8}"; font-family: "Material Icons";
                           color: Theme.text-secondary; font-size: Theme.fs-sm;
                           horizontal-alignment: center; vertical-alignment: center; }
                    Text { text: @tr("Configuration"); color: Theme.text-primary; font-size: Theme.fs-md;
                           height: parent.height; vertical-alignment: center; horizontal-stretch: 1; }
                }
            }
        }
    }

    // --- Configuration dialog --------------------------------------------
    Rectangle {
        width: parent.width;
        height: parent.height;
        visible: root.config-open;
        background: #00000070;
        TouchArea { clicked => { root.config-open = false; } }

        Rectangle {
            x: (parent.width - self.width) / 2;
            y: (parent.height - self.height) / 2;
            width: min(640px, parent.width - 48px);
            height: min(620px, parent.height - 48px);
            background: Theme.bg-panel;
            border-radius: Theme.radius-md;
            border-width: 1px;
            border-color: Theme.border-strong;
            drop-shadow-blur: 20px;
            drop-shadow-color: #00000080;

            TouchArea {}

            VerticalLayout {
                padding: 16px;
                spacing: 10px;

                HorizontalLayout {
                    Text {
                        text: @tr("Configuration");
                        color: Theme.text-primary;
                        font-size: Theme.fs-md;
                        font-weight: 600;
                        vertical-alignment: center;
                        horizontal-stretch: 1;
                    }
                    Rectangle {
                        width: 22px; height: 22px;
                        border-radius: Theme.radius-sm;
                        background: cfg-close-ta.has-hover ? Theme.bg-hover : transparent;
                        cfg-close-ta := TouchArea {
                            mouse-cursor: pointer;
                            clicked => { root.config-open = false; }
                        }
                        Text { text: "\u{E5CD}"; font-family: "Material Icons";
                               color: Theme.text-secondary; font-size: Theme.fs-sm;
                               width: parent.width; height: parent.height;
                               horizontal-alignment: center; vertical-alignment: center; }
                    }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("Maximum terminal windows");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigTextField {
                        value <=> root.max-tabs-text;
                        field-width: 86px;
                    }
                    Rectangle { horizontal-stretch: 1; }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("Terminal font size");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigTextField {
                        value <=> root.terminal-font-size-text;
                        field-width: 72px;
                    }
                    Text {
                        width: 26px;
                        height: parent.height;
                        text: "px";
                        color: Theme.text-muted;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                    }
                    Text {
                        width: 138px;
                        height: parent.height;
                        text: @tr("File manager font size");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigTextField {
                        value <=> root.sftp-font-size-text;
                        field-width: 72px;
                    }
                    Text {
                        width: 26px;
                        height: parent.height;
                        text: "px";
                        color: Theme.text-muted;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                    }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("Background image");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigValueBox {
                        horizontal-stretch: 1;
                        value: root.background-path-text;
                        empty-text: @tr("No background image");
                    }
                    ConfigButton {
                        label: @tr("Choose");
                        button-width: 82px;
                        clicked => {
                            if root.ui-debug-ids { root.debug-click("configuration", "choose-background"); }
                            root.app-background-pick();
                        }
                    }
                    ConfigButton {
                        label: @tr("Clear");
                        button-width: 72px;
                        clicked => {
                            if root.ui-debug-ids { root.debug-click("configuration", "clear-background"); }
                            root.app-background-clear();
                        }
                    }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("Background scope");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigButton {
                        label: @tr("Terminal");
                        button-width: 96px;
                        selected: root.background-mode == 1;
                        clicked => {
                            if root.ui-debug-ids { root.debug-click("configuration", "background-terminal"); }
                            root.background-mode = 1;
                        }
                    }
                    ConfigButton {
                        label: @tr("Fullscreen");
                        button-width: 104px;
                        selected: root.background-mode == 2;
                        clicked => {
                            if root.ui-debug-ids { root.debug-click("configuration", "background-fullscreen"); }
                            root.background-mode = 2;
                        }
                    }
                    Rectangle { horizontal-stretch: 1; }
                    Text {
                        height: parent.height;
                        text: @tr("Blur");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                    }
                    ConfigTextField {
                        value <=> root.background-blur-text;
                        field-width: 58px;
                    }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("Terminal opacity");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigTextField {
                        value <=> root.terminal-opacity-text;
                        field-width: 68px;
                    }
                    Text {
                        width: 24px;
                        height: parent.height;
                        text: "%";
                        color: Theme.text-muted;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                    }
                    Text {
                        width: 108px;
                        height: parent.height;
                        text: @tr("UI opacity");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigTextField {
                        value <=> root.ui-opacity-text;
                        field-width: 68px;
                    }
                    Text {
                        width: 24px;
                        height: parent.height;
                        text: "%";
                        color: Theme.text-muted;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                    }
                    Rectangle { horizontal-stretch: 1; }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("Click log");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigButton {
                        label: root.ui-debug-ids ? @tr("On") : @tr("Off");
                        button-width: 76px;
                        selected: root.ui-debug-ids;
                        clicked => {
                            root.ui-debug-ids = !root.ui-debug-ids;
                            if root.ui-debug-ids { root.debug-click("configuration", "click-log-on"); }
                        }
                    }
                    Text {
                        text: @tr("Writes clicked button/parent ids to the debug log");
                        color: Theme.text-muted;
                        font-size: Theme.fs-xs;
                        vertical-alignment: center;
                        horizontal-stretch: 1;
                        overflow: elide;
                    }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("Configuration directory");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigValueBox {
                        horizontal-stretch: 1;
                        value: root.config-dir-text;
                        empty-text: "";
                    }
                    ConfigButton {
                        label: @tr("Choose");
                        button-width: 82px;
                        clicked => {
                            if root.ui-debug-ids { root.debug-click("configuration", "choose-config-dir"); }
                            root.app-config-pick-dir();
                        }
                    }
                }

                // --- WebDAV Sync Settings ---
                Rectangle { height: 1px; background: Theme.border-subtle; }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("WebDAV sync");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        font-weight: 600;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigButton {
                        label: root.webdav-enabled ? @tr("On") : @tr("Off");
                        button-width: 76px;
                        selected: root.webdav-enabled;
                        clicked => {
                            root.webdav-enabled = !root.webdav-enabled;
                        }
                    }
                    Rectangle { horizontal-stretch: 1; }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("WebDAV URL");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigTextField {
                        value <=> root.webdav-url-text;
                        field-width: 300px;
                    }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: @tr("WebDAV username");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigTextField {
                        value <=> root.webdav-username-text;
                        field-width: 160px;
                    }
                    Text {
                        width: 80px;
                        height: parent.height;
                        text: @tr("Password");
                        color: Theme.text-secondary;
                        font-size: Theme.fs-sm;
                        vertical-alignment: center;
                        overflow: elide;
                    }
                    ConfigTextField {
                        value <=> root.webdav-password-text;
                        field-width: 140px;
                    }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Text {
                        width: 148px;
                        height: parent.height;
                        text: root.webdav-status-text;
                        color: root.webdav-status-text == @tr("Connection OK") ? Theme.success : Theme.text-muted;
                        font-size: Theme.fs-xs;
                        vertical-alignment: center;
                        overflow: elide;
                        horizontal-stretch: 1;
                    }
                    ConfigButton {
                        label: @tr("Test");
                        button-width: 72px;
                        clicked => { root.webdav-test-connection(); }
                    }
                    ConfigButton {
                        label: @tr("Upload");
                        button-width: 82px;
                        clicked => { root.webdav-push(); }
                    }
                    ConfigButton {
                        label: @tr("Download");
                        button-width: 82px;
                        clicked => { root.webdav-pull(); }
                    }
                }

                HorizontalLayout {
                    height: 30px;
                    spacing: 10px;
                    Rectangle { horizontal-stretch: 1; }
                    ConfigButton {
                        label: @tr("Cancel");
                        button-width: 82px;
                        clicked => {
                            if root.ui-debug-ids { root.debug-click("configuration", "cancel"); }
                            root.config-open = false;
                        }
                    }
                    ConfigButton {
                        label: @tr("Save");
                        button-width: 82px;
                        primary: true;
                        clicked => {
                            if root.ui-debug-ids { root.debug-click("configuration", "save"); }
                            root.webdav-save-settings(
                                root.webdav-enabled,
                                root.webdav-url-text,
                                root.webdav-username-text,
                                root.webdav-password-text);
                            root.app-config-save(
                                root.max-tabs-text,
                                root.terminal-font-size-text,
                                root.sftp-font-size-text,
                                root.background-mode,
                                root.background-blur-text,
                                root.terminal-opacity-text,
                                root.ui-opacity-text,
                                root.ui-debug-ids,
                                root.config-dir-text);
                        }
                    }
                }
            }
        }
    }

    // --- About dialog (centered on the window, with dim backdrop) ---------
    Rectangle {
        width: parent.width;
        height: parent.height;
        visible: root.about-open;
        background: #00000080;            // dim backdrop
        TouchArea { clicked => { root.about-open = false; } }

        Rectangle {
            x: (parent.width - self.width) / 2;
            y: (parent.height - self.height) / 2;
            width: 380px;
            height: 440px;
            background: Theme.bg-panel;
            border-radius: Theme.radius-md;
            border-width: 1px;
            border-color: Theme.border-strong;
            drop-shadow-blur: 24px;
            drop-shadow-color: #000000a0;

            // Swallow clicks so the backdrop doesn't close when clicking inside.
            TouchArea {}

            VerticalLayout {
                padding: 18px;
                spacing: 8px;

                HorizontalLayout {
                    Text {
                        text: @tr("About meatshell");
                        color: Theme.text-primary;
                        font-size: Theme.fs-lg;
                        font-weight: 700;
                        horizontal-stretch: 1;
                        vertical-alignment: center;
                    }
                    Rectangle {
                        width: 22px; height: 22px;
                        border-radius: Theme.radius-sm;
                        background: ab-close-ta.has-hover ? Theme.bg-hover : transparent;
                        ab-close-ta := TouchArea {
                            mouse-cursor: pointer;
                            clicked => { root.about-open = false; }
                        }
                        Text { text: "\u{E5CD}"; font-family: "Material Icons";
                               color: Theme.text-secondary; font-size: Theme.fs-sm;
                               width: parent.width; height: parent.height;
                               horizontal-alignment: center; vertical-alignment: center; }
                    }
                }

                Text {
                    text: @tr("A lightweight Rust + Slint SSH terminal client by 'lil meatball'.");
                    color: Theme.text-secondary;
                    font-size: Theme.fs-sm;
                    wrap: word-wrap;
                }
                Text {
                    text: @tr("Open source · MIT / Apache-2.0");
                    color: Theme.text-muted;
                    font-size: Theme.fs-xs;
                }

                Rectangle { height: 1px; background: Theme.border-subtle; }

                Text {
                    text: @tr("Open-source libraries used");
                    color: Theme.text-secondary;
                    font-size: Theme.fs-sm;
                }

                Flickable {
                    vertical-stretch: 1;
                    viewport-width: self.width;
                    viewport-height: max(self.height, libs-col.preferred-height);
                    libs-col := VerticalLayout {
                        alignment: start;
                        spacing: 4px;
                        for lib in root.about-libs : Text {
                            text: lib;
                            color: Theme.text-primary;
                            font-size: Theme.fs-xs;
                            wrap: no-wrap;
                            overflow: elide;
                        }
                    }
                }
            }
        }
    }

    // --- Connection folder dialog ----------------------------------------
    Rectangle {
        width: parent.width;
        height: parent.height;
        visible: root.folder-dialog-open;
        background: #00000070;
        TouchArea { clicked => { root.folder-dialog-open = false; } }

        Rectangle {
            x: (parent.width - self.width) / 2;
            y: (parent.height - self.height) / 2;
            width: min(360px, parent.width - 48px);
            height: 194px;
            background: Theme.bg-panel;
            border-radius: Theme.radius-md;
            border-width: 1px;
            border-color: Theme.border-strong;
            drop-shadow-blur: 20px;
            drop-shadow-color: #00000080;

            TouchArea {}

            VerticalLayout {
                padding: 16px;
                spacing: 12px;

                Text {
                    text: root.folder-dialog-mode == "rename" ? @tr("Rename category") : @tr("New category");
                    color: Theme.text-primary;
                    font-size: Theme.fs-md;
                    font-weight: 600;
                }

                Rectangle {
                    height: 32px;
                    border-radius: Theme.radius-sm;
                    border-width: 1px;
                    border-color: folder-name-input.has-focus ? Theme.accent : Theme.border-subtle;
                    background: Theme.bg-root;
                    folder-name-input := TextInput {
                        x: 10px;
                        width: parent.width - 20px;
                        height: parent.height;
                        text <=> root.folder-draft;
                        color: Theme.text-primary;
                        font-size: Theme.fs-md;
                        single-line: true;
                        vertical-alignment: center;
                        edited => { root.folder-error = ""; }
                        init => { self.focus(); }
                        key-pressed(e) => {
                            if (e.text == "\n") {
                                if (root.folder-dialog-mode == "rename") {
                                    root.connection-folder-rename(root.folder-edit-original, root.folder-draft);
                                } else {
                                    root.connection-folder-create(root.folder-draft);
                                }
                                accept
                            } else {
                                reject
                            }
                        }
                    }
                    if root.folder-draft == "" : Text {
                        x: 10px;
                        height: parent.height;
                        text: @tr("Category name");
                        color: Theme.text-muted;
                        font-size: Theme.fs-md;
                        vertical-alignment: center;
                    }
                }

                Text {
                    height: 14px;
                    text: root.folder-error;
                    color: Theme.danger;
                    font-size: Theme.fs-xs;
                    visible: root.folder-error != "";
                }

                HorizontalLayout {
                    height: 28px;
                    spacing: 8px;
                    Rectangle { horizontal-stretch: 1; }
                    Rectangle {
                        width: 72px;
                        height: parent.height;
                        border-radius: Theme.radius-sm;
                        background: folder-cancel-ta.has-hover ? Theme.bg-hover : Theme.bg-elevated;
                        folder-cancel-ta := TouchArea {
                            mouse-cursor: pointer;
                            clicked => { root.folder-dialog-open = false; }
                        }
                        Text {
                            width: parent.width;
                            height: parent.height;
                            text: @tr("Cancel");
                            color: Theme.text-primary;
                            font-size: Theme.fs-sm;
                            horizontal-alignment: center;
                            vertical-alignment: center;
                        }
                    }
                    Rectangle {
                        width: 72px;
                        height: parent.height;
                        border-radius: Theme.radius-sm;
                        background: folder-create-ta.has-hover ? Theme.accent-hover : Theme.accent;
                        folder-create-ta := TouchArea {
                            mouse-cursor: pointer;
                            clicked => {
                                if (root.folder-dialog-mode == "rename") {
                                    root.connection-folder-rename(root.folder-edit-original, root.folder-draft);
                                } else {
                                    root.connection-folder-create(root.folder-draft);
                                }
                            }
                        }
                        Text {
                            width: parent.width;
                            height: parent.height;
                            text: root.folder-dialog-mode == "rename" ? @tr("Rename") : @tr("Create");
                            color: #ffffff;
                            font-size: Theme.fs-sm;
                            horizontal-alignment: center;
                            vertical-alignment: center;
                        }
                    }
                }
            }
        }
    }

    // --- Modal dialog -----------------------------------------------------
    SessionDialog {
        width: parent.width;
        height: parent.height;
        is-open <=> root.dialog-open;
        is-editing <=> root.dialog-editing;
        draft-id <=> root.dialog-id;
        draft-name <=> root.dialog-name;
        draft-group <=> root.dialog-group;
        draft-host <=> root.dialog-host;
        draft-port <=> root.dialog-port;
        draft-user <=> root.dialog-user;
        draft-auth <=> root.dialog-auth;
        draft-password <=> root.dialog-password;
        draft-key-path <=> root.dialog-key-path;
        draft-proxy <=> root.dialog-proxy;
        draft-kind <=> root.dialog-kind;
        draft-serial-port <=> root.dialog-serial-port;
        draft-baud <=> root.dialog-baud;
        draft-data-bits <=> root.dialog-data-bits;
        draft-stop-bits <=> root.dialog-stop-bits;
        draft-parity <=> root.dialog-parity;
        draft-flow <=> root.dialog-flow;
        folders: root.connection-folder-names;
        submit(draft) => { root.session-dialog-submit(draft); }
        cancel => { root.session-dialog-cancel(); }
        pick-key-file => { root.session-dialog-pick-key(); }
    }

    // --- Delete confirmation (#28) ----------------------------------------
    ConfirmDialog {
        width: parent.width;
        height: parent.height;
        is-open <=> root.confirm-delete-open;
        title: @tr("Confirm delete");
        message: @tr("Delete this item? This cannot be undone.");
        detail: root.confirm-delete-path;
        confirm-label: @tr("Delete");
        confirm => {
            root.sftp-delete(root.confirm-delete-tab, root.confirm-delete-path);
            root.confirm-delete-open = false;
        }
        cancel => { root.confirm-delete-open = false; }
    }
}
