refactor(ui): tokenize HUD overlay colors off raw Color() literals

p2-74 cluster 2 (HUD panels + notifications), overlays sub-cluster. Final 6 HUD
scripts onto ThemeAssets.color() tokens; completes the cluster-2 fence.

- hotkey_sheet: dim → background.overlay; panel → background.panel/border.panel;
  title/key labels → text.title; group headers → accent.gold; descriptions →
  text.primary; footer → text.muted; empty rows → text.disabled.
- overlay_panel: panel → background.panel/border.divider; active-lens font →
  semantic.positive; view-center label → text.muted.
- chronicle_panel: backdrop scrim → background.overlay.
- comms_renderer: dev heartbeat strip → background.hud/border.divider; per-event
  toast accents → accent.gold/goldResource, semantic.positive/negative/warning,
  player.purple (first-contact, sighting, blackout, new-capital, vision share,
  heartbeat sent/missed, envelope tap) — semantic, not inline RGB.
- debug_menu: dev panel → background.panel/semantic.diplomacy; button styleboxes
  → button.bgHover/bgPressed/background.raised + border.panel/focus; font →
  text.button/buttonHover; find label → text.secondary.
- tutorial_overlay: dim → background.overlay; panel → background.panel/border.panel;
  title → text.title; counter → text.muted; body → text.primary; action badge →
  semantic.positive (done) / semantic.warning (required).

Visual-only; no logic change (Rail 3). 0 inline Color() remain across the entire
cluster-2 fence (named hud panels + notifications). All edited scripts compile
with autoloads present (GATE_OK).

Proof: hotkey_sheet_proof.tscn captured on apricot (headless weston) shows the
themed purple panel, gold border/title, gold group headers, primary-text
descriptions, and the muted "(no bindings yet)" empty row.
.project/screenshots/p2-74-cluster2-hotkey-sheet.png

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
autocommit 2026-06-04 21:18:44 -07:00
parent d2ebec0eba
commit db309a4236
7 changed files with 45 additions and 45 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View file

@ -68,7 +68,7 @@ func _build_ui() -> void:
func _build_background(parent: Control) -> void:
_background = ColorRect.new()
_background.name = "Background"
_background.color = Color(0.0, 0.0, 0.0, 0.6)
_background.color = ThemeAssets.color("background.overlay")
_background.set_anchors_preset(Control.PRESET_FULL_RECT)
_background.mouse_filter = Control.MOUSE_FILTER_IGNORE
parent.add_child(_background)

View file

