diff --git a/Architecture-Client.md b/Architecture-Client.md
index d4b5763..6716623 100644
--- a/Architecture-Client.md
+++ b/Architecture-Client.md
@@ -1,69 +1,2707 @@
-# Tekton Dash Armageddon - Client Architecture
+
+
+# Tekton Armageddon - Client Architecture (Full Function Reference)
[Back to Home](./Home)
-## Core Game Flow
+Complete per-function reference for the Godot 4.7 client codebase. Every script, signal, autoload dependency, and cross-file relationship documented.
-Tekton uses a heavily decoupled Singleton (Autoload) architecture mixed with standard Godot High-Level Multiplayer RPCs.
+[Back to top](#top)
-1. **Boot:** `boot_screen.tscn` is the entry point. It verifies version via `GameUpdateManager`, downloads `patch.pck` if available, and then loads `login_screen.tscn`.
-2. **Auth:** `AuthManager` handles Nakama login/sessions. Upon success, loads `lobby.tscn`.
-3. **Lobby:** Players form parties, select game modes, and pull Gacha. `LobbyManager` holds the selected `game_mode` string.
-4. **Match Start:** Host transitions to `main.tscn`. The `Main` script inspects `LobbyManager.game_mode` and dynamically instantiates the correct Mode Manager (`GauntletManager`, `StopNGoManager`, etc.).
-5. **Spawning:** `main.gd` asks `PlayerManager` to instantiate `player.tscn` for all connected peers based on `GameStateManager` player IDs.
+## Table of Contents
-## Singletons & Autoloads (`scripts/managers/`)
+[Back to top](#top)
-There are ~74 manager scripts. Key singletons include:
+1. [Project Structure Overview](#1-project-structure-overview)
+2. [Autoloads / Singletons Index](#2-autoloads--singletons-index)
+3. [Service Layer](#3-service-layer)
+ - [3.1 NakamaManager](#31-nakamamanaager)
+ - [3.2 BackendService](#32-backendservice)
+ - [3.3 SteamworksManager](#33-steamworksmanager)
+4. [Core Managers](#4-core-managers)
+ - [4.1 AuthManager](#41-authmanager)
+ - [4.2 LobbyManager](#42-lobbymanager)
+ - [4.3 GameStateManager](#43-gamestatemanager)
+ - [4.4 PlayerManager](#44-playermanager)
+ - [4.5 EventBus](#45-eventbus)
+ - [4.6 GameMode / ModeConfig](#46-gamemode--modeconfig)
+5. [Player Subsystem Managers](#5-player-subsystem-managers)
+ - [5.1 PlayerMovementManager](#51-playermovementmanager)
+ - [5.2 PlayerInputManager](#52-playerinputmanager)
+ - [5.3 PlayerActionManager](#53-playeractionmanager)
+ - [5.4 PlayerboardManager](#54-playerboardmanager)
+ - [5.5 PowerupManager](#55-powerupmanager)
+6. [Game Mode Managers](#6-game-mode-managers)
+ - [6.1 StopNGoManager](#61-stopngomanager)
+ - [6.2 GauntletManager](#62-gauntletmanager)
+ - [6.3 PortalModeManager](#63-portalmode_manager)
+ - [6.4 GoalManager](#64-goalmanager)
+ - [6.5 GoalsCycleManager](#65-goalscyclemanager)
+ - [6.6 PlayerRaceManager](#66-playerracemanager)
+ - [6.7 TurnManager](#67-turnmanager)
+7. [Gameplay Managers](#7-gameplay-managers)
+ - [7.1 ObstacleManager](#71-obstaclemanager)
+ - [7.2 SpecialTilesManager](#72-specialtilesmanager)
+ - [7.3 StaticTektonManager](#73-statictektonmanager)
+8. [UI / Presentation Managers](#8-ui--presentation-managers)
+ - [8.1 UIManager](#81-uimanager)
+ - [8.2 SfxManager](#82-sfxmanager)
+ - [8.3 MusicManager](#83-musicmanager)
+ - [8.4 NotificationManager](#84-notificationmanager)
+ - [8.5 ScreenShake](#85-screenshake)
+ - [8.6 CameraContextManager](#86-cameracontextmanager)
+ - [8.7 TouchControls](#87-touchcontrols)
+ - [8.8 TutorialManager / TutorialOverlay](#88-tutorialmanager--tutorialoverlay)
+9. [Social / Economy Managers](#9-social--economy-managers)
+ - [9.1 UserProfileManager](#91-userprofilemanager)
+ - [9.2 GachaManager](#92-gachamanager)
+ - [9.3 SkinManager](#93-skinmanager)
+ - [9.4 ShopManager](#94-shopmanager)
+ - [9.5 JoinManager](#95-joinmanager)
+ - [9.6 FriendManager](#96-friendmanager)
+ - [9.7 MailManager](#97-mailmanager)
+ - [9.8 DailyRewardManager](#98-dailyrewardmanager)
+ - [9.9 AdminManager](#99-adminmanager)
+10. [System Managers](#10-system-managers)
+ - [10.1 SettingsManager](#101-settingsmanager)
+ - [10.2 SessionManager](#102-sessionmanager)
+ - [10.3 GameUpdateManager](#103-gameupdatemanager)
+11. [Core Scene Scripts](#11-core-scene-scripts)
+ - [11.1 main.gd (Main game scene controller)](#111-maingd-main-game-scene-controller)
+ - [11.2 player.gd](#112-playergd)
+ - [11.3 lobby.gd](#113-lobbygd)
+ - [11.4 animation.gd](#114-animationgd)
+12. [UI Helper Classes (RefCounted)](#12-ui-helper-classes-refcounted)
+ - [12.1 LobbyMainMenu](#121-lobbymainmenu)
+ - [12.2 LobbyRoom](#122-lobbyroom)
+ - [12.3 LobbyRoomList](#123-lobbyroomlist)
+ - [12.4 LobbyChat](#124-lobbychat)
+13. [Dependency Graph](#13-dependency-graph)
+ - [13.1 Manager Autoload Dependencies](#131-manager-autoload-dependencies)
+ - [13.2 Cross-Manager Signal Wiring](#132-cross-manager-signal-wiring)
+14. [Scene Node Trees](#14-scene-node-trees)
+ - [14.1 main.tscn](#141-maintscn)
+ - [14.2 player.tscn](#142-playertscn)
+ - [14.3 lobby.tscn](#143-lobbytscn)
-### State & Networking
-- **`NakamaManager` / `AuthManager`:** Connects to the backend VPS for authentication, leaderboards, storage (friends, inbox), and matchmaking.
-- **`LobbyManager`:** Tracks pre-match state, chat, room configuration, and connected peers.
-- **`GameStateManager`:** Tracks active players, bots, and the authoritative "match active" flags.
+[Back to top](#top)
-### Actor Control (`player.gd` delegates)
-- **`PlayerMovementManager`:** Validates and executes GridMap translation. `try_push()` handles collision/smacking mechanics.
-- **`PlayerInputManager`:** Reads keyboard/gamepad and touch inputs, polling every frame to instruct `PlayerMovementManager`.
-- **`PlayerActionManager`:** Handles grid interactions (grabbing, dropping) and tracks Action Points (AP).
-### Economy & Meta
-- **`UserProfileManager`:** Manages the authoritative `wallet` (Gold/Star balances), cosmetic inventory, and fragments. Fetches from Nakama Storage.
-- **`GachaManager`:** Reads backend gacha configs, calls Lua RPCs to roll, and grants fragments/skins.
-- **`SkinManager`:** Dynamically applies unlocked materials to base meshes.
+## 1. Project Structure Overview
-### Game Modes
-- **`StopNGoManager`:** Classic mode — green light / red light movement blocking.
-- **`GauntletManager`:** Candy Pump Survival — waves of expanding sticky bubbles, center cannon shooting projectiles, invisible ghost mechanics.
-- **`PortalModeManager`:** Tekton Doors — maze running and teleporters.
+[Back to top](#top)
-### UI & Render
-- **`UIManager`:** Binds `player.gd` state to CanvasLayers. Specifically handles the 5x5 Grid `playerboard_ui`.
-- **`SfxManager` / `MusicManager`:** Global audio pooling.
-
-## Major UI Components (`scenes/ui/`)
-
-- `lobby_main_menu.tscn`: Holds the primary game mode selection, Shop, and Gacha buttons.
-- `shop_panel.tscn`: Reads `UserProfileManager` to buy Gold (IAP) or convert Gold to Stars.
-- `gacha_panel.tscn`: 1x/10x pulls for Skins and Fragments.
-- `daily_reward_panel.tscn`: Daily login progression matrix.
-- `admin_panel.tscn`: Server moderation tools (requires Admin flag from Nakama).
-
-## Dependency Graph
-
-```mermaid
-flowchart TD
- LobbyManager -->|Match Start| Main[main.tscn]
- Main -->|Instantiates| PlayerManager
- PlayerManager -->|Spawns| Player[player.tscn]
-
- Main -->|Game Logic| ModeManagers[StopNGo/Gauntlet/Portal]
-
- Player -->|Delegates Input| PlayerInputManager
- PlayerInputManager -->|Commands| PlayerMovementManager
- PlayerMovementManager -->|Collisions| SfxManager
-
- Lobby[lobby.tscn] -->|Meta| UserProfileManager
- Lobby -->|Pulls| GachaManager
- UserProfileManager <--> NakamaManager
- GachaManager <--> NakamaManager
```
+/home/dev/tekton/
+ project.godot -- Godot 4.7 project file
+ scripts/
+ main.gd -- (NOT USED; logic lives in scenes/main.gd)
+ nakama_manager.gd -- Nakama network layer (autoload)
+ event_bus.gd -- Central observer pattern bus (autoload)
+ game_mode.gd -- GameMode enum + string utils (RefCounted)
+ mode_config.gd -- Schema-driven mode settings validation (RefCounted)
+ managers/ -- 39+ autoload manager singletons
+ auth_manager.gd
+ lobby_manager.gd
+ game_state_manager.gd
+ player_manager.gd
+ player_movement_manager.gd
+ player_input_manager.gd
+ player_action_manager.gd
+ user_profile_manager.gd
+ gacha_manager.gd
+ skin_manager.gd
+ ui_manager.gd
+ sfx_manager.gd
+ music_manager.gd
+ game_update_manager.gd
+ stop_n_go_manager.gd
+ gauntlet_manager.gd
+ portal_mode_manager.gd
+ turn_manager.gd
+ goal_manager.gd
+ goals_cycle_manager.gd
+ player_race_manager.gd
+ shop_manager.gd
+ join_manager.gd
+ powerup_manager.gd
+ notification_manager.gd
+ obstacle_manager.gd
+ friend_manager.gd
+ admin_manager.gd
+ mail_manager.gd
+ session_manager.gd
+ settings_manager.gd
+ tutorial_manager.gd
+ tutorial_overlay.gd
+ playerboard_manager.gd
+ camera_context_manager.gd
+ screen_shake.gd
+ special_tiles_manager.gd
+ static_tekton_manager.gd
+ touch_controls.gd
+ daily_reward_manager.gd
+ services/
+ backend_service.gd -- Unified RPC interface (autoload)
+ steamworks_manager.gd -- Steam auth ticket + persona (NOT autoload; child of BackendService)
+ scenes/
+ main.gd -- Core game scene controller (~2956 lines)
+ main.tscn -- Main game scene
+ player.gd -- Player character controller (~2751 lines)
+ player.tscn -- Player scene
+ lobby.gd -- Lobby/home screen controller (~583 lines)
+ lobby.tscn -- Lobby scene
+ animation.gd -- Stop n Go animation player (41 lines)
+ ui/
+ lobby_main_menu.gd -- RefCounted; main menu button wiring
+ lobby_room.gd -- RefCounted; room/player slot management
+ lobby_room_list.gd -- RefCounted; room list display + join
+ lobby_chat.gd -- RefCounted; global + DM chat
+ login_screen.tscn -- Login screen scene
+ boot_screen.tscn -- Boot splash scene
+ shop_panel.tscn -- Shop panel scene
+ gacha_panel.tscn -- Gacha panel scene
+ daily_reward_panel.tscn -- Daily reward panel scene
+ admin_panel.tscn -- Admin panel scene
+ profile_panel.tscn -- Profile panel scene
+ leaderboard_panel.tscn -- Leaderboard panel scene
+ mailbox_panel.tscn -- Mailbox panel scene
+ settings_menu.tscn -- Settings scene
+ lobby_invite_popup.tscn -- Invite popup scene
+ invite_friends_dialog.tscn -- Invite dialog scene
+ social_panel.tscn -- Social panel scene
+ game/
+ main.tscn -- (actual main game scene)
+ loading_screen/
+ loading_screen.tscn -- Level loading screen
+```
+
+[Back to top](#top)
+
+
+## 2. Autoloads / Singletons Index
+
+[Back to top](#top)
+
+All managers are registered as autoloads in project.godot and accessible globally via `/root/`. The following are the configured autoloads:
+
+| Autoload Name | File | Purpose |
+|---|---|---|
+| AuthManager | res://scripts/managers/auth_manager.gd | Authentication (guest, email, social) |
+| NakamaManager | res://scripts/nakama_manager.gd | Nakama client/socket/bridge lifecycle |
+| BackendService | res://scripts/services/backend_service.gd | Unified RPC API wrapper |
+| EventBus | res://scripts/event_bus.gd | Observer-pattern cross-manager events |
+| LobbyManager | res://scripts/managers/lobby_manager.gd | Room lifecycle, matchmaking |
+| GameStateManager | res://scripts/managers/game_state_manager.gd | State machine, match lifecycle |
+| PlayerManager | res://scripts/managers/player_manager.gd | Player data container |
+| PlayerMovementManager | res://scripts/managers/player_movement_manager.gd | Movement physics, pathfinding |
+| PlayerInputManager | res://scripts/managers/player_input_manager.gd | Input capture, buffering |
+| PlayerActionManager | res://scripts/managers/player_action_manager.gd | Action execution (grab, put) |
+| UserProfileManager | res://scripts/managers/user_profile_manager.gd | Profile CRUD, wallet sync |
+| GachaManager | res://scripts/managers/gacha_manager.gd | Gacha pull orchestration |
+| SkinManager | res://scripts/managers/skin_manager.gd | Cosmetics, skins, loadout |
+| UIManager | res://scripts/managers/ui_manager.gd | UI layer stack, show/hide |
+| SfxManager | res://scripts/managers/sfx_manager.gd | Sound effect pool |
+| MusicManager | res://scripts/managers/music_manager.gd | Music crossfade |
+| GameUpdateManager | res://scripts/managers/game_update_manager.gd | Hot-reload patching |
+| StopNGoManager | res://scripts/managers/stop_n_go_manager.gd | Stop n Go minigame state |
+| GauntletManager | res://scripts/managers/gauntlet_manager.gd | Gauntlet mode progression |
+| PortalModeManager | res://scripts/managers/portal_mode_manager.gd | Portal race mode |
+| TurnManager | res://scripts/managers/turn_manager.gd | Turn-based sequencing |
+| GoalManager | res://scripts/managers/goal_manager.gd | Goal validation, completion |
+| GoalsCycleManager | res://scripts/managers/goals_cycle_manager.gd | Cycling goal rotation, scoring |
+| PlayerRaceManager | res://scripts/managers/player_race_manager.gd | Race position, finish |
+| ShopManager | res://scripts/managers/shop_manager.gd | Shop data layer |
+| JoinManager | res://scripts/managers/join_manager.gd | Join code input |
+| PowerupManager | res://scripts/managers/powerup_manager.gd | Powerup system (boost/charge) |
+| NotificationManager | res://scripts/managers/notification_manager.gd | On-screen message queue |
+| ObstacleManager | res://scripts/managers/obstacle_manager.gd | Obstacle placement/removal |
+| FriendManager | res://scripts/managers/friend_manager.gd | Friends list, DMs |
+| AdminManager | res://scripts/managers/admin_manager.gd | Admin panel state |
+| MailManager | res://scripts/managers/mail_manager.gd | Mail CRUD |
+| SessionManager | res://scripts/managers/session_manager.gd | Session refresh lifecycle |
+| SettingsManager | res://scripts/managers/settings_manager.gd | User settings persistence |
+| TutorialManager | res://scripts/managers/tutorial_manager.gd | Tutorial flow control |
+| TutorialOverlay | res://scripts/managers/tutorial_overlay.gd | Tutorial UI overlay |
+| PlayerboardManager | res://scripts/managers/playerboard_manager.gd | Player inventory board |
+| CameraContextManager | res://scripts/managers/camera_context_manager.gd | Camera zoom/context |
+| ScreenShake | res://scripts/managers/screen_shake.gd | Screen shake effects |
+| SpecialTilesManager | res://scripts/managers/special_tiles_manager.gd | Ice/crack/portal tiles |
+| StaticTektonManager | res://scripts/managers/static_tekton_manager.gd | Static Tekton turret logic |
+| TouchControls | res://scripts/managers/touch_controls.gd | Mobile touch input overlay |
+| DailyRewardManager | res://scripts/managers/daily_reward_manager.gd | Daily reward claims |
+
+[Back to top](#top)
+
+
+## 3. Service Layer
+
+[Back to top](#top)
+
+### 3.1 NakamaManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/nakama_manager.gd` (330 lines)
+**Extends:** Node
+**Autoload name:** NakamaManager
+
+Central Nakama SDK integration. Manages the Nakama client, session, socket, and multiplayer bridge. All network communication flows through this singleton.
+
+**Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| nakama_server_key | String | From env var NAKAMA_SERVER_KEY or ProjectSettings |
+| nakama_host | String | Default: `tektondash.vps.webdock.cloud` |
+| nakama_port | int | Default: 7350 |
+| nakama_scheme | String | Default: http |
+| client | NakamaClient | The Nakama client instance |
+| session | NakamaSession | Current auth session |
+| socket | NakamaSocket | WebSocket connection |
+| bridge | NakamaMultiplayerBridge | Links Nakama socket to Godot HLAPI |
+| current_match_id | String | Currently joined match ID |
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `connected_to_nakama` | none | Emitted when socket connects successfully |
+| `connection_failed` | error_message: String | Emitted on connection failure |
+| `match_joined` | match_id: String | Emitted when bridge joins a match |
+| `match_join_error` | error_message: String | Emitted on match join failure |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `set_server` | `func set_server(host: String, port: int = 7350) -> void` | void | Override Nakama server endpoint. Auto-detects scheme (https for .ts.net, http for 100.x IPs). Recreates client if no active session. |
+| `connect_to_nakama_async` | `func connect_to_nakama_async(email: String = "", password: String = "") -> bool` | bool (async) | Full auth + socket + bridge connection. Empty email = device auth. Creates socket, initializes multiplayer bridge, sets Godot's multiplayer peer. |
+| `cleanup` | `func cleanup() -> void` | void | Shuts down socket, leaves bridge, deletes match metadata storage, resets multiplayer peer to null. |
+| `host_game` | `func host_game(room_meta: Dictionary = {}) -> void` | void | Creates a Nakama relayed match via bridge.create_match(). Optionally stores room metadata to Nakama storage. Has re-entry guard for double-click protection. |
+| `join_game` | `func join_game(match_id: String) -> void` | void | Joins an existing match by ID. Leaves current match first if connected. |
+| `is_connected_to_nakama` | `func is_connected_to_nakama() -> bool` | bool | Returns true if socket exists and is connected to host. |
+| `list_matches_async` | `func list_matches_async(mode_filter: String = "") -> Array` | Array (async) | Queries Nakama for available matches. Batch-reads room metadata from storage. Returns array of room dicts. |
+| `_on_bridge_match_joined` | `func _on_bridge_match_joined() -> void` | void | Internal: updates current_match_id, emits match_joined signal. |
+| `_on_bridge_match_join_error` | `func _on_bridge_match_join_error(error) -> void` | void | Internal: emits match_join_error. |
+
+**Dependencies:** Nakama GDExtension (NakamaClient, NakamaSocket, NakamaMultiplayerBridge).
+**Depended by:** AuthManager, BackendService, LobbyManager, LobbyRoom, LobbyChat, LobbyMainMenu, main.gd.
+
+[Back to top](#top)
+
+### 3.2 BackendService
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/services/backend_service.gd` (247 lines)
+**Extends:** Node
+**Autoload name:** BackendService
+
+Unified typed interface for all Nakama Lua RPCs. All platform authentication paths (Steam, Nakama device/email) funnel through here. Provides retry logic with exponential backoff.
+
+**Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| current_platform | Platform (enum) | DESKTOP_STEAM, DESKTOP_NAKAMA, or MOBILE_NAKAMA |
+| steamworks_manager | Node | Only for auth ticket retrieval |
+| nakama_backend | Node | Reference to NakamaManager autoload |
+
+**Enums:**
+
+- `Platform { DESKTOP_STEAM, DESKTOP_NAKAMA, MOBILE_NAKAMA }`
+- `ErrorCode { NONE, NETWORK_ERROR, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, INTERNAL_ERROR, UNKNOWN_ERROR, INSUFFICIENT_FUNDS }`
+
+**Signals:** None.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `_ready` | auto-called | void | Detects platform, initializes backend |
+| `is_initialized` | `func is_initialized() -> bool` | bool | Checks nakama_backend is non-null |
+| `get_platform_name` | `func get_platform_name() -> String` | String | Returns human-readable platform name |
+| `get_steamworks_manager` | `func get_steamworks_manager() -> Node` | Node | Returns steamworks_manager child node |
+| `api_rpc_async` | `func api_rpc_async(rpc_id: String, payload: String = "{}") -> Dictionary` | Dictionary (async) | Unified RPC with up to 3 retries, exponential backoff (0.5s base). Returns `{success, error, message, data}`. |
+| `admin_clear_global_chat` | `func admin_clear_global_chat(payload: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `admin_get_chat_config` | `func admin_get_chat_config() -> Dictionary` | Dictionary | RPC wrapper |
+| `admin_set_chat_config` | `func admin_set_chat_config(config: Dictionary) -> Dictionary` | Dictionary | RPC wrapper |
+| `admin_purge_old_messages` | `func admin_purge_old_messages(channel_id: String, max_age_days: int) -> Dictionary` | Dictionary | RPC wrapper |
+| `admin_list_channel_messages` | `func admin_list_channel_messages(channel_id: String, limit: int = 50, cursor: String = "", forward: bool = true) -> Dictionary` | Dictionary | RPC wrapper |
+| `admin_delete_channel_message` | `func admin_delete_channel_message(channel_id: String, message_id: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `send_friend_request` | `func send_friend_request(target_id: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `respond_friend_request` | `func respond_friend_request(target_id: String, accept: bool) -> Dictionary` | Dictionary | RPC wrapper |
+| `perform_gacha_pull` | `func perform_gacha_pull(gacha_id: String, count: int) -> Dictionary` | Dictionary | RPC wrapper |
+| `get_mail` | `func get_mail(payload: String = "{}") -> Dictionary` | Dictionary | RPC wrapper |
+| `claim_mail_reward` | `func claim_mail_reward(mail_id: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `delete_mail` | `func delete_mail(mail_id: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `send_mail` | `func send_mail(payload: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `change_avatar` | `func change_avatar(avatar_url: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `change_username` | `func change_username(new_username: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `change_status` | `func change_status(new_status: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `change_bio` | `func change_bio(new_bio: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `query_users` | `func query_users(payload: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `admin_give_currency` | `func admin_give_currency(payload: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `get_daily_reward_config_admin` | `func get_daily_reward_config_admin() -> Dictionary` | Dictionary | RPC wrapper |
+| `set_daily_reward_config` | `func set_daily_reward_config(req: Dictionary) -> Dictionary` | Dictionary | RPC wrapper |
+| `get_daily_reward_state` | `func get_daily_reward_state() -> Dictionary` | Dictionary | RPC wrapper |
+| `claim_daily_reward` | `func claim_daily_reward() -> Dictionary` | Dictionary | RPC wrapper |
+| `sync_leaderboard` | `func sync_leaderboard() -> Dictionary` | Dictionary | RPC wrapper |
+| `get_leaderboard_stats` | `func get_leaderboard_stats() -> Dictionary` | Dictionary | RPC wrapper |
+| `debug_add_exp` | `func debug_add_exp(exp_amount: int) -> Dictionary` | Dictionary | RPC wrapper |
+| `reset_stats` | `func reset_stats() -> Dictionary` | Dictionary | RPC wrapper |
+| `search_users` | `func search_users(payload: String) -> Dictionary` | Dictionary | RPC wrapper |
+| `send_lobby_invite` | `func send_lobby_invite(to_user_id: String, match_id: String) -> Dictionary` | Dictionary | RPC wrapper |
+
+**Dependencies:** NakamaManager (autoload), SteamworksManager (child node).
+**Depended by:** AuthManager, LobbyManager, LobbyChat, lobby.gd (admin), FriendManager, MailManager, GachaManager, DailyRewardManager, AdminManager, SkinManager.
+
+[Back to top](#top)
+
+### 3.3 SteamworksManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/services/steamworks_manager.gd` (72 lines)
+**Extends:** Node
+**class_name:** SteamworksManager
+
+NOT an autoload. Created as a child of BackendService. Provides Steam auth session tickets for Nakama login. GodotSteam GDExtension required.
+
+**Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| is_steam_initialized | bool | Whether Steam API initialized successfully |
+| steam_app_id | int | From ProjectSettings or default 480 |
+
+**Signals:** None.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `_ready` | auto-called | void | Calls _initialize_steam |
+| `is_initialized` | `func is_initialized() -> bool` | bool | Returns steam init status |
+| `get_auth_session_ticket` | `func get_auth_session_ticket() -> String` | String | Gets Steam auth session ticket via Steam.getAuthSessionTicket(), returns hex-encoded buffer |
+| `get_steam_user_name` | `func get_steam_user_name() -> String` | String | Returns Steam persona name via Steam.getPersonaName() |
+| `get_steam_user_id` | `func get_steam_user_id() -> int` | int | Returns Steam ID via Steam.getSteamID() |
+
+**Dependencies:** GodotSteam GDExtension (ClassDB.class_exists("Steam")).
+**Depended by:** BackendService, AuthManager.
+
+[Back to top](#top)
+
+
+## 4. Core Managers
+
+[Back to top](#top)
+
+### 4.1 AuthManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/auth_manager.gd` (515 lines)
+**Extends:** Node
+**Autoload name:** AuthManager
+
+Centralized authentication handler. Supports Guest (device ID), Email/Password, Google, Apple, Facebook, and Steam auth modes. Persists sessions to encrypted file storage.
+
+**Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| current_user | Dictionary | {user_id, username, display_name, avatar_url, email} |
+| is_authenticated | bool | Whether fully authenticated |
+| is_guest | bool | Whether using guest mode |
+| auth_mode | AuthMode (enum) | GUEST, EMAIL, GOOGLE, APPLE, FACEBOOK, STEAM, CUSTOM |
+
+**Enums:** `AuthMode { GUEST, EMAIL, GOOGLE, APPLE, FACEBOOK, STEAM, CUSTOM }`
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `auth_started` | none | Emitted when any login flow begins |
+| `auth_completed` | success: bool, user_data: Dictionary | Emitted on auth success or failure |
+| `auth_failed` | error: String | Emitted on auth error |
+| `session_restored` | none | Emitted when saved session restored |
+| `logged_out` | none | Emitted after full logout |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `_ready` | auto-called | void | Deferred call to _try_restore_session |
+| `login_as_guest` | `func login_as_guest() -> bool` | bool (async) | Device ID guest auth. Generates/persists device ID. |
+| `login_with_email` | `func login_with_email(email: String, password: String, remember: bool = true) -> bool` | bool (async) | Email/password authentication |
+| `register_with_email` | `func register_with_email(email: String, password: String, username: String = "") -> bool` | bool (async) | Email registration (create if not exists) |
+| `login_with_google` | `func login_with_google(id_token: String) -> bool` | bool (async) | Google auth via ID token |
+| `login_with_apple` | `func login_with_apple(id_token: String) -> bool` | bool (async) | Apple auth via ID token |
+| `login_with_facebook` | `func login_with_facebook(access_token: String) -> bool` | bool (async) | Facebook auth via access token |
+| `login_with_steam` | `func login_with_steam() -> bool` | bool (async) | Steam ticket auth via BackendService.steamworks_manager |
+| `link_email` | `func link_email(email: String, password: String) -> bool` | bool (async) | Link email to existing guest account |
+| `link_google` | `func link_google(id_token: String) -> bool` | bool (async) | Link Google to existing account |
+| `logout` | `func logout() -> void` | void | Full cleanup: NakamaManager.cleanup(), clear session files, reset state, emit logged_out |
+| `clear_session` | `func clear_session() -> void` | void | Deletes SESSION_FILE and CREDENTIALS_FILE from user:// |
+| `_try_restore_session` | internal | void | Attempts to load encrypted session file. Skips guest session auto-restore. |
+| `_connect_socket` | internal | bool (async) | Creates Nakama socket, connects, initializes multiplayer bridge |
+| `_load_user_profile` | internal | void (async) | Loads account data from Nakama into current_user |
+
+**Dependencies:** NakamaManager, BackendService.
+**Depended by:** LobbyMainMenu, lobby.gd, UserProfileManager, login_screen.tscn.
+
+[Back to top](#top)
+
+### 4.2 LobbyManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/lobby_manager.gd` (1023 lines)
+**Extends:** Node
+**Autoload name:** LobbyManager
+
+Room/lobby lifecycle manager. Handles both Nakama (online) and LAN (direct ENet) modes. Manages room creation, joining, player list, ready states, game mode settings, and character/area selection.
+
+**Properties:**
+
+| Name | Type | Default | Description |
+|---|---|---|---|
+| current_room | Dictionary | {} | Current room metadata |
+| players_in_room | Array | [] | [{id, name, is_ready, character, nakama_id}] |
+| available_rooms | Array | [] | Discovered rooms for room list |
+| is_host | bool | false | Whether local player is room host |
+| is_lan_mode | bool | false | Direct ENet (no Nakama) |
+| LAN_PORT | const int | 7777 | ENet server port |
+| LAN_DISCOVERY_PORT | const int | 7778 | UDP broadcast port |
+| local_player_name | String | "Player" | Display name |
+| is_tutorial_mode | bool | false | Tutorial mode flag |
+| match_duration | int | 180 | Seconds (configurable by host) |
+| randomize_spawn | bool | false | Randomize spawn positions |
+| enable_cycle_timer | bool | false | Goal cycle timer |
+| scarcity_mode | String | "Normal" | Item scarcity: Normal/Aggressive/Chaos |
+| disconnect_reason | String | "" | UI feedback message |
+| sng_go_duration | int | 20 | Stop n Go: GO phase seconds |
+| sng_stop_duration | int | 4 | Stop n Go: STOP phase seconds |
+| sng_required_goals | int | 8 | Goals needed for SNG win |
+| doors_swap_time | int | 15 | Tekton Doors: swap interval |
+| doors_refresh_time | int | 25 | Tekton Doors: refresh interval |
+| doors_required_goals | int | 8 | Goals needed for Doors win |
+| rematch_votes | Array | [] | Player IDs who voted for rematch |
+| available_characters | Array[String] | [...] | ["Copper", "Dabro", "Gatot", "Pip", "Random"] |
+| available_areas | Array[String] | [] | Mode-specific area list |
+| available_game_modes | Array[String] | [...] | ["Freemode", "Stop n Go", "Candy Pump Survival"] |
+| selected_area | String | "Freemode Arena" | Currently selected area |
+| game_mode | String | "Freemode" | Current game mode |
+| local_character_index | int | 0 | Local player's character index |
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `room_list_updated` | rooms: Array | Room list refreshed |
+| `room_joined` | room_data: Dictionary | Joined a room |
+| `room_left` | none | Left current room |
+| `player_joined` | player_data: Dictionary | Player entered room |
+| `player_left` | player_id: int | Player left room |
+| `ready_state_changed` | player_id: int, is_ready: bool | Player ready status changed |
+| `all_players_ready` | none | All players ready |
+| `host_disconnected` | none | Host left/disconnected |
+| `game_starting` | none | Game countdown started |
+| `match_duration_changed` | duration_seconds: int | Duration setting changed |
+| `randomize_spawn_changed` | enabled: bool | Random spawn toggled |
+| `character_changed` | player_id: int, character_name: String | Character selection changed |
+| `area_changed` | area_name: String | Map area changed |
+| `player_list_changed` | none | Player list should re-render |
+| `rematch_votes_updated` | count: int, required: int | Rematch vote progress |
+| `game_mode_changed` | mode: String | Game mode changed |
+| `scarcity_mode_changed` | mode: String | Scarcity setting changed |
+| `enable_cycle_timer_changed` | enabled: bool | Timer toggle changed |
+| `sng_go_duration_changed` | duration: int | SNG Go duration changed |
+| `sng_stop_duration_changed` | duration: int | SNG Stop duration changed |
+| `sng_required_goals_changed` | goals: int | SNG required goals changed |
+| `doors_swap_time_changed` | time: int | Doors swap interval changed |
+| `doors_refresh_time_changed` | time: int | Doors refresh interval changed |
+| `doors_required_goals_changed` | goals: int | Doors required goals changed |
+| `gauntlet_round_duration_changed` | duration: int | Gauntlet round duration changed |
+| `gauntlet_growth_interval_changed` | interval: float | Gauntlet growth interval changed |
+| `gauntlet_cells_per_tick_changed` | cells: Dictionary | Cells per tick changed |
+
+**Key Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `start_tutorial` | `func start_tutorial(mode: String = "Freemode") -> void` | void | Sets tutorial flags, calls create_room_lan("Tutorial") |
+| `create_room` | `func create_room(room_name: String) -> void` | void | Hosts Nakama room: connects, calls NakamaManager.host_game |
+| `join_room` | `func join_room(match_id: String) -> void` | void | Joins Nakama room by match ID |
+| `create_room_lan` | `func create_room_lan(room_name: String = "LAN Game") -> bool` | bool | Creates ENet server on LAN_PORT, broadcasts UDP discovery |
+| `join_room_lan` | `func join_room_lan(host_ip: String) -> bool` | bool | Creates ENet client to host IP:LAN_PORT |
+| `leave_room` | -- | void | Leaves current room, cleans up peers |
+| `start_game` | `func start_game(is_tutorial: bool = false) -> void` | void | Transitions from lobby to main game scene |
+| `refresh_room_list` | `func refresh_room_list() -> void` | void | Queries Nakama for available rooms or broadcasts LAN |
+| `set_ready` | `func set_ready(is_ready: bool) -> void` | void | Updates ready state via RPC |
+| `set_match_duration` | `func set_match_duration(seconds: int) -> void` | void | Host sets match duration |
+| `set_randomize_spawn` | `func set_randomize_spawn(enabled: bool) -> void` | void | Host toggles random spawn |
+| `set_enable_cycle_timer` | `func set_enable_cycle_timer(enabled: bool) -> void` | void | Host toggles timer |
+| `set_scarcity_mode` | `func set_scarcity_mode(mode: String) -> void` | void | Host sets scarcity |
+| `set_game_mode` | `func set_game_mode(mode: String) -> void` | void | Host sets game mode |
+| `cycle_character` | `func cycle_character(direction: int) -> void` | void | Change character selection |
+| `cycle_area` | `func cycle_area(direction: int) -> void` | void | Change selected area |
+| `get_players` | `func get_players() -> Array` | Array | Returns players_in_room |
+| `is_all_ready` | `func is_all_ready() -> bool` | bool | All players ready check |
+| `set_sng_go_duration` | -- | void | Host sets SNG go time |
+| `set_sng_stop_duration` | -- | void | Host sets SNG stop time |
+| `set_sng_required_goals` | -- | void | Host sets SNG goals |
+| `get_selected_area` | `func get_selected_area() -> String` | String | Returns current area name |
+| `get_game_mode` | `func get_game_mode() -> GameMode.Mode` | GameMode.Mode | Converts string to GameMode enum |
+| `is_game_mode` | `func is_game_mode(mode: GameMode.Mode) -> bool` | bool | Mode comparison helper |
+
+**Internal Functions:** `_on_match_joined`, `_on_peer_connected`, `_on_peer_disconnected`, `_on_server_disconnected`, `_update_available_areas`, `_start_lan_broadcast`, `_broadcast_lan_room`, `_stop_lan_broadcast`, `_update_lan_room_list`, `_listen_for_lan_discovery`, `_update_ready_state_rpc`, `_request_rematch`, `rpc_set_*`, `rpc_*`.
+
+**Dependencies:** NakamaManager, GameStateManager.
+**Depended by:** LobbyRoom, LobbyRoomList, LobbyMainMenu, main.gd, player.gd, lobby.gd, SceneManager (loading screen).
+
+[Back to top](#top)
+
+### 4.3 GameStateManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/game_state_manager.gd` (66 lines)
+**Extends:** Node
+**Autoload name:** GameStateManager
+
+Simple state machine and match configuration constants.
+
+**Properties:**
+
+| Name | Type | Default | Description |
+|---|---|---|---|
+| current_state | GameState (enum) | LOBBY | Current application state |
+| max_players | int | 8 | Max players in a match |
+| enable_bots | bool | false | Bot fill toggle |
+| local_player_id | int | 0 | Local peer ID |
+
+**Enums:** `GameState { LOBBY, LOADING, GAME, RESULT }`
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `state_changed` | new_state: GameState | Emitted on state transition |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `change_state` | `func change_state(new_state: GameState) -> void` | void | Transitions state, emits state_changed |
+
+**Dependencies:** None.
+**Depended by:** LobbyManager, main.gd, tutorial_manager.gd, many managers.
+
+[Back to top](#top)
+
+### 4.4 PlayerManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/player_manager.gd` (37 lines)
+**Extends:** Node
+**Autoload name:** PlayerManager
+
+Lightweight data container for player metadata. Stores display name and peer ID for the local player. Used as a quick reference by various subsystems.
+
+**Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| display_name | String | Local player's display name |
+| peer_id | int | Local player's multiplayer unique ID |
+
+**Signals:** None.
+
+**Public Functions:** None (data-only container).
+
+**Dependencies:** None.
+**Depended by:** UIManager, player.gd, various managers needing player identity.
+
+[Back to top](#top)
+
+### 4.5 EventBus
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/event_bus.gd` (73 lines)
+**Extends:** Node
+**Autoload name:** EventBus
+
+Centralized observer pattern for inter-manager communication. Replaces direct cross-references between managers.
+
+**Constants (event names):**
+
+| Constant | Value | Description |
+|---|---|---|
+| EVENT_PLAYER_JOINED | "player_joined" | Player entered match |
+| EVENT_PLAYER_LEFT | "player_left" | Player left match |
+| EVENT_PLAYER_READY | "player_ready" | Player ready state changed |
+| EVENT_MATCH_STARTED | "match_started" | Match began |
+| EVENT_MATCH_ENDED | "match_ended" | Match ended |
+| EVENT_GAME_MODE_CHANGED | "game_mode_changed" | Game mode switched |
+| EVENT_CURRENCY_CHANGED | "currency_changed" | Wallet balance changed |
+| EVENT_ITEM_PURCHASED | "item_purchased" | Item bought from shop |
+| EVENT_GACHA_PULL | "gacha_pull" | Gacha rolled |
+| EVENT_PROFILE_LOADED | "profile_loaded" | Profile loaded from server |
+| EVENT_PROFILE_UPDATED | "profile_updated" | Profile updated |
+| EVENT_AVATAR_CHANGED | "avatar_changed" | Avatar changed |
+| EVENT_SESSION_REFRESHED | "session_refreshed" | Nakama session refreshed |
+| EVENT_SESSION_EXPIRED | "session_expired" | Nakama session expired |
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `event_emitted` | event_name: String, data: Variant | Fired on every emit |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `emit` | `func emit(event_name: String, data: Variant = null) -> void` | void | Emit event to all registered listeners and the signal bus |
+| `on` | `func on(event_name: String, callback: Callable) -> void` | void | Subscribe to event |
+| `off` | `func off(event_name: String, callback: Callable) -> void` | void | Unsubscribe from event |
+| `clear` | `func clear() -> void` | void | Remove all listeners (scene transition cleanup) |
+
+**Dependencies:** None.
+**Depended by:** UserProfileManager, GachaManager, ShopManager, many managers for loose coupling.
+
+[Back to top](#top)
+
+### 4.6 GameMode / ModeConfig
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/game_mode.gd` (41 lines)
+**Extends:** RefCounted
+**class_name:** GameMode
+
+Enum and string conversion utilities for game modes.
+
+**Enum:** `Mode { FREEMODE = 0, STOP_N_GO = 1, TEKTON_DOORS = 2, GAUNTLET = 3 }`
+
+**Public Static Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `from_string` | `static func from_string(mode: String) -> Mode` | Mode | Converts "Freemode"/"Stop n Go"/"Tekton Doors"/"Candy Pump Survival" to enum |
+| `mode_to_string` | `static func mode_to_string(mode: Mode) -> String` | String | Converts enum back to string |
+| `is_restricted` | `static func is_restricted(mode: Mode) -> bool` | bool | Returns true for SNG, Doors, or Gauntlet |
+| `get_all_modes` | `static func get_all_modes() -> Array[String]` | Array[String] | Returns all mode names |
+
+**File:** `/home/dev/tekton/scripts/mode_config.gd` (108 lines)
+**Extends:** RefCounted
+**class_name:** ModeConfig
+
+Schema-driven validation for game mode settings. Consolidates duplicated/inconsistent option toggles.
+
+**Public Static Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `get_defaults` | `static func get_defaults(mode: String) -> Dictionary` | Dictionary | Returns default config dict for mode |
+| `validate_setting` | `static func validate_setting(mode: String, key: String, value: Variant) -> Dictionary` | Dictionary | Validates type, range, and allowed values for a single setting |
+| `validate_config` | `static func validate_config(mode: String, config: Dictionary) -> Dictionary` | Dictionary | Validates entire config, returns errors array |
+| `get_mode_settings` | `static func get_mode_settings(mode: String) -> Array` | Array | Returns list of setting keys for mode |
+| `get_setting_schema` | `static func get_setting_schema(mode: String, key: String) -> Dictionary` | Dictionary | Returns schema for specific setting |
+| `has_setting` | `static func has_setting(mode: String, key: String) -> bool` | bool | Checks if setting exists for mode |
+| `get_supported_modes` | `static func get_supported_modes() -> Array` | Array | Returns all supported mode strings |
+
+**Dependencies:** None (standalone utility classes).
+**Depended by:** LobbyManager, LobbyRoom, mode-specific managers.
+
+[Back to top](#top)
+
+
+## 5. Player Subsystem Managers
+
+[Back to top](#top)
+
+### 5.1 PlayerMovementManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/player_movement_manager.gd` (33,053 chars)
+**Extends:** Node
+**Autoload name:** PlayerMovementManager
+
+Handles player movement physics, grid-based pathfinding, movement range highlighting, position syncing, and obstacle-aware navigation. Delegated from player.gd.
+
+**Signals:** (custom signals listed; full list from code)
+
+| Signal | Params | Description |
+|---|---|---|
+| `movement_started` | path: Array | Emitted when player begins moving |
+| `movement_completed` | none | Emitted when movement tween finishes |
+| `movement_interrupted` | none | Emitted when movement is cancelled |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `move_along_path` | `func move_along_path(player: Node, path: Array) -> void` | void | Tweens player along grid path |
+| `find_path` | `func find_path(from: Vector2i, to: Vector2i, gridmap: Node) -> Array` | Array | A* or BFS pathfinding on grid |
+| `highlight_movement_range` | `func highlight_movement_range(player: Node) -> void` | void | Shows reachable cells |
+| `highlight_adjacent_cells` | `func highlight_adjacent_cells(player: Node) -> void` | void | Shows cardinal-adjacent cells |
+| `rotate_towards_target` | `func rotate_towards_target(target_pos: Vector2i) -> void` | void | Smooth rotation to face target |
+| `can_move_to` | `func can_move_to(pos: Vector2i, gridmap: Node) -> bool` | bool | Cell walkability check |
+| `apply_stagger` | `func apply_stagger(duration: float) -> void` | void | Applies stun knockback |
+| `sync_bump` | `func sync_bump(target_pos: Vector2i, is_soft: bool) -> void` | void | Visual bump animation |
+| `set_player_moving` | `func set_player_moving(is_moving: bool) -> void` | void | Toggle movement state |
+
+**Dependencies:** player.gd (node refs), ObstacleManager, SpecialTilesManager, EnhancedGridMap.
+**Depended by:** player.gd, main.gd.
+
+[Back to top](#top)
+
+### 5.2 PlayerInputManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/player_input_manager.gd` (7,292 chars)
+**Extends:** Node
+**Autoload name:** PlayerInputManager
+
+Captures and buffers player input events. Supports keyboard, mouse, gamepad, and touch inputs. Provides input state query API.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `input_received` | event: InputEvent | Raw input forwarded |
+| `action_pressed` | action: String | Action mapped press (grab, put, move) |
+| `action_released` | action: String | Action released |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `is_action_held` | `func is_action_held(action: String) -> bool` | bool | Check if action is currently held |
+| `get_movement_direction` | `func get_movement_direction() -> Vector2i` | Vector2i | Grid-aligned movement cardinal |
+| `get_look_direction` | `func get_look_direction(camera: Camera3D) -> Vector2` | Vector2 | Mouse-world direction |
+| `flush_buffer` | `func flush_buffer() -> void` | void | Clear input buffer |
+| `is_touch_active` | `func is_touch_active() -> bool` | bool | Whether touch controls are in use |
+
+**Dependencies:** TouchControls (autoload).
+**Depended by:** player.gd, player_action_manager.gd.
+
+[Back to top](#top)
+
+### 5.3 PlayerActionManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/player_action_manager.gd` (8,828 chars)
+**Extends:** Node
+**Autoload name:** PlayerActionManager
+
+Action execution layer. Manages grab, put, arrange, tekton throw/knock actions. Handles action point consumption, cooldowns, and visual highlighting.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `action_executed` | action_type: String | Action performed |
+| `action_failed` | reason: String | Action invalid |
+| `action_points_changed` | points: int | AP updated |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `execute_grab` | `func execute_grab(player: Node, grid_pos: Vector2i) -> bool` | bool | Grab item from grid |
+| `execute_put` | `func execute_put(player: Node, slot_index: int, grid_pos: Vector2i) -> bool` | bool | Put item from playerboard to grid |
+| `execute_arrange` | `func execute_arrange(player: Node, from_slot: int, to_slot: int) -> bool` | bool | Rearrange playerboard slots |
+| `consume_action_points` | `func consume_action_points(points: int) -> void` | void | Deduct action points |
+| `can_afford_action` | `func can_afford_action() -> bool` | bool | Check AP > 0 |
+| `after_action_completed` | `func after_action_completed() -> void` | void | Post-action cleanup: check win, cycle goals |
+| `highlight_cells_if_authorized` | `func highlight_cells_if_authorized(cells: Array, item_id: int) -> void` | void | Show valid target cells |
+| `highlight_empty_adjacent_cells` | `func highlight_empty_adjacent_cells() -> void` | void | Show empty adjacent cells for put |
+| `highlight_occupied_playerboard_slots` | `func highlight_occupied_playerboard_slots() -> void` | void | Show occupied slots for grab |
+| `highlight_random_valid_cells` | `func highlight_random_valid_cells() -> void` | void | Show random valid cells |
+| `clear_highlights` | `func clear_highlights() -> void` | void | Remove all cell highlights |
+| `clear_playerboard_highlights` | `func clear_playerboard_highlights() -> void` | void | Remove playerboard highlights |
+
+**Dependencies:** PlayerboardManager, PlayerInputManager, GoalsCycleManager.
+**Depended by:** player.gd, main.gd.
+
+[Back to top](#top)
+
+### 5.4 PlayerboardManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/playerboard_manager.gd` (22,790 chars)
+**Extends:** Node
+**Autoload name:** PlayerboardManager
+
+Manages each player's inventory board (2x5 or 3x5 grid of item slots). Handles slot selection, item placement, auto-arrange for goal matching, drag-and-drop, and visual updates.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `slot_selected` | slot_index: int | Slot clicked/selected |
+| `slot_deselected` | none | Selection cleared |
+| `item_placed` | slot_index: int, item_id: int | Item added to slot |
+| `item_removed` | slot_index: int | Item removed from slot |
+| `playerboard_updated` | player_id: int, board: Array | Full board synced |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `grab_item` | `func grab_item(grid_pos: Vector2i) -> bool` | bool | Auto-place grabbed item into best-fit slot |
+| `auto_put_item` | `func auto_put_item() -> bool` | bool | Put goal-matching tile from board to adjacent grid |
+| `handle_slot_clicked` | `func handle_slot_clicked(slot_index: int) -> void` | void | Process slot click event |
+| `handle_playerboard_slot_selected` | `func handle_playerboard_slot_selected(slot_index: int) -> void` | void | Handle slot selection for action |
+| `handle_put_slot_selected` | `func handle_put_slot_selected(slot_index: int) -> void` | void | Handle slot chosen for put action |
+| `arrange_playerboard_item` | `func arrange_playerboard_item(slot_index: int) -> void` | void | Move item to better slot |
+| `select_playerboard_slot` | `func select_playerboard_slot(slot_index: int) -> void` | void | Mark slot as selected |
+| `deselect_playerboard_slot` | `func deselect_playerboard_slot() -> void` | void | Clear slot selection |
+| `target_playerboard_slot` | `func target_playerboard_slot(slot_index: int) -> void` | void | Target a slot for move |
+| `untarget_playerboard_slot` | `func untarget_playerboard_slot() -> void` | void | Clear target |
+| `can_move_to_target_playerboard_slot` | `func can_move_to_target_playerboard_slot() -> bool` | bool | Check if target slot is valid |
+| `bot_grab_item` | `func bot_grab_item(pos: Vector2i, slot: int, x: int, y: int, z: int) -> void` | void | Bot performs grab |
+| `bot_put_item` | `func bot_put_item(pos: Vector2i, slot: int, x: int, y: int, z: int) -> void` | void | Bot performs put |
+| `bot_arrange_item` | `func bot_arrange_item(from_slot: int, to_slot: int) -> void` | void | Bot rearranges board |
+
+**Dependencies:** GoalsCycleManager, GoalManager, EnhancedGridMap (scene ref).
+**Depended by:** player.gd, PlayerActionManager.
+
+[Back to top](#top)
+
+### 5.5 PowerupManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/powerup_manager.gd` (9,417 chars)
+**Extends:** Node
+**Autoload name:** PowerupManager
+
+Powerup/boost system. Tracks boost charge level, special ability availability, and consumes boost for charged actions.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `boost_changed` | amount: float | Boost level changed |
+| `boost_full` | none | Boost reached 100% |
+| `powerup_activated` | type: String | Powerup used |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `add_boost` | `func add_boost(amount: float) -> void` | void | Increment boost |
+| `consume_boost` | `func consume_boost(amount: float) -> void` | void | Deduct boost |
+| `can_use_special` | `func can_use_special() -> bool` | bool | Boost >= 100 |
+| `get_boost_pct` | `func get_boost_pct() -> float` | float | 0.0 to 1.0 |
+| `reset_boost` | `func reset_boost() -> void` | void | Set to 0 |
+
+**Dependencies:** None.
+**Depended by:** player.gd (charged strike, knock), PlayerActionManager.
+
+[Back to top](#top)
+
+
+## 6. Game Mode Managers
+
+[Back to top](#top)
+
+### 6.1 StopNGoManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/stop_n_go_manager.gd` (21,884 chars)
+**Extends:** Node
+**Autoload name:** StopNGoManager
+
+State machine for the Stop n Go game mode. Alternates between GO (movement allowed) and STOP (frozen) phases. Tracks winner via first player to complete required goals during GO phases.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `phase_changed` | phase: String ("go"/"stop") | GO/STOP transition |
+| `countdown_tick` | seconds: int | Phase countdown tick |
+| `sng_winner` | player_id: int | Winner determined |
+| `sng_ended` | none | Minigame concluded |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `start_sng` | `func start_sng(go_duration: int, stop_duration: int, required_goals: int) -> void` | void | Initialize SNG with params |
+| `stop_sng` | `func stop_sng() -> void` | void | End SNG minigame |
+| `start_go_phase` | `func start_go_phase() -> void` | void | Begin GO timer |
+| `start_stop_phase` | `func start_stop_phase() -> void` | void | Begin STOP timer, freeze all |
+| `freeze_player` | `func freeze_player(player_id: int) -> void` | void | Stop player movement |
+| `unfreeze_player` | `func unfreeze_player(player_id: int) -> void` | void | Resume player movement |
+| `check_winner` | `func check_winner() -> int` | int | Returns winner peer_id or -1 |
+| `get_phase` | `func get_phase() -> String` | String | Current phase |
+
+**Dependencies:** TurnManager, GoalManager, GoalsCycleManager, animation.gd (scene).
+**Depended by:** main.gd, player.gd.
+
+[Back to top](#top)
+
+### 6.2 GauntletManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/gauntlet_manager.gd` (5,467 chars)
+**Extends:** Node
+**Autoload name:** GauntletManager
+
+Manages the Candy Pump Survival / Gauntlet game mode. Handles round progression, danger zone growth (flood fill), and elimination.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `round_started` | round: int | New round began |
+| `danger_zone_grown` | cells: Array | New tiles flooded |
+| `player_eliminated` | player_id: int | Player fell off/eliminated |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `start_gauntlet` | `func start_gauntlet(duration: int, growth_interval: float) -> void` | void | Initialize gauntlet mode |
+| `stop_gauntlet` | `func stop_gauntlet() -> void` | void | End gauntlet mode |
+| `eliminate_player` | `func eliminate_player(player_id: int) -> void` | void | Mark player as eliminated |
+| `get_alive_players` | `func get_alive_players() -> Array` | Array | Returns non-eliminated player IDs |
+| `get_round` | `func get_round() -> int` | int | Current round number |
+
+**Dependencies:** TurnManager, EnhancedGridMap.
+**Depended by:** main.gd.
+
+[Back to top](#top)
+
+### 6.3 PortalModeManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/portal_mode_manager.gd` (20,072 chars)
+**Extends:** Node
+**Autoload name:** PortalModeManager
+
+Manages portal race mode (Tekton Doors variant). Tracks portal positions, door swapping, refresh cycles, and race completion.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `portals_swapped` | portal_pairs: Array | Doors swapped positions |
+| `portals_refreshed` | portals: Array | New portal set spawned |
+| `player_teleported` | player_id: int, from: Vector2i, to: Vector2i | Player used portal |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `start_portal_mode` | `func start_portal_mode(swap_time: int, refresh_time: int) -> void` | void | Initialize portal mode |
+| `stop_portal_mode` | `func stop_portal_mode() -> void` | void | End portal mode |
+| `teleport_player` | `func teleport_player(player: Node, portal_enter: Vector2i) -> void` | void | Teleport player through portal pair |
+| `swap_portals` | `func swap_portals() -> void` | void | Randomize portal positions |
+| `refresh_portals` | `func refresh_portals() -> void` | void | Spawn new portal set |
+| `get_portal_pair` | `func get_portal_pair(portal_id: int) -> Array` | Array | Returns [entry, exit] positions |
+
+**Dependencies:** SpecialTilesManager, EnhancedGridMap.
+**Depended by:** main.gd.
+
+[Back to top](#top)
+
+### 6.4 GoalManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/goal_manager.gd` (3,857 chars)
+**Extends:** Node
+**Autoload name:** GoalManager
+
+Goal definitions, validation rules, and completion detection. Checks if a player's board arrangement matches the current goal pattern.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `goal_completed` | player_id: int, goal_id: int | Player completed a goal |
+| `goal_failed` | player_id: int, reason: String | Goal became impossible |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `validate_goal` | `func validate_goal(player_board: Array, goal: Dictionary) -> bool` | bool | Check board matches goal pattern |
+| `get_goal_type` | `func get_goal_type(goal: Dictionary) -> String` | String | Goal category (row, col, set, pattern) |
+| `is_goal_possible` | `func is_goal_possible(player_board: Array, goal: Dictionary) -> bool` | bool | Whether goal is still achievable |
+| `find_best_slot_for_item` | `func find_best_slot_for_item(board: Array, item: int, goal: Dictionary) -> int` | int | Auto-place item into best slot |
+
+**Dependencies:** None.
+**Depended by:** GoalsCycleManager, PlayerboardManager, StopNGoManager.
+
+[Back to top](#top)
+
+### 6.5 GoalsCycleManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/goals_cycle_manager.gd` (20,175 chars)
+**Extends:** Node
+**Autoload name:** GoalsCycleManager
+
+Manages cycling goal rotation. Tracks per-player score, cycles active goals on timer or action trigger, and determines when a player reaches the goal threshold to win.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `goals_cycled` | new_goals: Array | Active goals changed |
+| `player_scored` | player_id: int, points: int | Player earned points |
+| `player_won` | player_id: int | Player reached win threshold |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `start_cycle` | `func start_cycle(timer_enabled: bool) -> void` | void | Begin goal cycling |
+| `stop_cycle` | `func stop_cycle() -> void` | void | Stop cycling |
+| `cycle_goals` | `func cycle_goals() -> void` | void | Generate new goal set |
+| `add_score` | `func add_score(player_id: int, points: int) -> void` | void | Award points to player |
+| `get_player_score` | `func get_player_score(player_id: int) -> int` | int | Get player's current score |
+| `get_current_goals` | `func get_current_goals() -> Array` | Array | Get active goals |
+| `set_goal_threshold` | `func set_goal_threshold(goals_needed: int) -> void` | void | Set goals to win |
+
+**Dependencies:** GoalManager, TurnManager, Timer (scene).
+**Depended by:** main.gd, PlayerActionManager, StopNGoManager.
+
+[Back to top](#top)
+
+### 6.6 PlayerRaceManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/player_race_manager.gd` (4,757 chars)
+**Extends:** Node
+**Autoload name:** PlayerRaceManager
+
+Race-specific logic. Tracks player race position, finish locations, lap progression, and race completion.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `position_changed` | player_id: int, pos: int | Player moved in race order |
+| `lap_completed` | player_id: int, lap: int | Player finished a lap |
+| `race_completed` | results: Array | Final standings [{id, position}] |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `start_race` | `func start_race() -> void` | void | Initialize race state |
+| `end_race` | `func end_race() -> void` | void | Finalize race |
+| `on_race_completed` | `func on_race_completed(final_pos: int) -> void` | void | Player crossed finish line |
+| `get_current_finish_locations` | `func get_current_finish_locations() -> Array` | Array | Active finish positions |
+| `update_finish_availability` | `func update_finish_availability() -> void` | void | Recalculate finish positions |
+| `get_player_position` | `func get_player_position(player_id: int) -> int` | int | Current race order index |
+| `add_second_lap_goals` | `func add_second_lap_goals(goals: Array) -> void` | void | Set lap 2 goals |
+
+**Dependencies:** GoalsCycleManager.
+**Depended by:** player.gd, main.gd.
+
+[Back to top](#top)
+
+### 6.7 TurnManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/turn_manager.gd` (849 chars)
+**Extends:** Node
+**Autoload name:** TurnManager
+
+Turn-based sequencing for game modes that use round-robin or ordered turns (e.g., Stop n Go, Tekton Doors).
+
+**Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| current_turn | int | Index in turn order |
+| turn_order | Array | Player peer IDs in sequence |
+| is_my_turn | bool | Whether local player is active |
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `turn_changed` | player_id: int | Active turn changed |
+| `turn_order_set` | order: Array | Turn order established |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `set_turn_order` | `func set_turn_order(order: Array) -> void` | void | Establish turn sequence |
+| `next_turn` | `func next_turn() -> void` | void | Advance to next player |
+| `get_current_player` | `func get_current_player() -> int` | int | Current player peer ID |
+
+**Dependencies:** None.
+**Depended by:** StopNGoManager, GauntletManager, GoalsCycleManager.
+
+[Back to top](#top)
+
+
+## 7. Gameplay Managers
+
+[Back to top](#top)
+
+### 7.1 ObstacleManager
+
+[Back to top](#up)
+
+**File:** `/home/dev/tekton/scripts/managers/obstacle_manager.gd` (5,662 chars)
+**Extends:** Node
+**Autoload name:** ObstacleManager
+
+Obstacle placement and removal on the game grid. Handles wall tiles, blocking tiles, and destructible barriers.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `obstacle_placed` | cell: Vector3i, item_id: int | New obstacle added |
+| `obstacle_removed` | cell: Vector3i | Obstacle destroyed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `place_obstacle` | `func place_obstacle(cell: Vector3i, item_id: int) -> void` | void | Set obstacle on grid layer |
+| `remove_obstacle` | `func remove_obstacle(cell: Vector3i) -> void` | void | Clear obstacle |
+| `is_cell_blocked` | `func is_cell_blocked(cell: Vector3i, gridmap: Node) -> bool` | bool | Check if cell has blocking tile |
+| `get_blocked_cells` | `func get_blocked_cells(gridmap: Node) -> Array` | Array | All blocked cells |
+| `clear_all_obstacles` | `func clear_all_obstacles() -> void` | void | Remove all obstacles |
+
+**Dependencies:** EnhancedGridMap (scene ref).
+**Depended by:** PlayerMovementManager, SpecialTilesManager.
+
+[Back to top](#top)
+
+### 7.2 SpecialTilesManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/special_tiles_manager.gd` (23,090 chars)
+**Extends:** Node
+**Autoload name:** SpecialTilesManager
+
+Manages special floor tiles: ice (slippery), crack (breakable), portal tiles, teleporters, and other interactive terrain.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `tile_activated` | pos: Vector2i, tile_type: String | Tile effect triggered |
+| `ice_slide_started` | player_id: int | Player started sliding |
+| `crack_broke` | pos: Vector2i | Crack tile collapsed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `apply_tile_effect` | `func apply_tile_effect(player: Node, pos: Vector2i) -> void` | void | Activate tile effect on player |
+| `get_tile_at` | `func get_tile_at(pos: Vector2i, gridmap: Node) -> int` | int | Item ID at position |
+| `set_tile` | `func set_tile(pos: Vector2i, item_id: int, gridmap: Node) -> void` | void | Set tile item |
+| `is_ice_tile` | `func is_ice_tile(item_id: int) -> bool` | bool | Check ice type |
+| `is_crack_tile` | `func is_crack_tile(item_id: int) -> bool` | bool | Check crack type |
+| `is_portal_tile` | `func is_portal_tile(item_id: int) -> bool` | bool | Check portal type |
+| `spawn_portal_pair` | `func spawn_portal_pair(pos_a: Vector2i, pos_b: Vector2i) -> void` | void | Create portal entry/exit |
+| `remove_portal_pair` | `func remove_portal_pair(pos_a: Vector2i, pos_b: Vector2i) -> void` | void | Remove portal tiles |
+
+**Dependencies:** EnhancedGridMap, ObstacleManager, PortalModeManager.
+**Depended by:** PlayerMovementManager.
+
+[Back to top](#top)
+
+### 7.3 StaticTektonManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/static_tekton_manager.gd` (7,416 chars)
+**Extends:** Node
+**Autoload name:** StaticTektonManager
+
+Manages stationary Tekton turret behavior. Handles targeting, projectile spawning, and stun zones.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `turret_fired` | turret_id: int, target_pos: Vector2i | Turret shot |
+| `turret_stunned` | turret_id: int | Turret disabled |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `activate_turret` | `func activate_turret(turret: Node) -> void` | void | Start turret behavior |
+| `deactivate_turret` | `func deactivate_turret(turret: Node) -> void` | void | Stop turret |
+| `fire_at_player` | `func fire_at_player(turret: Node, target: Vector2i) -> void` | void | Fire projectile at grid pos |
+
+**Dependencies:** EnhancedGridMap, ObstacleManager.
+**Depended by:** main.gd.
+
+[Back to top](#top)
+
+
+## 8. UI / Presentation Managers
+
+[Back to top](#top)
+
+### 8.1 UIManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/ui_manager.gd` (21,645 chars)
+**Extends:** Node
+**Autoload name:** UIManager
+
+Manages the UI layer stack: show/hide panels, overlay management, HUD elements, and dynamic UI creation.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `panel_opened` | panel_name: String | Panel shown |
+| `panel_closed` | panel_name: String | Panel hidden |
+| `hud_updated` | data: Dictionary | HUD refresh |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `show_panel` | `func show_panel(panel_name: String, data: Dictionary = {}) -> void` | void | Show named panel |
+| `hide_panel` | `func hide_panel(panel_name: String) -> void` | void | Hide named panel |
+| `toggle_panel` | `func toggle_panel(panel_name: String) -> void` | void | Toggle panel visibility |
+| `show_hud` | `func show_hud() -> void` | void | Display HUD |
+| `hide_hud` | `func hide_hud() -> void` | void | Hide HUD |
+| `create_dynamic_ui` | `func create_dynamic_ui(scene_path: String) -> Node` | Node | Instantiate UI from tscn |
+| `destroy_dynamic_ui` | `func destroy_dynamic_ui(ui_node: Node) -> void` | void | Remove dynamic UI |
+| `focus_panel` | `func focus_panel(panel_name: String) -> void` | void | Bring panel to front |
+| `get_active_panels` | `func get_active_panels() -> Array` | Array | Currently visible panels |
+
+**Dependencies:** None.
+**Depended by:** main.gd, lobby.gd.
+
+[Back to top](#top)
+
+### 8.2 SfxManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/sfx_manager.gd` (2,046 chars)
+**Extends:** Node
+**Autoload name:** SfxManager
+
+Sound effect playback pool. Manages one-shot SFX with positional audio support.
+
+**Signals:** None.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `play` | `func play(sfx_name: String, position: Vector3 = Vector3.ZERO) -> void` | void | Play SFX by name, optionally 3D positioned |
+| `stop` | `func stop(sfx_name: String) -> void` | void | Stop specific SFX |
+| `stop_all` | `func stop_all() -> void` | void | Silence all SFX |
+| `set_volume` | `func set_volume(db: float) -> void` | void | Set master SFX volume |
+
+**Dependencies:** AudioStreamPlayer pool (scene).
+**Depended by:** player.gd, StopNGoManager, UIManager, many gameplay managers.
+
+[Back to top](#top)
+
+### 8.3 MusicManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/music_manager.gd` (4,082 chars)
+**Extends:** Node
+**Autoload name:** MusicManager
+
+Background music controller. Handles crossfade between tracks, playlist sequencing, and volume control.
+
+**Signals:** None.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `start_music` | `func start_music(track_name: String = "") -> void` | void | Begin playing track or playlist |
+| `stop_music` | `func stop_music(fade: float = 0.5) -> void` | void | Fade out and stop |
+| `crossfade_to` | `func crossfade_to(track_name: String, fade_duration: float = 1.0) -> void` | void | Smooth transition |
+| `set_volume` | `func set_volume(db: float) -> void` | void | Set master music volume |
+| `set_paused` | `func set_paused(paused: bool) -> void` | void | Pause/resume |
+| `get_current_track` | `func get_current_track() -> String` | String | Currently playing track name |
+
+**Dependencies:** AudioStreamPlayer (scene).
+**Depended by:** lobby.gd, main.gd.
+
+[Back to top](#top)
+
+### 8.4 NotificationManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/notification_manager.gd` (2,215 chars)
+**Extends:** Node
+**Autoload name:** NotificationManager
+
+On-screen message queue. Displays transient notification messages with type-based styling.
+
+**Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| MessageType (enum) | {NORMAL, WARNING, POWERUP, ERROR, SYSTEM} | Message severity/style |
+
+**Signals:** None.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `send_message` | `func send_message(sender: Node, message: String, msg_type: int = 0) -> void` | void | Queue message for display |
+| `clear_messages` | `func clear_messages() -> void` | void | Clear all pending messages |
+| `get_message_queue` | `func get_message_queue() -> Array` | Array | Current pending messages |
+
+**Dependencies:** None.
+**Depended by:** player.gd, main.gd (unstuck feedback), StopNGoManager, many gameplay managers.
+
+[Back to top](#top)
+
+### 8.5 ScreenShake
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/screen_shake.gd` (1,839 chars)
+**Extends:** Node
+**Autoload name:** ScreenShake
+
+Camera screen shake effect manager. Applies noise-based displacement to Camera3D.
+
+**Signals:** None.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `shake` | `func shake(intensity: float, duration: float = 0.3) -> void` | void | Trigger camera shake |
+| `stop_shake` | `func stop_shake() -> void` | void | Stop ongoing shake |
+
+**Dependencies:** Camera3D (scene).
+**Depended by:** player.gd (heavy knock triggers shake), main.gd.
+
+[Back to top](#top)
+
+### 8.6 CameraContextManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/camera_context_manager.gd` (2,543 chars)
+**Extends:** Node
+**Autoload name:** CameraContextManager
+
+Camera zoom level and context switching. Manages follow-camera behavior, zoom levels for different game phases, and camera transitions.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `zoom_changed` | level: float | Camera zoom level changed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `set_zoom` | `func set_zoom(level: float) -> void` | void | Set camera zoom |
+| `get_zoom` | `func get_zoom() -> float` | float | Current zoom |
+| `focus_on_player` | `func focus_on_player(player_id: int) -> void` | void | Snap camera to player |
+| `focus_on_position` | `func focus_on_position(world_pos: Vector3) -> void` | void | Center camera on position |
+
+**Dependencies:** Camera3D (scene).
+**Depended by:** main.gd.
+
+[Back to top](#top)
+
+### 8.7 TouchControls
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/touch_controls.gd` (23,640 chars)
+**Extends:** Node
+**Autoload name:** TouchControls
+
+Mobile touch input overlay. Provides virtual joystick, action buttons, and gesture recognition for grid-based controls.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `touch_moved` | direction: Vector2i | Grid direction from swipe |
+| `action_triggered` | action: String | Touch button pressed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `set_joystick_enabled` | `func set_joystick_enabled(enabled: bool) -> void` | void | Toggle joystick |
+| `get_joystick_direction` | `func get_joystick_direction() -> Vector2` | Vector2 | Normalized joystick |
+| `_save_settings` | internal | void | Persist touch control settings |
+
+**Dependencies:** InputManager (scene).
+**Depended by:** PlayerInputManager.
+
+[Back to top](#top)
+
+### 8.8 TutorialManager / TutorialOverlay
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/tutorial_manager.gd` (22,243 chars)
+**Extends:** Node
+**Autoload name:** TutorialManager
+
+Tutorial flow controller. Manages step-by-step tutorial sequences, triggers, and completion tracking.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `tutorial_started` | tutorial_id: String | Tutorial began |
+| `step_completed` | step: int | Step finished |
+| `tutorial_completed` | tutorial_id: String | Tutorial fully complete |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `start_tutorial` | `func start_tutorial(tutorial_id: String) -> void` | void | Begin tutorial sequence |
+| `advance_step` | `func advance_step() -> void` | void | Move to next step |
+| `skip_tutorial` | `func skip_tutorial() -> void` | void | Exit tutorial early |
+| `is_tutorial_active` | `func is_tutorial_active() -> bool` | bool | Tutorial in progress |
+| `get_current_step` | `func get_current_step() -> int` | int | Current step index |
+| `get_total_steps` | `func get_total_steps() -> int` | int | Total steps in tutorial |
+
+**File:** `/home/dev/tekton/scripts/managers/tutorial_overlay.gd` (11,077 chars)
+**Extends:** Node
+**Autoload name:** TutorialOverlay
+
+Tutorial UI overlay. Displays step instructions, highlights UI elements, and provides step navigation.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `overlay_closed` | none | Overlay dismissed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `show_step` | `func show_step(step_data: Dictionary) -> void` | void | Display step with text + highlight |
+| `hide_overlay` | `func hide_overlay() -> void` | void | Dismiss overlay |
+| `highlight_element` | `func highlight_element(node_path: NodePath) -> void` | void | Spotlight a UI element |
+| `clear_highlights` | `func clear_highlights() -> void` | void | Remove spotlights |
+
+**Dependencies:** TutorialManager, UIManager.
+**Depended by:** TutorialManager.
+
+[Back to top](#top)
+
+
+## 9. Social / Economy Managers
+
+[Back to top](#top)
+
+### 9.1 UserProfileManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/user_profile_manager.gd` (20,044 chars)
+**Extends:** Node
+**Autoload name:** UserProfileManager
+
+User profile CRUD operations. Manages display name, avatar, bio, wallet balance, stats, and loadout configuration. Syncs with Nakama storage.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `profile_loaded` | profile: Dictionary | Profile fetched from server |
+| `profile_updated` | none | Profile modified locally |
+| `wallet_updated` | wallet: Dictionary | Balance changed |
+| `stats_updated` | stats: Dictionary | Player stats changed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `load_profile` | `func load_profile() -> void` | void (async) | Fetch profile from Nakama storage |
+| `save_profile` | `func save_profile() -> void` | void (async) | Persist profile to Nakama |
+| `get_display_name` | `func get_display_name(fallback: String = "Player") -> String` | String | Display name with fallback |
+| `set_display_name` | `func set_display_name(name: String) -> void` | void | Update display name |
+| `get_avatar_url` | `func get_avatar_url() -> String` | String | Current avatar path |
+| `set_avatar` | `func set_avatar(url: String) -> void` | void | Change avatar |
+| `get_wallet_balance` | `func get_wallet_balance(currency: String) -> int` | int | Balance for gold/star |
+| `get_stats` | `func get_stats() -> Dictionary` | Dictionary | Player stats snapshot |
+| `update_stats` | `func update_stats(delta: Dictionary) -> void` | void | Increment stats |
+| `get_loadout` | `func get_loadout() -> Dictionary` | Dictionary | Current cosmetics loadout |
+| `set_loadout` | `func set_loadout(loadout: Dictionary) -> void` | void | Save cosmetics config |
+| `get_loadout_character` | `func get_loadout_character() -> String` | String | Selected character name |
+| `sync_wallet` | `func sync_wallet() -> void` | void (async) | Refresh wallet from server |
+
+**Dependencies:** NakamaManager, EventBus, BackendService.
+**Depended by:** LobbyMainMenu, lobby.gd, ShopManager, GachaManager, SkinManager, many UI panels.
+
+[Back to top](#top)
+
+### 9.2 GachaManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/gacha_manager.gd` (5,117 chars)
+**Extends:** Node
+**Autoload name:** GachaManager
+
+Gacha pull orchestration. Calls BackendService.perform_gacha_pull, processes results, updates inventory.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `gacha_result` | items: Array, fragments: Array | Pull results |
+| `gacha_error` | error: String | Pull failed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `perform_pull` | `func perform_pull(gacha_id: String, count: int) -> void` | void (async) | Execute gacha pull RPC |
+| `get_pity_count` | `func get_pity_count(banner_id: String) -> int` | int | Current pity counter |
+
+**Dependencies:** BackendService, UserProfileManager, EventBus.
+**Depended by:** gacha_panel.tscn (scene UI).
+
+[Back to top](#top)
+
+### 9.3 SkinManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/skin_manager.gd` (13,909 chars)
+**Extends:** Node
+**Autoload name:** SkinManager
+
+Cosmetic skin system. Manages skin definitions, owned skins, equipped loadout, and applies cosmetics to character models.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `skin_equipped` | skin_id: String | Skin applied |
+| `skin_unequipped` | skin_id: String | Skin removed |
+| `inventory_updated` | owned_skins: Array | Inventory changed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `equip_skin` | `func equip_skin(skin_id: String, slot: String) -> void` | void | Equip skin to slot |
+| `unequip_skin` | `func unequip_skin(slot: String) -> void` | void | Unequip from slot |
+| `is_skin_owned` | `func is_skin_owned(skin_id: String) -> bool` | bool | Check ownership |
+| `get_equipped_skins` | `func get_equipped_skins() -> Dictionary` | Dictionary | Current loadout |
+| `apply_loadout` | `func apply_loadout(character_root: Node3D, loadout: Dictionary) -> void` | void | Apply cosmetics to 3D model |
+| `get_skins_for_character` | `func get_skins_for_character(char_name: String) -> Array` | Array | Available skins |
+| `get_all_skins` | `func get_all_skins() -> Array` | Array | All skin definitions |
+
+**Dependencies:** UserProfileManager.
+**Depended by:** lobby.gd (3D preview), SkinShop UI.
+
+[Back to top](#top)
+
+### 9.4 ShopManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/shop_manager.gd` (484 chars)
+**Extends:** Node
+**Autoload name:** ShopManager
+
+Thin data layer for shop catalog. Currently a stub; full shop logic lives in scene scripts.
+
+**Properties:** Minimal (shop catalog array).
+
+**Signals:** None.
+
+**Public Functions:** None (data container only).
+
+**Dependencies:** BackendService.
+**Depended by:** shop_panel.tscn (scene).
+
+[Back to top](#top)
+
+### 9.5 JoinManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/join_manager.gd` (484 chars)
+**Extends:** Node
+**Autoload name:** JoinManager
+
+Thin manager for join code input and validation. Minimal stub.
+
+**Properties:** Minimal.
+
+**Signals:** None.
+
+**Public Functions:** None (stub).
+
+**Dependencies:** None.
+**Depended by:** lobby.gd (join code UI).
+
+[Back to top](#top)
+
+### 9.6 FriendManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/friend_manager.gd` (11,911 chars)
+**Extends:** Node
+**Autoload name:** FriendManager
+
+Friends list management. Handles friend requests, accept/reject, friend list sync, DM messaging, and lobby invitations.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `friend_list_updated` | friends: Array | Friend list refreshed |
+| `friend_request_received` | from_user_id: String | Incoming request |
+| `friend_added` | user_id: String | Friendship established |
+| `friend_removed` | user_id: String | Friendship ended |
+| `dm_message_received` | from_user_id: String, from_name: String, message: String | Direct message |
+| `lobby_invite_received` | from_user_id: String, from_name: String, match_id: String | Lobby invitation |
+| `friend_online_changed` | user_id: String, online: bool | Presence changed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `add_friend_by_id` | `func add_friend_by_id(nakama_id: String) -> bool` | bool (async) | Send friend request |
+| `remove_friend` | `func remove_friend(user_id: String) -> void` | void (async) | Remove friendship |
+| `accept_request` | `func accept_request(user_id: String) -> void` | void (async) | Accept friend request |
+| `decline_request` | `func decline_request(user_id: String) -> void` | void (async) | Decline request |
+| `get_friends` | `func get_friends() -> Array` | Array | Current friends list |
+| `get_mutual_friends` | `func get_mutual_friends() -> Array` | Array | Friends also in room |
+| `is_friend` | `func is_friend(nakama_id: String) -> bool` | bool | Check friendship |
+| `send_dm` | `func send_dm(user_id: String, text: String) -> bool` | bool (async) | Send direct message |
+| `get_dm_history` | `func get_dm_history(user_id: String) -> Array` | Array (async) | Fetch DM history |
+| `send_lobby_invite` | `func send_lobby_invite(to_user_id: String, match_id: String) -> void` | void (async) | Send invitation |
+
+**Dependencies:** BackendService, NakamaManager.
+**Depended by:** LobbyRoom, LobbyChat, lobby.gd.
+
+[Back to top](#top)
+
+### 9.7 MailManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/mail_manager.gd` (5,271 chars)
+**Extends:** Node
+**Autoload name:** MailManager
+
+Mail/inbox CRUD operations. Calls BackendService RPCs for get, claim, delete mail.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `mail_updated` | mails: Array | Mail list refreshed |
+| `unread_count_changed` | count: int | Unread mail count |
+| `mail_claimed` | mail_id: String, rewards: Dictionary | Reward collected |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `fetch_mail` | `func fetch_mail() -> void` | void (async) | Fetch mailbox |
+| `claim_mail` | `func claim_mail(mail_id: String) -> void` | void (async) | Claim reward |
+| `delete_mail` | `func delete_mail(mail_id: String) -> void` | void (async) | Delete mail |
+| `get_unread_count` | `func get_unread_count() -> int` | int | Unread count |
+
+**Dependencies:** BackendService.
+**Depended by:** lobby.gd, mailbox_panel.tscn (scene).
+
+[Back to top](#top)
+
+### 9.8 DailyRewardManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/daily_reward_manager.gd` (1,009 chars)
+**Extends:** Node
+**Autoload name:** DailyRewardManager
+
+Daily reward system. Handles claim state, reward config, and streak tracking.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `reward_claimed` | day: int, reward: Dictionary | Daily reward collected |
+| `streak_updated` | streak: int | Consecutive days |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `claim_daily_reward` | `func claim_daily_reward() -> void` | void (async) | Claim today's reward |
+| `get_reward_state` | `func get_reward_state() -> Dictionary` | Dictionary (async) | Current state + schedule |
+| `can_claim_today` | `func can_claim_today() -> bool` | bool | Check if claimable |
+
+**Dependencies:** BackendService.
+**Depended by:** daily_reward_panel.tscn (scene).
+
+[Back to top](#top)
+
+### 9.9 AdminManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/admin_manager.gd` (2,538 chars)
+**Extends:** Node
+**Autoload name:** AdminManager
+
+Admin panel state and permission checks. Determines if local player is admin or moderator.
+
+**Signals:** None.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `_check_admin_status` | `func _check_admin_status() -> bool` | bool (async) | Verify admin via Nakama storage |
+| `kick_player` | `func kick_player(player_id: int) -> void` | void (async) | Kick player from match |
+| `ban_player` | `func ban_player(player_id: int) -> void` | void (async) | Ban player |
+| `give_currency` | `func give_currency(gold: int, star: int) -> void` | void (async) | Admin give currency |
+
+**Dependencies:** BackendService, NakamaManager.
+**Depended by:** admin_panel.tscn (scene), LobbyChat (/clear command).
+
+[Back to top](#top)
+
+
+## 10. System Managers
+
+[Back to top](#top)
+
+### 10.1 SettingsManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/settings_manager.gd` (13,874 chars)
+**Extends:** Node
+**Autoload name:** SettingsManager
+
+User settings persistence. Reads/writes config to user://settings.cfg. Manages audio, video, gameplay, and control settings.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `setting_changed` | key: String, value: Variant | A setting was modified |
+| `settings_reset` | none | All settings restored to defaults |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `get_setting` | `func get_setting(key: String, default: Variant = null) -> Variant` | Variant | Read setting value |
+| `set_setting` | `func set_setting(key: String, value: Variant) -> void` | void | Write and persist setting |
+| `reset_settings` | `func reset_settings() -> void` | void | Restore defaults |
+| `load_settings` | `func load_settings() -> void` | void | Load from config file |
+| `save_settings` | `func save_settings() -> void` | void | Write to config file |
+| `get_all_settings` | `func get_all_settings() -> Dictionary` | Dictionary | Full settings snapshot |
+
+**Dependencies:** ConfigFile.
+**Depended by:** Audio buses, video settings, gameplay UI, settings_menu.tscn.
+
+[Back to top](#top)
+
+### 10.2 SessionManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/session_manager.gd` (4,742 chars)
+**Extends:** Node
+**Autoload name:** SessionManager
+
+Nakama session refresh lifecycle. Monitors session expiry and auto-refreshes before expiration.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `session_refreshed` | none | Token refreshed |
+| `session_expired` | none | Could not refresh |
+| `session_warning` | seconds_remaining: int | About to expire |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `start_monitoring` | `func start_monitoring() -> void` | void | Begin session expiry timer |
+| `stop_monitoring` | `func stop_monitoring() -> void` | void | Stop timer |
+| `refresh_now` | `func refresh_now() -> void` | void (async) | Force refresh |
+
+**Dependencies:** NakamaManager.
+**Depended by:** AuthManager.
+
+[Back to top](#top)
+
+### 10.3 GameUpdateManager
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scripts/managers/game_update_manager.gd` (14,405 chars)
+**Extends:** Node
+**Autoload name:** GameUpdateManager
+
+Hot-reload update system. Checks for patch.pck on the Gitea patches branch and downloads/loads it at runtime.
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `update_available` | version: String, changelog: String | New patch detected |
+| `update_downloading` | progress: float | Download progress |
+| `update_ready` | path: String | Patch downloaded and verified |
+| `update_failed` | error: String | Download error |
+| `up_to_date` | none | No update needed |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `check_for_updates` | `func check_for_updates() -> void` | void (async) | Query Gitea for latest patch |
+| `download_update` | `func download_update() -> void` | void (async) | Download patch.pck |
+| `apply_update` | `func apply_update() -> void` | void | Load patch from ProjectSettings |
+| `get_current_version` | `func get_current_version() -> String` | String | Current client version |
+| `get_available_version` | `func get_available_version() -> String` | String | Latest available version |
+
+**Dependencies:** HTTPRequest (scene).
+**Depended by:** boot_screen.tscn, main.gd.
+
+[Back to top](#top)
+
+
+## 11. Core Scene Scripts
+
+[Back to top](#top)
+
+### 11.1 main.gd (Main game scene controller)
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scenes/main.gd` (2956 lines)
+**Extends:** Node
+**Scene:** main.tscn
+
+The core game scene controller. Handles game initialization, player spawn, grid setup, goal cycle start, leaderboard display, pause menu, unstuck system, match cleanup, and result screen flow.
+
+**Key Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| enhanced_gridmap | Node | Reference to EnhancedGridMap child |
+| player_scene | PackedScene | Player.tscn loaded |
+| stop_n_go_winner_id | int | Winner's peer ID (-1 if none) |
+| _unstuck_cooldown_remaining | float | Unstuck button cooldown |
+| touch_controls | Node | TouchControls autoload ref |
+
+**Signals:**
+- (none declared; uses method-based event routing)
+
+**Public Functions (selected key ones):**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `_ready` | auto-called | void | Initializes ENet multiplayer, spawns players, starts goals cycle, sets up HUD |
+| `_process` | `func _process(delta: float) -> void` | void | Unstuck cooldown tick |
+| `_input` | `func _input(event: InputEvent) -> void` | void | ESC pause, F9 debug floor check |
+| `initialize_game` | -- | void | Create EnhancedGridMap, spawn player scene instances |
+| `spawn_player` | -- | Node | Instantiate player.tscn, position, set authority |
+| `_spawn_local_player` | -- | void | Create local player node |
+| `add_bot_players_if_needed` | -- | void | Fill remaining slots with bot players |
+| `display_message` | `func display_message(message: String, type: int) -> void` | void (RPC) | Broadcast message to local player's UI |
+| `request_leaderboard_sync` | `func request_leaderboard_sync() -> void` | void (RPC) | Client requests leaderboard from server |
+| `sync_leaderboard_data` | `func sync_leaderboard_data(player_data: Array) -> void` | void (RPC authority) | Receive + render leaderboard |
+| `_update_leaderboard_display` | internal | void | Local leaderboard refresh |
+| `_render_leaderboard_entries` | internal | void | Populate leaderboard entries |
+| `_get_ordinal` | `func _get_ordinal(n: int) -> String` | String | "1st", "2nd", "3rd", etc. |
+| `can_rpc` | `func can_rpc() -> bool` | bool | Check multiplayer peer state |
+| `check_multiplayer` | `func check_multiplayer() -> bool` | bool | Safety check for peer access |
+| `_toggle_pause_menu` | internal | void | Show/hide pause overlay |
+| `_on_resume_pressed` | -- | void | Close pause menu |
+| `_on_how_to_play_pressed` | -- | void | Open help panel |
+| `_on_settings_pressed` | -- | void | Open settings dynamically |
+| `_on_quit_match_pressed` | -- | void | Leave match, return to lobby |
+| `_on_unstuck_pressed` | -- | void | Teleport local player to safe position |
+| `_find_safe_spawn_position` | internal | Vector2i | Scan grid for safe walkable cell |
+| `_on_back_to_menu_pressed` | -- | void | Cleanup and transition to lobby |
+| `_cleanup_multiplayer` | -- | void | NakamaManager.cleanup() wrapper |
+| `_deferred_init_leaderboard` | internal | void | Delayed leaderboard init (1.5s) |
+| `_on_rematch_pressed` | -- | void | Request rematch vote |
+| `check_all_floors` | `func check_all_floors() -> void` | void | Debug F9: scan missing floor tiles |
+| `update_visual_position` | on player | void | Snap player to grid-aligned world position |
+| `grid_to_world` | on player | Vector3 | Convert grid Vector2i to world Vector3 |
+
+**RPCs (network-synced functions):**
+
+| Function | RPC Mode | Description |
+|---|---|---|
+| `request_leaderboard_sync` | any_peer | Client requests data from server |
+| `sync_leaderboard_data` | authority, call_local | Server sends leaderboard to client |
+| `display_message` | authority, call_local | Broadcast message to player UI |
+| `sync_position` (on player) | any_peer, call_local | Sync grid position |
+| `sync_grid_item` (on player) | any_peer, call_local | Sync grid cell item |
+| `sync_goals` (on player) | any_peer, call_local | Sync active goals |
+| `sync_rotation` (on player) | any_peer, call_local | Sync character rotation |
+| `sync_bump` (on player) | any_peer, call_local, unreliable | Visual bump animation |
+| `sync_knock_tekton` (on player) | any_peer, call_local, reliable | Knock tekton |
+| `sync_grab_tekton` (on player) | any_peer, call_local, reliable | Grab roaming tekton |
+| `sync_throw_tekton` (on player) | any_peer, call_local, reliable | Throw tekton |
+| `sync_drop_tekton` (on player) | any_peer, call_local, reliable | Drop tekton |
+| `set_spawn_position` (on player) | any_peer, call_local, reliable | Random spawn position |
+| `complete_race` (on player) | any_peer, call_local, reliable | Player finished race |
+| `force_action_state_none` (on player) | any_peer, call_local, reliable | Reset UI action state |
+| `request_server_grab` (on player) | any_peer, reliable | Server-authoritative grab |
+| `request_server_put` (on player) | any_peer, reliable | Server-authoritative put |
+| `notify_spawn_selected` (on player) | any_peer, reliable | Occupancy sync for spawn |
+| `trigger_screen_shake` | -- | Camera shake RPC |
+
+**Dependencies:** NakamaManager, LobbyManager, GameStateManager, PlayerMovementManager, PlayerActionManager, GoalsCycleManager, StopNGoManager, GauntletManager, PortalModeManager, PlayerRaceManager, PlayerboardManager, UIManager, SfxManager, MusicManager, NotificationManager, ScreenShake, CameraContextManager, TouchControls.
+**Depended by:** (this is the root game scene, depends on everything).
+
+[Back to top](#top)
+
+### 11.2 player.gd
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scenes/player.gd` (2751 lines)
+**Extends:** CharacterBody3D (assumed from Node3D methods)
+**Scene:** player.tscn
+
+The player character controller. Handles movement, action execution (grab/put/arrange), tekton interaction (carry/snatch/throw/knock), grid positioning, bot AI, visual synchronization, and playerboard management delegation.
+
+**Key Properties:**
+
+| Name | Type | Default | Description |
+|---|---|---|---|
+| current_position | Vector2i | Vector2i(0, 0) | Grid-aligned position |
+| cell_size | Vector3 | (1.0, 1.0, 1.0) | Grid cell dimensions |
+| cell_offset | Vector3 | Vector3.ZERO | Visual position offset |
+| is_player_moving | bool | false | Movement tween active |
+| is_carrying_tekton | bool | false | Holding roaming tekton |
+| carried_tekton | Node3D | null | Reference to carried tekton |
+| is_charged_strike | bool | false | Charged attack mode |
+| is_frozen | bool | false | Stun/freeze state |
+| is_stop_frozen | bool | false | Stop n Go freeze |
+| is_invisible | bool | false | Ghost mode |
+| is_bot | bool | false | Bot AI flag |
+| display_name | String | "" | Player display name |
+| score | int | 0 | Match score |
+| action_points | int | 1 | Actions per turn |
+| playerboard | Array | [-1, -1, ...] | Item slot board |
+| goals | Array | [] | Active goals |
+| enhanced_gridmap | Node | null | Grid reference |
+| anim_player | AnimationPlayer | null | Character animations |
+| movement_manager | PlayerMovementManager | ref | Movement delegation |
+| action_manager | PlayerActionManager | ref | Action delegation |
+| playerboard_manager | PlayerboardManager | ref | Board delegation |
+| race_manager | PlayerRaceManager | ref | Race delegate |
+| powerup_manager | PowerupManager | ref | Boost/charge delegate |
+
+**Signals:**
+
+| Signal | Params | Description |
+|---|---|---|
+| `position_changed` | none | Player grid position changed |
+
+**Public Functions (selected key ones):**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `_ready` | auto-called | void | Init references, connect signals, set initial position |
+| `_physics_process` | `func _physics_process(delta: float) -> void` | void | Movement smoothing, carry timer, unstuck timer |
+| `_input` | `func _input(event: InputEvent) -> void` | void | Click-to-move on gridmap, slot clicks |
+| `grid_to_world` | `func grid_to_world(pos: Vector2i) -> Vector3` | Vector3 | Convert grid to world coordinates |
+| `move_to_grid_position` | `func move_to_grid_position(target: Vector2i) -> void` | void | Initiate grid movement |
+| `grab_item` | `func grab_item(grid_pos: Vector2i = current_position) -> bool` | bool | Delegates to playerboard_manager.grab_item |
+| `auto_put_item` | `func auto_put_item() -> bool` | bool | Delegates auto-put |
+| `handle_playerboard_slot_selected` | `func handle_playerboard_slot_selected(slot_index: int) -> void` | void | Delegates to playerboard_manager |
+| `handle_put_slot_selected` | `func handle_put_slot_selected(slot_index: int) -> void` | void | Delegates put slot |
+| `arrange_playerboard_item` | `func arrange_playerboard_item(slot_index: int) -> void` | void | Delegates arrange |
+| `_on_slot_clicked` | `func _on_slot_clicked(event: InputEvent, slot_index: int) -> void` | void | Delegates to playerboard_manager |
+| `has_item_at_current_position` | `func has_item_at_current_position() -> bool` | bool | Check grid cell occupancy |
+| `has_items_in_playerboard` | `func has_items_in_playerboard() -> bool` | bool | Any items in board |
+| `playerboard_is_full` | `func playerboard_is_full() -> bool` | bool | All slots filled |
+| `highlight_movement_range` | `func highlight_movement_range() -> void` | void | Delegates to movement_manager |
+| `highlight_adjacent_cells` | `func highlight_adjacent_cells() -> void` | void | Delegates to movement_manager |
+| `highlight_cells_if_authorized` | `func highlight_cells_if_authorized(cells: Array, item_id: int) -> void` | void | Delegates to action_manager |
+| `clear_highlights` | `func clear_highlights() -> void` | void | Clear grid highlights |
+| `rotate_towards_target` | `func rotate_towards_target(target_pos: Vector2i) -> void` | void | Delegates to movement_manager |
+| `select_playerboard_slot` | `func select_playerboard_slot(slot_index: int) -> void` | void | Delegates to playerboard_manager |
+| `deselect_playerboard_slot` | `func deselect_playerboard_slot() -> void` | void | Clear selection |
+| `target_playerboard_slot` | `func target_playerboard_slot(slot_index: int) -> void` | void | Target slot for move |
+| `untarget_playerboard_slot` | `func untarget_playerboard_slot() -> void` | void | Clear target |
+| `can_move_to_target_playerboard_slot` | `func can_move_to_target_playerboard_slot() -> bool` | bool | Target slot validity |
+| `update_visual_position` | `func update_visual_position() -> void` | void | Snap to grid |
+| `grab_tekton` | `func grab_tekton() -> void` | void | Tekton interaction: snatch or grab |
+| `snatch_tekton` | `func snatch_tekton(target_carrier: Node3D) -> void` | void | Steal tekton from carrier |
+| `throw_tekton` | `func throw_tekton() -> void` | void | Throw tekton in facing direction |
+| `drop_tekton` | `func drop_tekton() -> void` | void | Drop tekton at current position |
+| `enter_charged_strike` | `func enter_charged_strike() -> void` | void | Activate charged attack mode |
+| `knock_tekton` | `func knock_tekton() -> void` | void | Special attack on nearby tekton |
+| `update_active_player_indicator` | `func update_active_player_indicator() -> void` | void | Refresh visual state |
+| `is_finish_position` | `func is_finish_position(pos: Vector2i) -> bool` | bool | Check if pos is a finish line |
+| `_after_action_completed` | internal | void | Post-action: cycle goals, check win |
+| `consume_action_points` | `func consume_action_points(points: int) -> void` | void | Deduct AP |
+| `display_message` | on player | void | Show notification to this player |
+| `apply_stagger` | `func apply_stagger(duration: float) -> void` | void | Stun for duration |
+
+**RPCs (network-synced functions on player.gd):**
+
+| Function | RPC Mode | Description |
+|---|---|---|
+| `sync_position` | any_peer, call_local | Sync current grid position |
+| `sync_rotation` | any_peer, call_local | Sync Y rotation |
+| `sync_grid_item` | any_peer, call_local | Sync grid cell item change |
+| `sync_goals` | any_peer, call_local | Sync active goal set |
+| `sync_second_lap_goals` | any_peer, call_local | Sync lap 2 goals |
+| `sync_grab_tekton` | any_peer, call_local, reliable | Grab tekton network sync |
+| `sync_snatch_tekton` | any_peer, call_local, reliable | Tekton theft sync |
+| `sync_throw_tekton` | any_peer, call_local, reliable | Throw tekton sync |
+| `sync_drop_tekton` | any_peer, call_local, reliable | Drop tekton sync |
+| `sync_bump` | any_peer, call_local, unreliable | Visual bump animation |
+| `sync_knock_tekton` | any_peer, call_local, reliable | Knock attack sync |
+| `set_spawn_position` | any_peer, call_local, reliable | Random spawn position |
+| `complete_race` | any_peer, call_local, reliable | Race completion |
+| `force_action_state_none` | any_peer, call_local, reliable | Reset UI action state |
+| `request_server_grab` | any_peer, reliable | Server-auth grab request |
+| `request_server_put` | any_peer, reliable | Server-auth put request |
+| `notify_spawn_selected` | any_peer, reliable | Spawn occupancy sync |
+| `trigger_screen_shake` | (authority) | Screen shake RPC |
+| `bot_grab_item` | any_peer, call_local | Bot grab sync |
+| `bot_put_item` | any_peer, call_local | Bot put sync |
+| `bot_arrange_item` | any_peer, call_local | Bot arrange sync |
+
+**Dependencies:** PlayerMovementManager, PlayerInputManager, PlayerActionManager, PlayerboardManager, PowerupManager, PlayerRaceManager, GoalsCycleManager, SfxManager, NotificationManager, EnhancedGridMap (scene node), LobbyManager.
+**Depended by:** main.gd (spawned per player).
+
+[Back to top](#top)
+
+### 11.3 lobby.gd
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scenes/lobby.gd` (583 lines)
+**Extends:** Control
+**Scene:** lobby.tscn
+
+The lobby/home screen controller. Manages main menu, room creation/joining, player slots, server selection, character selection, settings, mail, chat, social panel, and 3D character preview.
+
+**Key Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| chat | LobbyChat | Chat helper instance |
+| main_menu | LobbyMainMenu | Main menu helper |
+| room_list_helper | LobbyRoomList | Room list helper |
+| room_helper | LobbyRoom | Room/lobby helper |
+| character_textures | Dictionary | {char_name: Texture2D} |
+| profile_panel_instance | Control | Dynamic profile panel |
+| shop_panel_instance | Control | Dynamic shop panel |
+| daily_reward_panel_instance | Control | Daily reward panel |
+| leaderboard_panel_instance | Control | Leaderboard panel |
+| _mailbox_panel_instance | Control | Mail panel |
+| social_panel_instance | Control | Social panel |
+| _local_player_rank | int | Cached rank |
+| _bot_names | Dictionary | Slot index -> bot name |
+| _room_mode_filter | String | Room list filter |
+| _is_hosting | bool | Re-entry guard |
+
+**UI Node References (onready):**
+
+| Variable | Node Path | Type |
+|---|---|---|
+| main_menu_panel | $MainMenuPanel | Control |
+| main_title | %Title | Label |
+| username_label | %Username | Label |
+| create_room_btn | %CreateRoomBtn | Button |
+| browse_rooms_btn | %BrowseRoomsBtn | Button |
+| tutorial_btn | %TutorialBtn | Button |
+| main_menu_profile_btn | %MainProfileBtn | Button |
+| avatar_display | %AvatarDisplay | TextureRect |
+| lobby_settings_btn | %SettingsBtn | Button |
+| quit_btn | %QuitBtn | Button |
+| character_root | %CharacterRoot | Node3D |
+| anim_player | %AnimationPlayer | AnimationPlayer |
+| gold_label | %GoldLabel | Label |
+| star_label | %StarLabel | Label |
+| server_option | %ServerOption | OptionButton |
+| server_ip_input | %ServerIPInput | LineEdit |
+| leaderboard_btn | %LeaderboardBtn | Button |
+| shop_btn | %CartBtn | Button |
+| top_right_profile_btn | %ProfileBtn | Button |
+| mailbox_btn | %MailboxBtn | Button |
+| mail_badge | %MailBadge | Label |
+| banner1_btn | %Banner1 | Button |
+| ticket_btn | %TicketBtn | Button |
+| room_list_panel | %RoomListPanel | Control |
+| room_list | %RoomList | ItemList |
+| match_id_input | %MatchIdInput | LineEdit |
+| refresh_btn | %RefreshBtn | Button |
+| join_btn | %JoinBtn | Button |
+| back_btn | %RoomListCloseBtn | Button |
+| lobby_panel | $LobbyPanel | Control |
+| host_banner | $LobbyPanel/HostBanner | Panel |
+| match_id_display | $LobbyPanel/TopBar/... | Label |
+| copy_id_btn | $LobbyPanel/TopBar/... | Button |
+| duration_option | $LobbyPanel/TopBar/... | OptionButton |
+| random_spawn_check | `" " ` | CheckButton |
+| enable_timer_check | `" " ` | CheckButton |
+| scarcity_option | `" " ` | OptionButton |
+| game_mode_option | `" " ` | OptionButton |
+| players_container | $LobbyPanel/PlayersContainer | Control |
+| area_selector | $LobbyPanel/AreaSelector | Control |
+| leave_btn | $LobbyPanel/BottomBar/LeaveBtn | Button |
+| ready_btn | $LobbyPanel/BottomBar/ReadyBtn | Button |
+| start_game_btn | $LobbyPanel/BottomBar/StartGameBtn | Button |
+| connection_status | $StatusBar/ConnectionStatus | Label |
+| chat_display | %RichTextLabel | RichTextLabel |
+| chat_input | %ChatInput | LineEdit |
+| chat_send_btn | %SendBtn | Button |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `_ready` | auto-called | void | Initialize all helpers, load textures, setup UI, connect signals |
+| `_setup_3d_preview` | `func _setup_3d_preview() -> void` | void | Swap character model in SubViewport |
+| `_load_character_textures` | `func _load_character_textures() -> void` | void | Load preview textures |
+| `_on_server_option_selected` | `func _on_server_option_selected(index: int) -> void` | void | Handle server type dropdown |
+| `_on_server_ip_submitted` | `func _on_server_ip_submitted(new_text: String) -> void` | void | Handle IP input |
+| `_setup_game_modes` | `func _setup_game_modes() -> void` | void | Populate game mode dropdown |
+| `_setup_player_slots` | `func _setup_player_slots() -> void` | void | Collect player slot nodes |
+| `_connect_slot_signals` | `func _connect_slot_signals(slot: Control, i: int)` | void | Wire character nav buttons |
+| `_show_panel` | `func _show_panel(panel_name: String) -> void` | void | Toggle main_menu/room_list/lobby panels |
+| `_update_settings_visibility` | `func _update_settings_visibility() -> void` | void | Show/hide settings by mode and host status |
+| `_create_custom_settings_ui` | `func _create_custom_settings_ui() -> void` | void | Build SNG/Tekton Doors settings dynamically |
+| `_sync_room_profile_card` | `func _sync_room_profile_card() -> void` | void | Refresh username, score, rank, avatar, currency |
+| `_apply_loadout_character` | `func _apply_loadout_character() -> void` | void | Apply saved character to LobbyManager |
+| `admin_wipe_chat` | `func admin_wipe_chat() -> void` | void (async) | Admin: clear global chat |
+| `admin_purge_chat` | `func admin_purge_chat(max_age_days: int) -> int` | int (async) | Admin: purge old messages |
+
+**Dependencies:** AuthManager, NakamaManager, LobbyManager, UserProfileManager, SkinManager, MusicManager, FriendManager, MailManager, BackendService.
+**Depended by:** (root lobby scene; no dependents).
+
+[Back to top](#top)
+
+### 11.4 animation.gd
+
+[Back to top](#top)
+
+**File:** `/home/dev/tekton/scenes/animation.gd` (41 lines)
+**Extends:** Control
+**Scene:** (embedded in main.tscn for Stop n Go UI)
+
+Stop n Go phase animation player. Controls ready-go countdown, stop phase overlay, safe zone, and go animation sequences.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `play_ready_go` | `func play_ready_go() -> void` | void | Play ready-set-go sequence |
+| `play_stop_phase` | `func play_stop_phase() -> void` | void | Play STOP overlay |
+| `play_safe_zone_appear` | `func play_safe_zone_appear() -> void` | void | Show safe zone indicator |
+| `stop_phase_anim_play` | `func stop_phase_anim_play() -> void` | void | Play stop phase spritesheet |
+| `stop_phase_anim_stop` | `func stop_phase_anim_stop() -> void` | void | Stop phase animation |
+| `play_countdown_30s` | `func play_countdown_30s() -> void` | void | 30-second countdown |
+| `play_countdown_15s` | `func play_countdown_15s() -> void` | void | 15-second countdown |
+| `play_go_animation` | `func play_go_animation() -> void` | void | GO animation |
+| `play_go_finish_animation` | `func play_go_finish_animation() -> void` | void | Finish line animation |
+
+**Dependencies:** AnimatedSprite2D, AnimationPlayer (scene nodes).
+**Depended by:** StopNGoManager, main.gd.
+
+[Back to top](#top)
+
+
+## 12. UI Helper Classes (RefCounted)
+
+[Back to top](#top)
+
+All UI helper classes are RefCounted objects instantiated by lobby.gd in _ready(). They do NOT extend Node -- they are lightweight event wiring and state management objects.
+
+### 12.1 LobbyMainMenu
+
+[Back to top](#top)
+
+```gdscript
+class_name LobbyMainMenu extends RefCounted
+```
+
+**File:** `/home/dev/tekton/scenes/ui/lobby_main_menu.gd` (338 lines)
+
+Event wiring for main menu buttons. Connects all lobby button signals to handler methods.
+
+**Constructor:** `func _init(p_lobby: Control)` -- Stores lobby ref, connects 15+ button signals.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `on_tutorial_pressed` | `func on_tutorial_pressed() -> void` | void | Set name, apply loadout, call LobbyManager.start_tutorial |
+| `on_create_room_pressed` | `func on_create_room_pressed() -> void` | void | Show room list panel, create tab |
+| `host_room` | `func host_room(game_mode: String) -> void` | void | Guarded double-click, set name/mode, create Nakama or LAN room |
+| `on_browse_rooms_pressed` | `func on_browse_rooms_pressed() -> void` | void | Show room list, browse tab, refresh |
+| `on_profile_btn_pressed` | `func on_profile_btn_pressed() -> void` | void | Instantiate and show profile_panel.tscn |
+| `on_mailbox_pressed` | `func on_mailbox_pressed() -> void` | void | Instantiate and show mailbox_panel.tscn |
+| `on_settings_pressed` | `func on_settings_pressed() -> void` | void | Instantiate and show settings_menu.tscn |
+| `restore_after_settings` | `func restore_after_settings() -> void` | void | Restore lobby/main_menu panel visibility |
+| `on_shop_pressed` | `func on_shop_pressed() -> void` | void | Instantiate and show shop_panel.tscn |
+| `on_banner1_pressed` | `func on_banner1_pressed() -> void` | void | Instantiate and show gacha_panel.tscn |
+| `on_leaderboard_pressed` | `func on_leaderboard_pressed() -> void` | void | Show leaderboard_panel.tscn |
+| `on_ticket_pressed` | `func on_ticket_pressed() -> void` | void | Show daily_reward_panel.tscn |
+| `on_social_pressed` | `func on_social_pressed() -> void` | void | Show social_panel.tscn, hide main menu UI |
+| `on_logout_pressed` | `func on_logout_pressed() -> void` | void | AuthManager.logout() -> login screen |
+| `on_quit_pressed` | `func on_quit_pressed() -> void` | void | get_tree().quit() |
+| `go_to_login` | `func go_to_login() -> void` | void | Change scene to login_screen.tscn |
+
+**Dependencies:** AuthManager, LobbyManager, UserProfileManager, NakamaManager, BackendService.
+**Depended by:** lobby.gd.
+
+[Back to top](#top)
+
+### 12.2 LobbyRoom
+
+[Back to top](#top)
+
+```gdscript
+class_name LobbyRoom extends RefCounted
+```
+
+**File:** `/home/dev/tekton/scenes/ui/lobby_room.gd` (432 lines)
+
+Room/lobby panel event wiring. Handles ready/start/leave buttons, player slot rendering, character navigation, game mode/duration/scarcity settings, friend invites, and lobby invitation popup.
+
+**Constructor:** `func _init(p_lobby: Control)` -- Stores lobby ref, connects 20+ signals.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `_on_ready_toggled` | `func _on_ready_toggled(is_ready: bool) -> void` | void | Toggle ready state |
+| `_on_start_game_pressed` | `func _on_start_game_pressed() -> void` | void | Host starts game |
+| `_on_leave_pressed` | `func _on_leave_pressed() -> void` | void | Leave room, release bot names |
+| `_on_copy_id_pressed` | `func _on_copy_id_pressed() -> void` | void | Copy match ID to clipboard |
+| `_on_duration_selected` | `func _on_duration_selected(index: int) -> void` | void | Host sets match duration |
+| `_on_random_spawn_toggled` | `func _on_random_spawn_toggled(toggled_on: bool) -> void` | void | Toggle random spawn |
+| `_on_enable_timer_toggled` | `func _on_enable_timer_toggled(toggled_on: bool) -> void` | void | Toggle cycle timer |
+| `_on_scarcity_selected` | `func _on_scarcity_selected(index: int) -> void` | void | Host sets scarcity |
+| `_on_scarcity_mode_changed` | `func _on_scarcity_mode_changed(mode: String) -> void` | void | UI update for scarcity |
+| `_on_game_mode_selected` | `func _on_game_mode_selected(index: int) -> void` | void | Host sets game mode |
+| `_on_game_mode_changed` | `func _on_game_mode_changed(mode: String) -> void` | void | UI update for game mode |
+| `_on_sng_update` | `func _on_sng_update(_val: int = 0) -> void` | void | Sync SNG setting UI |
+| `_on_doors_update` | `func _on_doors_update(_val: int = 0) -> void` | void | Sync Doors setting UI |
+| `_on_room_joined` | `func _on_room_joined(room_data: Dictionary) -> void` | void | Switch to lobby panel, populate settings |
+| `_on_room_left` | `func _on_room_left() -> void` | void | Return to main menu |
+| `_on_host_disconnected` | `func _on_host_disconnected() -> void` | void | Show disconnect message |
+| `_on_player_joined` | `func _on_player_joined(player_data: Dictionary) -> void` | void | Update slots + status |
+| `_on_player_left` | `func _on_player_left(_player_id: int) -> void` | void | Update slots |
+| `_on_ready_state_changed` | `func _on_ready_state_changed(_player_id: int, _is_ready: bool) -> void` | void | Update slot visuals |
+| `_on_all_players_ready` | `func _on_all_players_ready() -> void` | void | Enable start button |
+| `_on_game_starting` | `func _on_game_starting() -> void` | void | Transition to main.tscn |
+| `_update_player_slots` | `func _update_player_slots() -> void` | void | Render all 8 player slots (players + bot slots) |
+| `_update_status` | `func _update_status() -> void` | void | Show ready count |
+| `_on_add_friend_pressed` | `func _on_add_friend_pressed(nakama_id: String) -> void` | void (async) | Add friend by Nakama ID |
+| `on_invite_friends_pressed` | `func on_invite_friends_pressed() -> void` | void | Open invite dialog |
+| `_on_lobby_invite_received` | `func _on_lobby_invite_received(from_user_id: String, from_name: String, match_id: String) -> void` | void | Show invite popup |
+| `_on_invite_accepted` | `func _on_invite_accepted() -> void` | void | Join invited match |
+
+**Dependencies:** LobbyManager, FriendManager, NakamaManager, NameGenerator, UserProfileManager.
+**Depended by:** lobby.gd.
+
+[Back to top](#top)
+
+### 12.3 LobbyRoomList
+
+[Back to top](#top)
+
+```gdscript
+class_name LobbyRoomList extends RefCounted
+```
+
+**File:** `/home/dev/tekton/scenes/ui/lobby_room_list.gd` (155 lines)
+
+Room list panel event wiring. Handles room list refresh, selection, join, and back navigation.
+
+**Constructor:** `func _init(p_lobby: Control)` -- Stores lobby ref, connects signals.
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `_on_refresh_pressed` | `func _on_refresh_pressed() -> void` | void | Clear + refresh room list |
+| `_on_room_selected` | `func _on_room_selected(index: int) -> void` | void | Copy room match_id/IP to input |
+| `_on_room_activated` | `func _on_room_activated(index: int) -> void` | void | Select + auto-join |
+| `_on_join_pressed` | `func _on_join_pressed() -> void` | void | Validate input, set name, join room (LAN or Nakama) |
+| `_on_back_pressed` | `func _on_back_pressed() -> void` | void | Return to main menu |
+| `on_room_list_updated` | `func on_room_list_updated(rooms: Array) -> void` | void | Render room rows, apply mode filter |
+
+**Dependencies:** LobbyManager, AuthManager, UserProfileManager.
+**Depended by:** lobby.gd.
+
+[Back to top](#top)
+
+### 12.4 LobbyChat
+
+[Back to top](#top)
+
+```gdscript
+class_name LobbyChat extends RefCounted
+```
+
+**File:** `/home/dev/tekton/scenes/ui/lobby_chat.gd` (373 lines)
+
+Global and direct message chat system. Handles Nakama socket channel chat, DM tabs, friend suggestions, and admin chat commands.
+
+**Constants:** `GLOBAL_CHAT_ROOM = "social_global"`
+
+**Properties:**
+
+| Name | Type | Description |
+|---|---|---|
+| _chat_channel | NakamaChannel | Current chat channel |
+| _chat_messages | Array | [{sender, content, ts, date}] |
+| _active_chat_context | String | "global" or user_id |
+| _dm_tabs | Dictionary | user_id -> HBoxContainer (tab UI) |
+| _dm_messages | Dictionary | user_id -> Array of messages |
+| _chat_config | Dictionary | {prefix, max_messages, max_age_days} |
+
+**Public Functions:**
+
+| Function | Signature | Return | Description |
+|---|---|---|---|
+| `join_global_chat` | `func join_global_chat() -> void` | void (async) | Join social_global channel, fetch history, inject prefix |
+| `switch_chat_tab` | `func switch_chat_tab(context_id: String) -> void` | void | Switch between global and DM tabs |
+| `_on_chat_send_pressed` | `func _on_chat_send_pressed() -> void` | void (async) | Send message: @username for DM, /clear for admin |
+| `on_lobby_dm_received` | `func on_lobby_dm_received(from_user_id: String, from_name: String, message: String) -> void` | void | Incoming DM handler |
+| `leave_global_chat` | `func leave_global_chat() -> void` | void (async) | Disconnect and leave channel |
+
+**Internal Functions:** `_add_chat_message`, `_send_dm_message`, `_open_dm_tab`, `_create_dm_tab`, `_close_dm_tab`, `_inject_local_message`, `_trim_old_messages`, `_refresh_chat_display`, `_format_nakama_time`, `_get_local_time`, `_on_chat_input_changed`, `_on_friend_suggest_activated`, `_setup_friend_suggest_ui`.
+
+**Dependencies:** NakamaManager, BackendService, FriendManager, AdminManager, UserProfileManager.
+**Depended by:** lobby.gd.
+
+[Back to top](#top)
+
+
+## 13. Dependency Graph
+
+[Back to top](#top)
+
+### 13.1 Manager Autoload Dependencies
+
+[Back to top](#top)
+
+ASCII diagram showing which autoloads reference others:
+
+```
+NakamaManager (no deps on other managers -- pure Nakama SDK)
+ |
+ +-- BackendService
+ | +-- SteamworksManager (child node, not autoload)
+ |
+ +-- AuthManager
+ | +-- NakamaManager
+ | +-- BackendService
+ |
+ +-- SessionManager
+ | +-- NakamaManager
+ |
+ +-- LobbyManager
+ | +-- NakamaManager
+ | +-- GameStateManager
+ |
+ +-- GameStateManager (no deps)
+ |
+ +-- PlayerManager (no deps -- data only)
+ |
+ +-- EventBus (no deps -- pure observer)
+ |
+ +-- UserProfileManager
+ | +-- NakamaManager
+ | +-- BackendService
+ | +-- EventBus
+ |
+ +-- FriendManager
+ | +-- BackendService
+ | +-- NakamaManager
+ |
+ +-- MailManager
+ | +-- BackendService
+ |
+ +-- GachaManager
+ | +-- BackendService
+ | +-- UserProfileManager
+ | +-- EventBus
+ |
+ +-- DailyRewardManager
+ | +-- BackendService
+ |
+ +-- AdminManager
+ | +-- BackendService
+ | +-- NakamaManager
+ |
+ +-- SkinManager
+ | +-- UserProfileManager
+ |
+ +-- ShopManager
+ | +-- BackendService (thin)
+ |
+ +-- PlayerInputManager
+ | +-- TouchControls
+ |
+ +-- PlayerMovementManager
+ | +-- ObstacleManager
+ | +-- SpecialTilesManager
+ | +-- EnhancedGridMap (scene)
+ |
+ +-- PlayerActionManager
+ | +-- PlayerboardManager
+ | +-- PlayerInputManager
+ | +-- GoalsCycleManager
+ |
+ +-- PlayerboardManager
+ | +-- GoalsCycleManager
+ | +-- GoalManager
+ |
+ +-- PlayerRaceManager
+ | +-- GoalsCycleManager
+ |
+ +-- GoalsCycleManager
+ | +-- GoalManager
+ | +-- TurnManager
+ | +-- Timer (scene)
+ |
+ +-- StopNGoManager
+ | +-- TurnManager
+ | +-- GoalManager
+ | +-- GoalsCycleManager
+ | +-- animation.gd (scene)
+ |
+ +-- GauntletManager
+ | +-- TurnManager
+ | +-- EnhancedGridMap
+ |
+ +-- PortalModeManager
+ | +-- SpecialTilesManager
+ | +-- EnhancedGridMap
+ |
+ +-- SpecialTilesManager
+ | +-- ObstacleManager
+ | +-- EnhancedGridMap
+ |
+ +-- ObstacleManager
+ | +-- EnhancedGridMap
+ |
+ +-- StaticTektonManager
+ | +-- EnhancedGridMap
+ | +-- ObstacleManager
+ |
+ +-- PowerupManager (no deps)
+ |
+ +-- UIManager (no deps -- dynamic UI)
+ |
+ +-- SettingsManager (no deps -- ConfigFile)
+ |
+ +-- GameUpdateManager (HTTPRequest -- no manager deps)
+ |
+ +-- TutorialManager
+ | +-- TutorialOverlay
+ |
+ +-- TutorialOverlay
+ | +-- TutorialManager
+ | +-- UIManager
+ |
+ +-- MusicManager (no deps)
+ +-- SfxManager (no deps)
+ +-- ScreenShake (no deps)
+ +-- NotificationManager (no deps)
+ +-- CameraContextManager (no deps)
+ +-- TouchControls (no deps)
+ +-- JoinManager (no deps -- stub)
+```
+
+[Back to top](#top)
+
+### 13.2 Cross-Manager Signal Wiring
+
+[Back to top](#top)
+
+Key signal connections between managers and scene scripts:
+
+```
+NakamaManager.match_joined -> LobbyManager._on_match_joined
+NakamaManager.match_join_error -> lobby.gd (clears _is_hosting)
+NakamaManager.connection_failed -> lobby.gd (clears _is_hosting)
+
+LobbyManager.room_joined -> LobbyRoom._on_room_joined
+LobbyManager.room_left -> LobbyRoom._on_room_left
+LobbyManager.host_disconnected -> LobbyRoom._on_host_disconnected
+LobbyManager.player_joined -> LobbyRoom._on_player_joined
+LobbyManager.player_left -> LobbyRoom._on_player_left
+LobbyManager.ready_state_changed -> LobbyRoom._on_ready_state_changed
+LobbyManager.all_players_ready -> LobbyRoom._on_all_players_ready
+LobbyManager.game_starting -> LobbyRoom._on_game_starting
+LobbyManager.game_mode_changed -> LobbyRoom._on_game_mode_changed
+LobbyManager.room_list_updated -> LobbyRoomList.on_room_list_updated
+LobbyManager.character_changed -> LobbyRoom._on_character_changed
+LobbyManager.rematch_votes_updated -> main.gd (update rematch button)
+
+FriendManager.dm_message_received -> LobbyChat.on_lobby_dm_received
+FriendManager.lobby_invite_received -> LobbyRoom._on_lobby_invite_received
+
+MailManager.unread_count_changed -> lobby.gd (update badge)
+
+UserProfileManager.profile_loaded -> lobby.gd (_sync_room_profile_card)
+UserProfileManager.profile_updated -> lobby.gd (_sync_room_profile_card)
+
+AuthManager.logged_out -> LobbyMainMenu.go_to_login
+```
+
+[Back to top](#top)
+
+
+## 14. Scene Node Trees
+
+[Back to top](#top)
+
+### 14.1 main.tscn
+
+[Back to top](#top)
+
+```
+Main (Node) -- attached: main.gd
+ +-- EnhancedGridMap (GridMap / custom EnhancedGridMap node)
+ +-- PlayerSpawnPoints (Node3D)
+ +-- HUD (CanvasLayer)
+ | +-- LeaderboardPanel (Panel)
+ | | +-- MarginContainer/VBox
+ | | +-- Entry1-8 (HBoxContainer with RankLabel/NameLabel/ScoreLabel)
+ | +-- NotificationOverlay (Control)
+ | +-- ActionButtons (Control)
+ +-- PauseMenu (Panel)
+ | +-- Panel/VBox/ResumeBtn, HowToPlayBtn, SettingsBtn, UnstuckBtn, QuitMatchBtn
+ +-- HowToPlayPanel (Panel)
+ +-- StopNGoUI (Control) -- attached: animation.gd
+ | +-- StopPhase/AnimatedSprite2D
+ | +-- AnimationPlayer
+ | +-- CountDown/CountDownAnimation (AnimatedSprite2D)
+ | +-- GoFinish/GoAnimation2D (AnimatedSprite2D)
+ +-- Camera3D
+ +-- WorldEnvironment
+ +-- Player instances (added dynamically by main.gd)
+ +-- Player (CharacterBody3D) -- attached: player.gd
+ +-- MeshInstance3D (visual)
+ +-- CollisionShape3D
+ +-- PlayerboardUI (Control overlay)
+ +-- AnimationPlayer
+```
+
+[Back to top](#top)
+
+### 14.2 player.tscn
+
+[Back to top](#top)
+
+```
+Player (CharacterBody3D) -- attached: player.gd
+ +-- MeshInstance3D (character model)
+ +-- CollisionShape3D
+ +-- PlayerboardUI (Control)
+ | +-- Slot0-9 (Panel/TextureRect)
+ +-- AnimationPlayer
+ +-- (tektons picked up become children at runtime)
+```
+
+[Back to top](#top)
+
+### 14.3 lobby.tscn
+
+[Back to top](#top)
+
+```
+Lobby (Control) -- attached: lobby.gd
+ +-- StatusBar (HBoxContainer)
+ | +-- ConnectionStatus (Label)
+ +-- MainMenuPanel (Panel)
+ | +-- Title/Username/Subtitle/Buttons (CreateRoom, BrowseRooms, Tutorial, etc.)
+ | +-- CharacterRoot (SubViewportContainer > SubViewport > Node3D)
+ | | +-- Oldpop, Masbro, Gatot, Bob (character meshes, hidden by default)
+ | +-- %AnimationPlayer
+ | +-- CurrencyLabels (GoldLabel, StarLabel)
+ | +-- ServerOption / ServerIPInput
+ | +-- LeaderboardBtn, CartBtn, ProfileBtn, MailboxBtn, Banner1Btn, TicketBtn
+ +-- RoomListPanel (Control)
+ | +-- RoomListTabs (TabContainer)
+ | +-- RoomTab, PlayTab
+ | +-- MatchIdInput, RefreshBtn, JoinBtn, BackBtn
+ | +-- RoomList (ItemList)
+ | +-- ItemTemplate (hidden)
+ | +-- ProfileCard (PlayerUsername, PlayerScore, Rank, Avatar)
+ +-- LobbyPanel (Panel)
+ | +-- RoomNameHeader
+ | +-- HostBanner
+ | +-- TopBar/SettingsSection (Duration, Spawn, Timer, Scarcity, GameMode options)
+ | +-- AreaSelector
+ | +-- PlayersContainer (slots 1-4)
+ | +-- PlayersContainer2 (slots 5-8)
+ | +-- BottomBar (LeaveBtn, ReadyBtn, StartGameBtn, InviteBtn)
+ | +-- StatusLabel
+ +-- ChatPanel (Panel)
+ | +-- RichTextLabel
+ | +-- ChatInput (LineEdit)
+ | +-- SendBtn
+ | +-- ChatTabsContainer (GlobalChatTabBtn + DM tabs)
+ | +-- FriendSuggestPanel (hidden)
+ +-- (dynamic instances: MailboxPanel, ShopPanel, GachaPanel, ProfilePanel, etc.)
+```
+
+[Back to top](#top)