// One place for the look: colors, spacing, fonts. The window, the cards and // the dialogs all read from here, so re-theming (or swapping in Kirigami's // Kirigami.Theme) is a single file. pragma Singleton import QtQuick QtObject { // Breeze-dark-ish (the desktop the app is built for), no hard contrast. readonly property color bg: "#15181a" readonly property color surface: "#1e2225" readonly property color surfaceAlt: "#262b2f" readonly property color surfaceHi: "#313840" readonly property color border: "#343b41" readonly property color text: "#eff0f1" readonly property color textDim: "#9aa2a8" /* Faint is still text: small print (hints, secondary lines, a selected * row's detail) has to stay readable on both the background and the * accent fill, so it is a step lighter than it looks in a mockup. */ readonly property color textFaint: "#8d959c" readonly property color accent: "#3daee9" readonly property color accentDim: "#1d6f95" /* What is written *on* the accent fill (a selection, the open session). * Named "accentText...", not "onAccent...": QML reads any `onFoo` as a * signal handler and refuses the assignment. */ readonly property color accentText: "#ffffff" readonly property color accentTextDim: "#dceefb" /* The dark ink a filled button carries (accent, ok, err are all light). */ readonly property color accentInk: "#12161a" readonly property color ok: "#27ae60" readonly property color warn: "#f67400" readonly property color err: "#da4453" /* Green on the accent fill is mud: the "in use" mark needs its own ink. */ readonly property color okOnAccent: "#d8f5e3" readonly property int radius: 6 readonly property int radiusSm: 3 readonly property int gap: 8 readonly property int gapL: 14 readonly property int pad: 12 readonly property int padL: 16 readonly property int bodySize: 14 readonly property int smallSize: 12 readonly property int monoSize: 13 readonly property string mono: "monospace" readonly property int sidebarWidth: 268 readonly property int contentMax: 1100 // Layout: below the breakpoint the sidebar slides over the transcript // instead of taking a column, and controls stay thumb-sized above it // (a finger needs ~34-40 px, a mouse is happy with 26). readonly property int compactBreakpoint: 880 readonly property int touchTarget: 34 readonly property int segmentHeight: 30 readonly property int headerHeight: 42 readonly property int jumpButton: 40 // Which Breeze icon stands for a tool: the card shows at a glance what // kind of thing ran. Unknown names still get one (no glyph fallbacks for // tools -- a missing icon just leaves the name alone). function toolIcon(name) { const n = String(name).toLowerCase() if (n.indexOf("patch") >= 0 || n.indexOf("write") >= 0 || n.indexOf("edit") >= 0) return "document-edit" if (n.indexOf("read") >= 0 || n.indexOf("cat") >= 0) return "text-x-generic" if (n.indexOf("list_dir") >= 0 || n.indexOf("glob") >= 0 || n.indexOf("find") >= 0 || n.indexOf("dir") >= 0 || n.indexOf("file") >= 0) return "folder-open" if (n.indexOf("grep") >= 0 || n.indexOf("search") >= 0) return "edit-find" if (n.indexOf("bash") >= 0 || n.indexOf("shell") >= 0 || n.indexOf("command") >= 0 || n.indexOf("run") >= 0) return "code-context" if (n.indexOf("web") >= 0 || n.indexOf("http") >= 0 || n.indexOf("fetch") >= 0) return "internet-services" if (n.indexOf("todo") >= 0 || n.indexOf("plan") >= 0) return "format-list-unordered" if (n.indexOf("ask") >= 0 || n.indexOf("question") >= 0 || n.indexOf("notif") >= 0) return "help-hint" return "code-context" } // The tool output / diff line colors, used by ToolCard. function lineColor(line) { if (line.startsWith("@@")) return accent if (line.startsWith("+++") || line.startsWith("---")) return textDim if (line.startsWith("+")) return ok if (line.startsWith("-")) return err return text } }