@ -80,8 +80,8 @@ func _build_ui() -> void:
_dev_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
var dev_style: StyleBoxFlat = StyleBoxFlat.new()
dev_style.bg_color = Color(0.0, 0.0, 0.0, 0.65)
dev_style.border_color = Color(0.5, 0.5, 0.5, 0.8)
dev_style.bg_color = ThemeAssets.color("background.hud")
dev_style.border_color = ThemeAssets.color("border.divider")
dev_style.set_border_width_all(1)
dev_style.content_margin_left = 8
dev_style.content_margin_right = 8
@ -148,7 +148,7 @@ func _on_player_discovered(payload: Dictionary) -> void:
name_str = pn
var title: String = str(strings.get("toast_title", "First Contact"))
var body: String = str(strings.get("toast_body_fmt", "First contact — %s.")) % name_str
_spawn_toast(title, body, Color(0.85, 0.78, 0.40, 1.0))
_spawn_toast(title, body, ThemeAssets.color("accent.gold"))
func _on_city_spotted(payload: Dictionary) -> void:
@ -160,7 +160,7 @@ func _on_city_spotted(payload: Dictionary) -> void:
var fmt: String = str(strings.get("toast_body_fmt", "Spotted %s settlement at (%d, %d)."))
var owner_str: String = "Clan %d" % owner_id
var body: String = fmt % [owner_str, col_v, row_v]
_spawn_toast(title, body, Color(0.95, 0.85, 0.35, 1.0))
_spawn_toast(title, body, ThemeAssets.color("accent.goldResource"))
func _on_unit_spotted(_payload: Dictionary) -> void:
@ -181,7 +181,7 @@ func _on_capital_blackout_began(payload: Dictionary) -> void:
var toast_title: String = str(strings.get("toast_title", "Capital Blackout"))
var fmt: String = str(strings.get("toast_body_fmt", "%s's capital has fallen."))
var pname: String = "Clan %d" % affected
_spawn_toast(toast_title, fmt % pname, Color(1.0, 0.45, 0.45, 1.0))
_spawn_toast(toast_title, fmt % pname, ThemeAssets.color("semantic.negative"))
func _on_capital_blackout_ended(payload: Dictionary) -> void:
@ -193,7 +193,7 @@ func _on_capital_blackout_ended(payload: Dictionary) -> void:
var title: String = str(strings.get("toast_title", "New Seat of Power"))
var fmt: String = str(strings.get("toast_body_fmt", "New seat of power: %s."))
var city_name: String = str(payload.get("new_capital_city_id", "?"))
_spawn_toast(title, fmt % city_name, Color(0.55, 0.95, 0.55, 1.0))
_spawn_toast(title, fmt % city_name, ThemeAssets.color("semantic.positive"))
func _on_envelope_tapped(payload: Dictionary) -> void:
@ -209,7 +209,7 @@ func _on_envelope_tapped(payload: Dictionary) -> void:
var fmt: String = str(
strings.get("toast_body_fmt", "Beacon at (%d, %d) intercepted enemy comms (%s).")
)
_spawn_toast(title, fmt % [col_v, row_v, pkind], Color(0.55, 0.40, 0.85, 1.0))
_spawn_toast(title, fmt % [col_v, row_v, pkind], ThemeAssets.color("player.purple"))
func _on_heartbeat_sent(payload: Dictionary) -> void:
@ -220,7 +220,7 @@ func _on_heartbeat_sent(payload: Dictionary) -> void:
var agid: int = int(payload.get("agreement_id", 0))
var sender: int = int(payload.get("sender", -1))
var recipient: int = int(payload.get("recipient", -1))
_push_dev_line(fmt % [agid, sender, recipient], Color(0.6, 0.85, 0.6, 1.0))
_push_dev_line(fmt % [agid, sender, recipient], ThemeAssets.color("semantic.positive"))
func _on_heartbeat_missed(payload: Dictionary) -> void:
@ -233,7 +233,7 @@ func _on_heartbeat_missed(payload: Dictionary) -> void:
var agid: int = int(payload.get("agreement_id", 0))
var expected: int = int(payload.get("expected_by_turn", 0))
var count: int = int(payload.get("missed_count", 0))
_push_dev_line(fmt % [agid, expected, count], Color(1.0, 0.55, 0.40, 1.0))
_push_dev_line(fmt % [agid, expected, count], ThemeAssets.color("semantic.warning"))
func _on_vision_share_collapsed(payload: Dictionary) -> void:
@ -243,7 +243,7 @@ func _on_vision_share_collapsed(payload: Dictionary) -> void:
var title: String = str(strings.get("toast_title", "Vision Share Severed"))
var fmt: String = str(strings.get("toast_body_fmt", "Shared vision with ally collapsed (%s)."))
var reason: String = str(payload.get("reason", "unknown"))
_spawn_toast(title, fmt % reason, Color(1.0, 0.55, 0.55, 1.0))
_spawn_toast(title, fmt % reason, ThemeAssets.color("semantic.negative"))
func _on_vision_share_restored(payload: Dictionary) -> void:
@ -252,7 +252,7 @@ func _on_vision_share_restored(payload: Dictionary) -> void:
_vision_share_state[agid] = "active"
var title: String = str(strings.get("toast_title", "Vision Share Restored"))
var body: String = str(strings.get("toast_body_fmt", "Shared vision with ally restored."))
_spawn_toast(title, body, Color(0.55, 0.95, 0.55, 1.0))
_spawn_toast(title, body, ThemeAssets.color("semantic.positive"))
# -- Render helpers ----------------------------------------------------------

