style: one PSI red for every busy camera badge, blue only for robot cooling

AUTO CENTERING, ROBOT MOUNTING/UNMOUNTING/DRYING and BEAMLINE BUSY each
had their own accent (purple, red, orange, yellow, maroon), so the sample
camera read as a per-activity rainbow instead of one "hands off" signal.
All busy states now share BUSY_PSI_RED; ROBOT COOLING keeps blue because
it is the long, harmless phase the operator should read as "wait".

The five near-identical BusyOverlayStyle blocks collapse into one
_animated() helper plus a text lookup, and the now-unused purple/orange/
red-badge constants are dropped from styles.py.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 14:14:55 +02:00
co-authored by Claude Fable 5.1
parent c842856fe0
commit 7c1efe4384
2 changed files with 21 additions and 84 deletions
+1 -12
View File
@@ -503,22 +503,11 @@ BOOKMARK_COLORS = {
"lime": "#179299", # teal — Latte has one green; teal keeps the pair distinct
}
# -- Busy overlay (per-source color coding) ---------------------------------
# -- Busy overlay: PSI red for every busy state, blue for robot cooling ------
# Catppuccin Latte accents; BORDER/DOT are 25%/20% mixes toward Latte base.
BUSY_YELLOW = "#df8e1d" # yellow
BUSY_YELLOW_BORDER = "#ebd8bf"
BUSY_YELLOW_DOT = "#ecddca"
BUSY_YELLOW_TEXT_DARK = "#4c4f69" # text
BUSY_PURPLE = "#8839ef" # mauve
BUSY_PURPLE_BORDER = "#d5c3f4"
BUSY_PURPLE_DOT = "#daccf4"
BUSY_RED_BADGE = "#d20f39" # red
BUSY_RED_FILL = "#d20f39" # red
BUSY_RED_BORDER = "#e8b8c6"
BUSY_RED_DOT = "#e9c4cf"
BUSY_ORANGE = "#fe640b" # peach
BUSY_ORANGE_BORDER = "#f3ceba"
BUSY_ORANGE_DOT = "#f2d5c6"
BUSY_BLUE = "#1e66f5" # blue
BUSY_BLUE_BORDER = "#bbcef5"
BUSY_BLUE_DOT = "#c5d5f5"
+20 -72
View File
@@ -11,23 +11,12 @@ from aare.gui.styles import (
BUSY_BLUE,
BUSY_BLUE_BORDER,
BUSY_BLUE_DOT,
BUSY_ORANGE,
BUSY_ORANGE_BORDER,
BUSY_ORANGE_DOT,
BUSY_PSI_RED,
BUSY_PSI_RED_BORDER,
BUSY_PSI_RED_DOT,
BUSY_PURPLE,
BUSY_PURPLE_BORDER,
BUSY_PURPLE_DOT,
BUSY_RED_BADGE,
BUSY_RED_BORDER,
BUSY_RED_DOT,
BUSY_RED_FILL,
BUSY_YELLOW,
BUSY_YELLOW_BORDER,
BUSY_YELLOW_DOT,
BUSY_YELLOW_TEXT_DARK,
SHADOW,
WHITE,
qcolor,
@@ -201,77 +190,36 @@ def build_busy_overlay_style(
# automation progress says the Center step is running. Checked before
# is_busy because the callers pass is_busy=False during alignment.
if auto_centering:
return BusyOverlayStyle(
text="AUTO CENTERING",
badge_bg=BUSY_PURPLE,
badge_fg=WHITE,
overlay_fill=qcolor(BUSY_PURPLE, 190),
overlay_border=qcolor(BUSY_PURPLE_BORDER, 235),
overlay_text=qcolor(WHITE),
accent_dot=BUSY_PURPLE_DOT,
animate=True,
)
return _animated("AUTO CENTERING", BUSY_PSI_RED, BUSY_PSI_RED_BORDER, BUSY_PSI_RED_DOT)
if not is_busy:
return None
activity_value = str(getattr(getattr(tell_state, "activity", None), "value", "") or "").lower()
if activity_value == "mounting":
return BusyOverlayStyle(
text="ROBOT MOUNTING",
badge_bg=BUSY_RED_BADGE,
badge_fg=WHITE,
overlay_fill=qcolor(BUSY_RED_FILL, 185),
overlay_border=qcolor(BUSY_RED_BORDER, 230),
overlay_text=qcolor(WHITE),
accent_dot=BUSY_RED_DOT,
animate=True,
)
if activity_value == "unmounting":
return BusyOverlayStyle(
text="ROBOT UNMOUNTING",
badge_bg=BUSY_ORANGE,
badge_fg=WHITE,
overlay_fill=qcolor(BUSY_ORANGE, 190),
overlay_border=qcolor(BUSY_ORANGE_BORDER, 230),
overlay_text=qcolor(WHITE),
accent_dot=BUSY_ORANGE_DOT,
animate=True,
)
if activity_value == "drying":
return BusyOverlayStyle(
text="ROBOT DRYING",
badge_bg=BUSY_YELLOW,
badge_fg=BUSY_YELLOW_TEXT_DARK,
overlay_fill=qcolor(BUSY_YELLOW, 195),
overlay_border=qcolor(BUSY_YELLOW_BORDER, 235),
overlay_text=qcolor(BUSY_YELLOW_TEXT_DARK),
accent_dot=BUSY_YELLOW_DOT,
animate=True,
)
# Cooling is the one robot phase that keeps its own (blue) color: it is
# long, harmless and the operator should read it as "wait" not "danger".
# Every other busy state shares the PSI red so the badge reads as one
# "hands off" signal instead of a per-activity rainbow.
if activity_value == "cooling":
return BusyOverlayStyle(
text="ROBOT COOLING",
badge_bg=BUSY_BLUE,
badge_fg=WHITE,
overlay_fill=qcolor(BUSY_BLUE, 190),
overlay_border=qcolor(BUSY_BLUE_BORDER, 235),
overlay_text=qcolor(WHITE),
accent_dot=BUSY_BLUE_DOT,
animate=True,
)
return _animated("ROBOT COOLING", BUSY_BLUE, BUSY_BLUE_BORDER, BUSY_BLUE_DOT)
text = {
"mounting": "ROBOT MOUNTING",
"unmounting": "ROBOT UNMOUNTING",
"drying": "ROBOT DRYING",
}.get(activity_value, "BEAMLINE BUSY")
return _animated(text, BUSY_PSI_RED, BUSY_PSI_RED_BORDER, BUSY_PSI_RED_DOT)
def _animated(text: str, base: str, border: str, dot: str) -> BusyOverlayStyle:
return BusyOverlayStyle(
text="BEAMLINE BUSY",
badge_bg=BUSY_PSI_RED,
text=text,
badge_bg=base,
badge_fg=WHITE,
overlay_fill=qcolor(BUSY_PSI_RED, 195),
overlay_border=qcolor(BUSY_PSI_RED_BORDER, 235),
overlay_fill=qcolor(base, 190),
overlay_border=qcolor(border, 235),
overlay_text=qcolor(WHITE),
accent_dot=BUSY_PSI_RED_DOT,
accent_dot=dot,
animate=True,
)