class_name ImplantNavStack extends Node ## Intra-app navigation stack for ImplantApp subclasses (#844, D-191). ## Mutation is synchronous: screen_changed fires before push/pop/replace returns. signal screen_changed(current_screen_id: String) var _stack: Array[String] = [] var _payloads: Array[Dictionary] = [] var _default_screen_id: String = "" func set_default(screen_id: String) -> void: _default_screen_id = screen_id func push(screen_id: String, payload: Dictionary = {}) -> void: _stack.append(screen_id) _payloads.append(payload) screen_changed.emit(screen_id) func pop() -> void: if _stack.is_empty(): push_warning("ImplantNavStack: pop() on empty stack") return _stack.pop_back() _payloads.pop_back() if not _stack.is_empty(): screen_changed.emit(_stack.back()) elif not _default_screen_id.is_empty(): push(_default_screen_id) func replace(screen_id: String, payload: Dictionary = {}) -> void: if not _stack.is_empty(): _stack.pop_back() _payloads.pop_back() _stack.append(screen_id) _payloads.append(payload) screen_changed.emit(screen_id) func reset_to_default() -> void: _stack.clear() _payloads.clear() if not _default_screen_id.is_empty(): push(_default_screen_id) func is_empty() -> bool: return _stack.is_empty() func push_default() -> void: if not _default_screen_id.is_empty(): push(_default_screen_id) func current() -> String: if _stack.is_empty(): return "" return _stack.back() func current_payload() -> Dictionary: if _payloads.is_empty(): return {} return _payloads.back()