View file

@ -83,8 +83,8 @@ func _on_turn_during_advance(turn_number: int, player_index: int) -> void:
func _apply_panel_style() -> void:
var style: StyleBoxFlat = StyleBoxFlat.new()
style.bg_color = Color(0.08, 0.04, 0.04, 0.85)
style.border_color = Color(0.7, 0.4, 0.25, 0.8)
style.bg_color = ThemeAssets.color("background.panel")
style.border_color = ThemeAssets.color("semantic.diplomacy")
style.set_border_width_all(1)
style.set_corner_radius_all(4)
add_theme_stylebox_override("panel", style)
@ -92,23 +92,23 @@ func _apply_panel_style() -> void:
func _apply_button_style(btn: Button) -> void:
var normal: StyleBoxFlat = StyleBoxFlat.new()
normal.bg_color = Color(0.12, 0.06, 0.04, 0.8)
normal.border_color = Color(0.65, 0.35, 0.2, 0.7)
normal.bg_color = ThemeAssets.color("button.bgHover")
normal.border_color = ThemeAssets.color("border.panel")
normal.set_border_width_all(1)
normal.set_corner_radius_all(4)
var hover: StyleBoxFlat = normal.duplicate()
hover.bg_color = Color(0.18, 0.09, 0.06, 0.9)
hover.border_color = Color(0.8, 0.5, 0.3, 0.9)
hover.bg_color = ThemeAssets.color("button.bgPressed")
hover.border_color = ThemeAssets.color("border.focus")
var pressed_style: StyleBoxFlat = normal.duplicate()
pressed_style.bg_color = Color(0.06, 0.03, 0.02, 0.9)
pressed_style.bg_color = ThemeAssets.color("background.raised")
btn.add_theme_stylebox_override("normal", normal)
btn.add_theme_stylebox_override("hover", hover)
btn.add_theme_stylebox_override("pressed", pressed_style)
btn.add_theme_color_override("font_color", Color(0.9, 0.7, 0.5, 1.0))
btn.add_theme_color_override("font_hover_color", Color(1.0, 0.85, 0.65, 1.0))
btn.add_theme_color_override("font_color", ThemeAssets.color("text.button"))
btn.add_theme_color_override("font_hover_color", ThemeAssets.color("text.buttonHover"))
func _build_find_ui() -> void:
@ -142,7 +142,7 @@ func _build_find_ui() -> void:
_find_label = Label.new()
_find_label.text = ""
_find_label.add_theme_font_size_override("font_size", 12)
_find_label.add_theme_color_override("font_color", Color(0.8, 0.7, 0.5))
_find_label.add_theme_color_override("font_color", ThemeAssets.color("text.secondary"))
row.add_child(_find_label)
var vbox: VBoxContainer = null

View file

