diff --git a/src/pygui/ISC/HomePage.qml b/src/pygui/ISC/HomePage.qml index cede73d..c109de6 100644 --- a/src/pygui/ISC/HomePage.qml +++ b/src/pygui/ISC/HomePage.qml @@ -404,7 +404,7 @@ Rectangle { id: badgeLabel anchors.centerIn: parent text: deviceController.connectionStatus || "Disconnected" - color: "#111111" + color: Theme.statusBadgeText font.pixelSize: Theme.font2xs font.bold: true } diff --git a/src/pygui/ISC/Tabs/DataTab.qml b/src/pygui/ISC/Tabs/DataTab.qml index 2dd862e..38e58ae 100644 --- a/src/pygui/ISC/Tabs/DataTab.qml +++ b/src/pygui/ISC/Tabs/DataTab.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Controls +import QtQuick.Controls.impl import QtQuick.Layouts import ISC import ISC.Wafer @@ -124,7 +125,7 @@ Item { Layout.fillWidth: true implicitHeight: 38 radius: 4 - color: Qt.rgba(1, 1, 1, 0.02) + color: Theme.cardWash border.color: Theme.cardBorder border.width: 1 @@ -232,7 +233,7 @@ Item { Label { text: slotBox.filePath !== "" ? root.shortName(slotBox.filePath) - : (root.activeBox === slotBox.boxIndex ? "← Select file from left panel…" : "Click to select") + : (root.activeBox === slotBox.boxIndex ? "<- Select file from left panel..." : "Click to select") font.pixelSize: Theme.fontXs color: slotBox.filePath !== "" ? Theme.headingColor : Theme.bodyColor opacity: slotBox.filePath !== "" ? 1.0 : 0.6 @@ -248,14 +249,15 @@ Item { onClicked: slotBox.cleared() background: Rectangle { radius: Theme.radiusSm - color: parent.hovered ? Qt.rgba(1, 1, 1, 0.08) : "transparent" + color: parent.hovered ? Theme.flatButtonHover : "transparent" } - contentItem: Label { - text: "✕" + contentItem: IconImage { + source: "icons/x.svg" + width: 14; height: 14 + sourceSize.width: 14 + sourceSize.height: 14 color: Theme.bodyColor - font.pixelSize: Theme.fontSm - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + anchors.centerIn: parent } } } @@ -291,44 +293,54 @@ Item { background: Rectangle { radius: Theme.radiusSm - color: resetBtn.hovered ? Qt.rgba(1, 1, 1, 0.08) : "transparent" + color: resetBtn.hovered ? Theme.flatButtonHover : "transparent" } - contentItem: Label { - text: "↺" - font.pixelSize: Theme.fontLg + contentItem: IconImage { + source: "icons/rotate-ccw.svg" + width: 18; height: 18 + sourceSize.width: 18 + sourceSize.height: 18 color: Theme.bodyColor - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + anchors.centerIn: parent } ToolTip.visible: resetBtn.hovered ToolTip.text: "Reset comparison" } - - Label { - text: "Dynamic Time Warping Profile Matching" - font.pixelSize: Theme.fontSm - color: Theme.bodyColor - } } // ── Error Banner ─────────────────────────────────────────── Rectangle { Layout.fillWidth: true - Layout.preferredHeight: errorLabel.implicitHeight + 16 + Layout.preferredHeight: errorRow.implicitHeight + 16 visible: root.errorMessage !== "" - color: Qt.rgba(0.93, 0.27, 0.27, 0.15) - border.color: "#ef4444" + color: Theme.errorSurface + border.color: Theme.statusErrorColor border.width: 1 radius: Theme.radiusSm - Label { - id: errorLabel + RowLayout { + id: errorRow anchors.fill: parent anchors.margins: 8 - text: "⚠ " + root.errorMessage - color: "#fca5a5" - font.pixelSize: Theme.fontSm - wrapMode: Text.WordWrap + spacing: 8 + + IconImage { + source: "icons/triangle-alert.svg" + width: 16; height: 16 + sourceSize.width: 16 + sourceSize.height: 16 + color: Theme.errorTextSoft + Layout.alignment: Qt.AlignTop + } + + Label { + id: errorLabel + text: root.errorMessage + color: Theme.errorTextSoft + font.pixelSize: Theme.fontSm + wrapMode: Text.WordWrap + Layout.fillWidth: true + } } } @@ -402,9 +414,9 @@ Item { var plotH = height - padTop - padBottom var range = (maxV - minV) || 1 - ctx.strokeStyle = Qt.rgba(1, 1, 1, 0.08) + ctx.strokeStyle = Theme.chartGridLine ctx.lineWidth = 1 - ctx.fillStyle = Qt.rgba(1, 1, 1, 0.35) + ctx.fillStyle = Theme.chartAxisText ctx.font = "10px sans-serif" ctx.textAlign = "right" @@ -507,10 +519,14 @@ Item { visible: !root.hasSeries spacing: 8 - Label { + IconImage { Layout.alignment: Qt.AlignHCenter - text: root.comparing ? "" : "📊" - font.pixelSize: 32 + visible: !root.comparing + source: "icons/bar-chart.svg" + width: 32; height: 32 + sourceSize.width: 32 + sourceSize.height: 32 + color: Theme.sideMutedText } Label { Layout.alignment: Qt.AlignHCenter @@ -655,10 +671,13 @@ Item { anchors.centerIn: parent visible: root.compareSensorLayout.length === 0 || !enableOverlapCheck.checked spacing: 4 - Label { + IconImage { Layout.alignment: Qt.AlignHCenter - text: "🗺" - font.pixelSize: 24 + source: "icons/map.svg" + width: 24; height: 24 + sourceSize.width: 24 + sourceSize.height: 24 + color: Theme.sideMutedText } Label { Layout.alignment: Qt.AlignHCenter @@ -864,7 +883,7 @@ Item { label: "DTW ALIGNMENT DISTANCE" value: root.warpingDistance >= 0 ? root.warpingDistance.toFixed(2) : "--" valueColor: root.warpingDistance >= 0 - ? (root.warpingDistance < 50 ? "#6ee7b7" : root.warpingDistance < 100 ? "#fde047" : "#ef4444") + ? (root.warpingDistance < 50 ? Theme.metricGood : root.warpingDistance < 100 ? Theme.metricWarn : Theme.metricBad) : Theme.sideMutedText } ReadoutCard { @@ -878,7 +897,7 @@ Item { label: "MAX SENSOR DEVIATION" value: root.maxSensorDeviation >= 0 ? root.maxSensorDeviation.toFixed(2) + "°C" : "--" valueColor: root.maxSensorDeviation >= 0 - ? (root.maxSensorDeviation < 1.0 ? "#6ee7b7" : root.maxSensorDeviation < 3.0 ? "#fde047" : "#ef4444") + ? (root.maxSensorDeviation < 1.0 ? Theme.metricGood : root.maxSensorDeviation < 3.0 ? Theme.metricWarn : Theme.metricBad) : Theme.sideMutedText } } diff --git a/src/pygui/ISC/Tabs/SelectFileDialog.qml b/src/pygui/ISC/Tabs/SelectFileDialog.qml index 7a2c2b8..4928be5 100644 --- a/src/pygui/ISC/Tabs/SelectFileDialog.qml +++ b/src/pygui/ISC/Tabs/SelectFileDialog.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Controls +import QtQuick.Controls.impl import QtQuick.Layouts import Qt.labs.qmlmodels import ISC @@ -181,10 +182,17 @@ Dialog { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: 12 - text: "✕" implicitWidth: 32 implicitHeight: 32 onClicked: root.close() + contentItem: IconImage { + source: "icons/x.svg" + width: 14; height: 14 + sourceSize.width: 14 + sourceSize.height: 14 + color: Theme.buttonNeutralText + anchors.centerIn: parent + } } } diff --git a/src/pygui/ISC/Tabs/SettingsTab.qml b/src/pygui/ISC/Tabs/SettingsTab.qml index b16d3fe..0ad7858 100644 --- a/src/pygui/ISC/Tabs/SettingsTab.qml +++ b/src/pygui/ISC/Tabs/SettingsTab.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Controls +import QtQuick.Controls.impl import QtQuick.Layouts import QtQuick.Dialogs import ISC @@ -123,19 +124,17 @@ Item { ColorAnimation { duration: Theme.durationFast } } - Text { + IconImage { anchors.centerIn: parent - text: "✓" - font.pixelSize: Theme.fontMd - font.bold: true + source: "icons/check.svg" + width: 12; height: 12 + sourceSize.width: 12 + sourceSize.height: 12 color: Theme.panelBackground opacity: toggle.checked ? 1.0 : 0.0 Behavior on opacity { NumberAnimation { duration: Theme.durationFast } } - // Small nudge to center the checkmark perfectly - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter } } @@ -366,7 +365,7 @@ Item { width: 22 height: 22 radius: height / 2 - color: "white" + color: Theme.toggleThumb anchors.verticalCenter: parent.verticalCenter x: Theme.isDarkMode ? parent.width - width - 3 : 3 @@ -452,12 +451,9 @@ Item { } } - Label { + Row { anchors.centerIn: parent - text: "↓ Scroll for more" - font.pixelSize: Theme.fontSm - font.bold: true - color: Theme.bodyColor + spacing: 4 opacity: (settingsScroll.ScrollBar.vertical.position <= 0 && settingsScroll.contentHeight > settingsScroll.height) ? (scrollHintTimer.running ? 1 : 0) : 0 Behavior on opacity { @@ -465,6 +461,22 @@ Item { duration: 400 } } + + IconImage { + anchors.verticalCenter: parent.verticalCenter + source: "icons/chevron-down.svg" + width: 14; height: 14 + sourceSize.width: 14 + sourceSize.height: 14 + color: Theme.bodyColor + } + Label { + anchors.verticalCenter: parent.verticalCenter + text: "Scroll for more" + font.pixelSize: Theme.fontSm + font.bold: true + color: Theme.bodyColor + } } } } diff --git a/src/pygui/ISC/Tabs/StatusTab.qml b/src/pygui/ISC/Tabs/StatusTab.qml index 24ff99e..98fb309 100644 --- a/src/pygui/ISC/Tabs/StatusTab.qml +++ b/src/pygui/ISC/Tabs/StatusTab.qml @@ -1,6 +1,7 @@ import QtQuick import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Controls.impl import QtQuick.Dialogs import ISC @@ -211,7 +212,7 @@ ColumnLayout { id: statusPillText anchors.centerIn: parent text: root.isConnected ? "ACTIVE" : (root.isBusy ? deviceController.connectionStatus.replace("...", "").toUpperCase() : "INACTIVE") - color: "#111111" + color: Theme.statusBadgeText font.pixelSize: Theme.fontXs font.weight: Font.Bold font.family: Theme.uiFontFamily @@ -483,9 +484,12 @@ ColumnLayout { anchors.rightMargin: Theme.panelPadding spacing: 8 - Text { - text: "📄" - font.pixelSize: Theme.fontSm + IconImage { + source: "icons/file-text.svg" + width: 14; height: 14 + sourceSize.width: 14 + sourceSize.height: 14 + color: Theme.bodyColor visible: root.csvPath !== "" Layout.alignment: Qt.AlignVCenter } diff --git a/src/pygui/ISC/Tabs/components/ReadoutPanel.qml b/src/pygui/ISC/Tabs/components/ReadoutPanel.qml index 962b671..39d139b 100644 --- a/src/pygui/ISC/Tabs/components/ReadoutPanel.qml +++ b/src/pygui/ISC/Tabs/components/ReadoutPanel.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Controls +import QtQuick.Controls.impl import QtQuick.Layouts import ISC @@ -32,18 +33,17 @@ ColumnLayout { ColorAnimation { duration: Theme.durationFast } } - Text { + IconImage { anchors.centerIn: parent - text: "✓" - font.pixelSize: Theme.fontSm - font.bold: true + source: "../icons/check.svg" + width: 12; height: 12 + sourceSize.width: 12 + sourceSize.height: 12 color: Theme.panelBackground opacity: toggle.checked ? 1.0 : 0.0 Behavior on opacity { NumberAnimation { duration: Theme.durationFast } } - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter } } @@ -205,7 +205,7 @@ ColumnLayout { Item { Layout.fillWidth: true } Label { text: s.diff !== undefined ? s.diff : "—" - color: Theme.isDarkMode ? "#A78BFA" : "#8B5CF6" + color: Theme.diffAccent font.family: Theme.codeFontFamily font.pixelSize: Theme.fontMd font.bold: true diff --git a/src/pygui/ISC/Tabs/components/ReplaceSensorDialog.qml b/src/pygui/ISC/Tabs/components/ReplaceSensorDialog.qml index 5c1ea37..7e3de1e 100644 --- a/src/pygui/ISC/Tabs/components/ReplaceSensorDialog.qml +++ b/src/pygui/ISC/Tabs/components/ReplaceSensorDialog.qml @@ -64,7 +64,7 @@ Dialog { id: overrideTag anchors.centerIn: parent text: "OVERRIDE" - color: "white" + color: Theme.statusBadgeText font.pixelSize: Theme.fontXs font.bold: true font.letterSpacing: 1 diff --git a/src/pygui/ISC/Tabs/components/StreamStatsDialog.qml b/src/pygui/ISC/Tabs/components/StreamStatsDialog.qml index bd1cc6a..0eb47d6 100644 --- a/src/pygui/ISC/Tabs/components/StreamStatsDialog.qml +++ b/src/pygui/ISC/Tabs/components/StreamStatsDialog.qml @@ -1,6 +1,7 @@ import QtQuick import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Controls.impl import ISC // ===== Stream Stats Dialog ===== @@ -72,7 +73,6 @@ Popup { } Button { - text: "✕" flat: true Layout.preferredWidth: 32 Layout.preferredHeight: 32 @@ -82,11 +82,13 @@ Popup { radius: Theme.radiusXs color: parent.hovered ? Theme.buttonNeutralHover : "transparent" } - contentItem: Label { - text: parent.text + contentItem: IconImage { + source: "../icons/x.svg" + width: 14; height: 14 + sourceSize.width: 14 + sourceSize.height: 14 color: Theme.bodyColor - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + anchors.centerIn: parent } } } diff --git a/src/pygui/ISC/Tabs/icons/bar-chart.svg b/src/pygui/ISC/Tabs/icons/bar-chart.svg new file mode 100644 index 0000000..f5445d1 --- /dev/null +++ b/src/pygui/ISC/Tabs/icons/bar-chart.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/src/pygui/ISC/Tabs/icons/check.svg b/src/pygui/ISC/Tabs/icons/check.svg new file mode 100644 index 0000000..5abe152 --- /dev/null +++ b/src/pygui/ISC/Tabs/icons/check.svg @@ -0,0 +1,13 @@ + + + diff --git a/src/pygui/ISC/Tabs/icons/chevron-down.svg b/src/pygui/ISC/Tabs/icons/chevron-down.svg new file mode 100644 index 0000000..e70d30b --- /dev/null +++ b/src/pygui/ISC/Tabs/icons/chevron-down.svg @@ -0,0 +1,13 @@ + + + diff --git a/src/pygui/ISC/Tabs/icons/file-text.svg b/src/pygui/ISC/Tabs/icons/file-text.svg new file mode 100644 index 0000000..5227939 --- /dev/null +++ b/src/pygui/ISC/Tabs/icons/file-text.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/src/pygui/ISC/Tabs/icons/folder.svg b/src/pygui/ISC/Tabs/icons/folder.svg new file mode 100644 index 0000000..ef69b34 --- /dev/null +++ b/src/pygui/ISC/Tabs/icons/folder.svg @@ -0,0 +1,13 @@ + + + diff --git a/src/pygui/ISC/Tabs/icons/rotate-ccw.svg b/src/pygui/ISC/Tabs/icons/rotate-ccw.svg new file mode 100644 index 0000000..eb0fe34 --- /dev/null +++ b/src/pygui/ISC/Tabs/icons/rotate-ccw.svg @@ -0,0 +1,14 @@ + + + + diff --git a/src/pygui/ISC/Tabs/icons/triangle-alert.svg b/src/pygui/ISC/Tabs/icons/triangle-alert.svg new file mode 100644 index 0000000..4739ae8 --- /dev/null +++ b/src/pygui/ISC/Tabs/icons/triangle-alert.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/src/pygui/ISC/Tabs/icons/x.svg b/src/pygui/ISC/Tabs/icons/x.svg new file mode 100644 index 0000000..e317943 --- /dev/null +++ b/src/pygui/ISC/Tabs/icons/x.svg @@ -0,0 +1,14 @@ + + + + diff --git a/src/pygui/ISC/Theme.qml b/src/pygui/ISC/Theme.qml index a82cb68..c9a9c8f 100644 --- a/src/pygui/ISC/Theme.qml +++ b/src/pygui/ISC/Theme.qml @@ -7,18 +7,23 @@ import QtQuick // ============================================================================= // Sections: // 1. Mode flag -// 2. Typography +// 2. Typography (families, pixel sizes, weights) // 3. Motion -// 4. Tone palette (raw tones; everything else derives from these) -// 5. Surfaces (page / card / panel / workspace backgrounds) +// 4. Tone palette (raw tones; everything else derives from these) +// 5. Surfaces (page / card / panel / workspace backgrounds) // 6. Borders -// 7. Text (headings, body, panel titles) -// 8. Controls (fields, buttons, checkbox) -// 9. Tracks (pill toggle + scrollbar) -// 10. Tabs (footer tab bar) -// 11. Side rail -// 12. Status (success / warning / error) -// 13. Geometry (radius / border width / spacing / sizing) +// 7. Text (headings, body, panel titles) +// 8. Controls (fields, buttons, checkbox, toggle) +// 9. Interaction overlays (hover / active washes — mode-aware) +// 10. Tracks (pill toggle + scrollbar) +// 11. Tabs (mode toggle pills) +// 12. Side rail +// 13. Transport / toolbar +// 14. Status & badges (success / warning / error, badge text) +// 15. Sensor bands (wafer map dots) +// 16. Wafer family badges (source list avatars + accent bars) +// 17. Comparison & charts (metric grading, diff accent, canvas grid) +// 18. Geometry (radius / border width / spacing / sizing) // ============================================================================= // Based on Codex themes: // Dark (oscurange): surface #0B0B0F, ink #E6E6E6 @@ -29,7 +34,10 @@ QtObject { // ── 1. Mode ────────────────────────────────────────────────────────────── property bool isDarkMode: true - // ── 2. Typography ────────────────────────────────────────────────────── + // ── 2. Typography ──────────────────────────────────────────────────────── + readonly property string uiFontFamily: "Geist, Inter, system-ui, -apple-system, BlinkMacSystemFont, sans-serif" + readonly property string codeFontFamily: "\"Geist Mono\", ui-monospace, \"SFMono-Regular\", monospace" + // pixelSize scale — map to closest token, tune globally readonly property int font2xs: 9 // tiny metadata readonly property int fontXs: 11 // captions, micro labels @@ -44,22 +52,20 @@ QtObject { readonly property int fontWeightMedium: 500 readonly property int fontWeightBold: 700 - // ── 3. Motion ────────────────────────────────────────────────────────── + // ── 3. Motion ──────────────────────────────────────────────────────────── readonly property int durationFast: 120 // micro-interactions (focus ring, hover flash) readonly property int durationBase: 180 // standard transitions (pill switch, row select) readonly property int durationSlow: 260 // larger transitions (panel open/close) readonly property var easeStandard: Easing.OutCubic - // ── 4. Tone palette (Codex theme v1 inspired) ─────────────────────────── - readonly property string uiFontFamily: "Geist, Inter, system-ui, -apple-system, BlinkMacSystemFont, sans-serif" - readonly property string codeFontFamily: "\"Geist Mono\", ui-monospace, \"SFMono-Regular\", monospace" - + // ── 4. Tone palette (Codex theme v1 inspired) ──────────────────────────── readonly property color themeSurface: isDarkMode ? "#0B0B0F" : "#F9F9F7" readonly property color themeInk: isDarkMode ? "#E6E6E6" : "#2D2D2B" readonly property color themeAccent: isDarkMode ? "#F9B98C" : "#B87333" readonly property color themeSkill: isDarkMode ? "#479FFA" : "#3B82F6" // blue family both modes readonly property color themeAdded: isDarkMode ? "#40C977" : "#00C853" readonly property color themeRemoved: isDarkMode ? "#FA423E" : "#FF5F38" + readonly property color themeViolet: isDarkMode ? "#A78BFA" : "#8B5CF6" readonly property color tone100: themeSurface readonly property color tone150: isDarkMode ? "#101014" : "#F3F3F1" @@ -71,7 +77,7 @@ QtObject { readonly property color toneMute: isDarkMode ? "#A8A8A1" : "#85857E" readonly property color toneBorder: isDarkMode ? "#2D2D34" : "#D2D2CE" - // ── 3. Surfaces ────────────────────────────────────────────────────────── + // ── 5. Surfaces ────────────────────────────────────────────────────────── readonly property color pageBackground: tone100 readonly property color cardBackground: tone150 readonly property color panelBackground: tone150 @@ -79,7 +85,7 @@ QtObject { readonly property color responseBackground: tone150 readonly property color subtleSectionBackground: tone250 - // ── 4. Borders ─────────────────────────────────────────────────────────── + // ── 6. Borders ─────────────────────────────────────────────────────────── readonly property color cardBorder: toneBorder readonly property color cardSurfaceBorder: isDarkMode ? "#3A3A42" : "#C7C7C2" readonly property color responseBorder: toneBorder @@ -88,14 +94,14 @@ QtObject { readonly property color outerFrameBorder: isDarkMode ? "#3A3A42" : "#C7C7C2" readonly property color softBorder: isDarkMode ? "#24242A" : "#E4E4E1" - // ── 5. Text ────────────────────────────────────────────────────────────── + // ── 7. Text ────────────────────────────────────────────────────────────── readonly property color headingColor: toneText readonly property color bodyColor: toneMute readonly property color subheadingColor: toneMute readonly property color panelTitleText: toneMute readonly property color disabledText: toneMute - // ── 6. Controls ────────────────────────────────────────────────────────── + // ── 8. Controls ────────────────────────────────────────────────────────── // Fields readonly property color fieldBackground: isDarkMode ? "#101014" : "#FFFFFF" readonly property color fieldText: toneText @@ -111,32 +117,48 @@ QtObject { readonly property color primaryAccent: themeAccent // Checkbox readonly property color checkboxText: toneText + // Toggle switch thumb (white knob reads on both track colors) + readonly property color toggleThumb: "#FFFFFF" - // ── 7. Tracks (pill toggle, scrollbar thumb) ───────────────────────────── + // ── 9. Interaction overlays ────────────────────────────────────────────── + // Mode-aware washes. Never use raw Qt.rgba(1,1,1,x) in views: a white + // overlay is invisible on light-mode surfaces. + readonly property color listHoverBackground: isDarkMode ? Qt.rgba(1, 1, 1, 0.04) : Qt.rgba(0, 0, 0, 0.03) + readonly property color listActiveBackground: isDarkMode ? Qt.rgba(1, 1, 1, 0.06) : Qt.rgba(0, 0, 0, 0.05) + readonly property color flatButtonHover: isDarkMode ? Qt.rgba(1, 1, 1, 0.08) : Qt.rgba(0, 0, 0, 0.06) + readonly property color cardWash: isDarkMode ? Qt.rgba(1, 1, 1, 0.02) : Qt.rgba(0, 0, 0, 0.02) + + // ── 10. Tracks (pill toggle, scrollbar thumb) ──────────────────────────── readonly property color trackBackground: isDarkMode ? "#25252B" : "#E2E2DE" - // ── 8. Tabs (mode toggle pills) ────────────────────────────────────────── + // ── 11. Tabs (mode toggle pills) ───────────────────────────────────────── readonly property color tabActiveBackground: isDarkMode ? "#25252B" : "#FFFFFF" - // ── 9. Side rail ───────────────────────────────────────────────────────── + // ── 12. Side rail ──────────────────────────────────────────────────────── readonly property color sideRailBackground: tone150 readonly property color sidePanelBackground: isDarkMode ? "#151518" : "#F3F3F1" readonly property color sideActiveBackground: isDarkMode ? "#25252B" : "#FFFFFF" readonly property color sideBorder: toneBorder readonly property color sideMutedText: toneMute - // ── 10a. Transport / toolbar surfaces ──────────────────────────────────── + // ── 13. Transport / toolbar surfaces ───────────────────────────────────── readonly property color transportButtonBg: tone250 readonly property color transportButtonHover: tone300 readonly property color liveColor: themeAdded readonly property color recordColor: themeRemoved - // ── 10. Status ─────────────────────────────────────────────────────────── + // ── 14. Status & badges ────────────────────────────────────────────────── readonly property color statusSuccessColor: themeAdded readonly property color statusWarningColor: isDarkMode ? "#E8A817" : "#B8860B" // amber/yellow, separate from accent readonly property color statusErrorColor: themeRemoved + // Text placed ON a filled status pill / saturated chip: + readonly property color statusBadgeText: "#111111" // dark ink on bright status fills, both modes + readonly property color textOnColor: "#FFFFFF" // white text on deep saturated fills (avatars etc.) + // Error banner (soft red surface + readable red text) + readonly property color errorSurface: Qt.alpha(statusErrorColor, 0.15) + readonly property color errorTextSoft: isDarkMode ? "#FCA5A5" : "#B91C1C" - // -- 10b. Sensor bands (wafer map dots) + // ── 15. Sensor bands (wafer map dots) ──────────────────────────────────── readonly property color sensorInRange: statusSuccessColor // ponytail: high-temp shares error red — semantically correct (dangerous value), // re-hue if colorblind testing demands a different channel. @@ -145,7 +167,31 @@ QtObject { readonly property color waferRingColor: toneBorder readonly property color waferAxisColor: softBorder - // ── 11. Geometry ───────────────────────────────────────────────────────── + // ── 16. Wafer family badges (SourcePanel list) ─────────────────────────── + // Accent = left bar / outline shade; Fill = avatar circle behind textOnColor. + // Family grouping mirrors FileBrowser's waferType first-letter convention. + readonly property color familyBlueAccent: "#3B82F6" // A / E / P + readonly property color familyBlueFill: "#1D4ED8" + readonly property color familyGreenAccent: "#10B981" // B / C / D + readonly property color familyGreenFill: "#065F46" + readonly property color familyVioletAccent: "#8B5CF6" // Z + readonly property color familyVioletFill: "#7C3AED" + readonly property color familyNeutralFill: "#374151" // unknown family + + // ── 17. Comparison & charts ────────────────────────────────────────────── + // Metric grading for DTW readout cards (good → caution → bad). + // Dark values are pastel (readable on tone150); light values are deepened + // so they still pass on near-white cards. + readonly property color metricGood: isDarkMode ? "#6EE7B7" : "#059669" + readonly property color metricWarn: isDarkMode ? "#FDE047" : "#B45309" + readonly property color metricBad: isDarkMode ? "#EF4444" : "#DC2626" + // DIFF column accent in ReadoutPanel + readonly property color diffAccent: themeViolet + // Canvas chart primitives (DTW plot grid + axis labels) + readonly property color chartGridLine: isDarkMode ? Qt.rgba(1, 1, 1, 0.08) : Qt.rgba(0, 0, 0, 0.10) + readonly property color chartAxisText: isDarkMode ? Qt.rgba(1, 1, 1, 0.35) : Qt.rgba(0, 0, 0, 0.45) + + // ── 18. Geometry ───────────────────────────────────────────────────────── // Radius readonly property int radiusXs: 6 // fields, tight elements readonly property int radiusSm: 8 // buttons