@ -45,7 +45,7 @@ func _ready() -> void:
func _build_ui() -> void:
var dim: ColorRect = ColorRect.new()
dim.color = Color(0.0, 0.0, 0.0, 0.55)
dim.color = ThemeAssets.color("background.overlay")
dim.anchor_right = 1.0
dim.anchor_bottom = 1.0
dim.mouse_filter = Control.MOUSE_FILTER_STOP
@ -78,7 +78,7 @@ func _build_ui() -> void:
var title: Label = Label.new()
title.text = ThemeVocabulary.lookup("hotkey_sheet_title")
title.add_theme_font_size_override("font_size", 24)
title.add_theme_color_override("font_color", Color(0.95, 0.82, 0.3))
title.add_theme_color_override("font_color", ThemeAssets.color("text.title"))
vbox.add_child(title)
_grid = GridContainer.new()
@ -93,7 +93,7 @@ func _build_ui() -> void:
var footer: Label = Label.new()
footer.text = ThemeVocabulary.lookup("hotkey_sheet_footer")
footer.add_theme_font_size_override("font_size", 12)
footer.add_theme_color_override("font_color", Color(0.7, 0.65, 0.45, 0.9))
footer.add_theme_color_override("font_color", ThemeAssets.color("text.muted"))
footer.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
vbox.add_child(footer)
@ -192,7 +192,7 @@ func _add_group_header(grid: GridContainer, text: String) -> void:
var header: Label = Label.new()
header.text = text
header.add_theme_font_size_override("font_size", 15)
header.add_theme_color_override("font_color", Color(0.9, 0.75, 0.35))
header.add_theme_color_override("font_color", ThemeAssets.color("accent.gold"))
grid.add_child(header)
@ -200,13 +200,13 @@ func _add_row(grid: GridContainer, keys: String, description: String) -> void:
var key_label: Label = Label.new()
key_label.text = keys
key_label.add_theme_font_size_override("font_size", 13)
key_label.add_theme_color_override("font_color", Color(0.95, 0.85, 0.55))
key_label.add_theme_color_override("font_color", ThemeAssets.color("text.title"))
key_label.custom_minimum_size = Vector2(140, 0)
grid.add_child(key_label)
var desc_label: Label = Label.new()
desc_label.text = description
desc_label.add_theme_font_size_override("font_size", 13)
desc_label.add_theme_color_override("font_color", Color(0.85, 0.8, 0.72))
desc_label.add_theme_color_override("font_color", ThemeAssets.color("text.primary"))
grid.add_child(desc_label)
@ -214,13 +214,13 @@ func _add_empty_row(grid: GridContainer) -> void:
var left: Label = Label.new()
left.text = ""
left.add_theme_font_size_override("font_size", 13)
left.add_theme_color_override("font_color", Color(0.55, 0.5, 0.4))
left.add_theme_color_override("font_color", ThemeAssets.color("text.disabled"))
left.custom_minimum_size = Vector2(140, 0)
grid.add_child(left)
var right: Label = Label.new()
right.text = ThemeVocabulary.lookup("hotkey_group_empty")
right.add_theme_font_size_override("font_size", 13)
right.add_theme_color_override("font_color", Color(0.55, 0.5, 0.4))
right.add_theme_color_override("font_color", ThemeAssets.color("text.disabled"))
grid.add_child(right)
@ -255,8 +255,8 @@ func _unhandled_input(event: InputEvent) -> void:
func _apply_panel_style(panel: PanelContainer) -> void:
var style: StyleBoxFlat = StyleBoxFlat.new()
style.bg_color = Color(0.06, 0.05, 0.09, 0.96)
style.border_color = Color(0.6, 0.45, 0.12, 0.9)
style.bg_color = ThemeAssets.color("background.panel")
style.border_color = ThemeAssets.color("border.panel")
style.set_border_width_all(2)
style.set_corner_radius_all(6)
panel.add_theme_stylebox_override("panel", style)

View file

@ -110,7 +110,7 @@ func _build_view_center_section() -> void:
var view_label: Label = Label.new()
view_label.text = ThemeVocabulary.lookup("view_center")
view_label.add_theme_font_size_override("font_size", 10)
view_label.add_theme_color_override("font_color", Color(0.7, 0.65, 0.45, 0.9))
view_label.add_theme_color_override("font_color", ThemeAssets.color("text.muted"))
add_child(view_label)
_btn_view_equator = Button.new()
@ -196,8 +196,8 @@ func _update_button_states() -> void:
func _set_active(btn: Button, active: bool) -> void:
if active:
btn.add_theme_color_override("font_color", Color(0.15, 0.9, 0.4, 1.0))
btn.add_theme_color_override("font_pressed_color", Color(0.15, 0.9, 0.4, 1.0))
btn.add_theme_color_override("font_color", ThemeAssets.color("semantic.positive"))
btn.add_theme_color_override("font_pressed_color", ThemeAssets.color("semantic.positive"))
else:
btn.remove_theme_color_override("font_color")
btn.remove_theme_color_override("font_pressed_color")
@ -219,8 +219,8 @@ func _update_view_button_states() -> void:
func _apply_panel_style() -> void:
var style: StyleBoxFlat = StyleBoxFlat.new()
style.bg_color = Color(0.05, 0.05, 0.08, 0.82)
style.border_color = Color(0.25, 0.22, 0.12, 0.85)
style.bg_color = ThemeAssets.color("background.panel")
style.border_color = ThemeAssets.color("border.divider")
style.set_border_width_all(1)
style.set_corner_radius_all(3)
add_theme_stylebox_override("panel", style)

View file

@ -78,7 +78,7 @@ func _exit_tree() -> void:
func _build_ui() -> void:
var dim: ColorRect = ColorRect.new()
dim.name = "Dim"
dim.color = Color(0.0, 0.0, 0.0, 0.55)
dim.color = ThemeAssets.color("background.overlay")
dim.anchor_right = 1.0
dim.anchor_bottom = 1.0
## p0-33: must PASS so the dim overlay does not eat clicks meant for the
@ -113,17 +113,17 @@ func _build_ui() -> void:
_title_label = Label.new()
_title_label.add_theme_font_size_override("font_size", 24)
_title_label.add_theme_color_override("font_color", Color(0.95, 0.82, 0.3))
_title_label.add_theme_color_override("font_color", ThemeAssets.color("text.title"))
vbox.add_child(_title_label)
_step_counter_label = Label.new()
_step_counter_label.add_theme_font_size_override("font_size", 12)
_step_counter_label.add_theme_color_override("font_color", Color(0.7, 0.65, 0.45, 0.9))
_step_counter_label.add_theme_color_override("font_color", ThemeAssets.color("text.muted"))
vbox.add_child(_step_counter_label)
_body_label = Label.new()
_body_label.add_theme_font_size_override("font_size", 15)
_body_label.add_theme_color_override("font_color", Color(0.88, 0.82, 0.72))
_body_label.add_theme_color_override("font_color", ThemeAssets.color("text.primary"))
_body_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
_body_label.size_flags_vertical = Control.SIZE_EXPAND_FILL
vbox.add_child(_body_label)
@ -180,9 +180,9 @@ func _render_step() -> void:
func _render_action_badge(prefix: String) -> void:
if _step_satisfied:
_action_badge.text = ThemeVocabulary.lookup("tutorial_action_done")
_action_badge.add_theme_color_override("font_color", Color(0.55, 0.9, 0.55))
_action_badge.add_theme_color_override("font_color", ThemeAssets.color("semantic.positive"))
return
_action_badge.add_theme_color_override("font_color", Color(0.95, 0.7, 0.35))
_action_badge.add_theme_color_override("font_color", ThemeAssets.color("semantic.warning"))
var action_hint: String = ThemeVocabulary.lookup("%s_action" % prefix)
var header: String = ThemeVocabulary.lookup("tutorial_action_required")
_action_badge.text = ThemeVocabulary.lookup("fmt_tutorial_badge") % [header, action_hint]
@ -275,8 +275,8 @@ func _unhandled_key_input(event: InputEvent) -> void:
func _apply_panel_style(panel: PanelContainer) -> void:
var style: StyleBoxFlat = StyleBoxFlat.new()
style.bg_color = Color(0.06, 0.05, 0.09, 0.96)
style.border_color = Color(0.6, 0.45, 0.12, 0.9)
style.bg_color = ThemeAssets.color("background.panel")
style.border_color = ThemeAssets.color("border.panel")
style.set_border_width_all(2)
style.set_corner_radius_all(6)
panel.add_theme_stylebox_override("panel", style)