Complete typed Original Tactics MainActivity

ober

bbea7eab607ac786a657ba36b41e59ce999a8ae6

diff --git a/templates/original-tactics-parts/MainActivity.kt.ss b/templates/original-tactics-parts/MainActivity.kt.ss
index 2af05be..f4909b3 100644
--- a/templates/original-tactics-parts/MainActivity.kt.ss
+++ b/templates/original-tactics-parts/MainActivity.kt.ss
@@ -2,300 +2,3341 @@
 
 (def fragment
   '((typed-kotlin-file "com/jerboa/originaltactics/MainActivity.kt"
-      (kotlin-imports (android graphics Color)
-                      (org json JSONObject))
+      (kotlin-imports
+        (android app Activity)
+        (android app Dialog)
+        (android content Context)
+        (android content res Resources)
+        (android graphics Color)
+        (android graphics Typeface)
+        (android graphics drawable ColorDrawable)
+        (android graphics drawable GradientDrawable)
+        (android os Bundle)
+        (android text InputType)
+        (android view Gravity)
+        (android view View)
+        (android view ViewGroup)
+        (android view Window)
+        (android widget ArrayAdapter)
+        (android widget Button)
+        (android widget CheckBox)
+        (android widget EditText)
+        (android widget FrameLayout)
+        (android widget LinearLayout)
+        (android widget LinearLayout LayoutParams)
+        (android widget ScrollView)
+        (android widget Spinner)
+        (android widget SpinnerAdapter)
+        (android widget TextView)
+        (android util DisplayMetrics)
+        (java io File)
+        (java lang Runnable)
+        (java lang StringBuilder)
+        (java lang Thread)
+        (org json JSONArray)
+        (org json JSONObject))
       (typed-library (com jerboa originaltactics)
-        (export autoEventDelayMillis isPhaserWeapon weaponSortBucket
-                actorLabel fireGroupName hudActionLabel seekingSortBucket
-                shortDefenseKind truncateForLog isInterestingEvent)
-        (type Any)
-        (type Float32)
-        (type Int32)
-        (type JSONObject)
-        (extern (mainActivityColorRgb
-                  (red : Int32)
-                  (green : Int32)
-                  (blue : Int32)) : Int32
+        (export MainActivity autoEventDelayMillis isPhaserWeapon
+                weaponSortBucket actorLabel fireGroupName hudActionLabel
+                seekingSortBucket shortDefenseKind truncateForLog
+                isInterestingEvent)
+
+        (type Activity) (type ArrayAdapter) (type BattleCommandView)
+        (type BridgeHudView) (type Bundle) (type Button) (type CheckBox)
+        (type ColorDrawable) (type CombatLogView) (type CombatTimelineView)
+        (type CommandAvailabilityView) (type Context) (type Dialog)
+        (type EditText) (type Exception) (type File) (type FrameLayout)
+        (type GradientDrawable) (type Int32) (type Int64) (type JSONArray)
+        (type JSONObject) (type LayoutParams) (type LinearLayout)
+        (type RulesClient) (type Runnable) (type Resources) (type ScrollView)
+        (type SpinnerAdapter)
+        (type Sfc2IntelView) (type SfcShipArtView) (type SfcSound)
+        (type ShipStatusView) (type Spinner) (type SsdDamageView)
+        (type SystemsReadinessView) (type TacticalMapView) (type TextView)
+        (type StringBuilder) (type Thread) (type Throwable) (type Typeface) (type View)
+        (type ViewGroup) (type Window) (type ZoomPanFrameLayout)
+        (type DisplayMetrics)
+        (type Any) (type Float32)
+        (type Number)
+
+        ;; Android and Kotlin interop stays explicit so every emitted statement
+        ;; remains type checked by the Jerboa Kotlin backend.
+        (extern (maColorRgb (r : Int32) (g : Int32) (b : Int32)) : Int32
           (kotlin-call Color rgb))
-        (extern (mainActivityEventType
-                  (event : JSONObject)
-                  (key : String)
-                  (fallback : String)) : String
-          (kotlin-member-call optString))
-        (extern (mainActivityStringReplace
-                  (text : String)
-                  (old : String)
-                  (replacement : String)) : String
+        (extern (maColorTransparent) : Int32 (kotlin-value Color TRANSPARENT))
+        (extern (maTypefaceBold) : Typeface (kotlin-value Typeface DEFAULT_BOLD))
+        (extern (maVertical) : Int32 (kotlin-value LinearLayout VERTICAL))
+        (extern (maHorizontal) : Int32 (kotlin-value LinearLayout HORIZONTAL))
+        (extern (maMatchParent) : Int32 (kotlin-value ViewGroup LayoutParams MATCH_PARENT))
+        (extern (maWrapContent) : Int32 (kotlin-value ViewGroup LayoutParams WRAP_CONTENT))
+        (extern (maGravityCenterVertical) : Int32 (kotlin-value Gravity CENTER_VERTICAL))
+        (extern (maInputNumber) : Int32 (kotlin-value InputType TYPE_CLASS_NUMBER))
+        (extern (maInputText) : Int32 (kotlin-value InputType TYPE_CLASS_TEXT))
+        (extern (maContextPrivate) : Int32 (kotlin-value Context MODE_PRIVATE))
+        (extern (maSimpleSpinnerItem) : Int32
+          (kotlin-value android R layout simple_spinner_item))
+        (extern (maSimpleSpinnerDropdown) : Int32
+          (kotlin-value android R layout simple_spinner_dropdown_item))
+
+        (extern (maSuperOnCreate (state : (Nullable Bundle))) : Unit
+          (kotlin-call super onCreate))
+        (extern (maSuperOnPause) : Unit (kotlin-call super onPause))
+        (extern (maSuperOnDestroy) : Unit (kotlin-call super onDestroy))
+        (extern (maSetContentView (activity : MainActivity) (view : View)) : Unit
+          (kotlin-member-call setContentView))
+        (extern (maRunOnUiThread (activity : MainActivity) (action : (-> Unit))) : Unit
+          (kotlin-member-call runOnUiThread))
+        (extern (maGetPreferences (activity : MainActivity) (mode : Int32)) : Any
+          (kotlin-member-call getPreferences))
+        (extern (maPrefsGetString (prefs : Any) (key : String)
+                                  (fallback : (Nullable String))) : (Nullable String)
+          (kotlin-member-call getString))
+        (extern (maPrefsEdit (prefs : Any)) : Any (kotlin-member-call edit))
+        (extern (maEditorPutString (editor : Any) (key : String) (value : String)) : Any
+          (kotlin-member-call putString))
+        (extern (maEditorApply (editor : Any)) : Unit (kotlin-member-call apply))
+        (extern (maGetFileStreamPath (activity : MainActivity) (name : String)) : File
+          (kotlin-member-call getFileStreamPath))
+        (extern (maFileExists (file : File)) : Bool (kotlin-member-call exists))
+        (extern (maFileReadText (file : File)) : String (kotlin-member-call readText))
+        (extern (maFileWriteText (file : File) (text : String)) : Unit
+          (kotlin-member-call writeText))
+        (extern (maFileDelete (file : File)) : Bool (kotlin-member-call delete))
+
+        (extern (maLinearLayout (context : MainActivity)) : LinearLayout
+          (kotlin-call LinearLayout))
+        (extern (maScrollView (context : MainActivity)) : ScrollView
+          (kotlin-call ScrollView))
+        (extern (maFrameLayout (context : MainActivity)) : FrameLayout
+          (kotlin-call FrameLayout))
+        (extern (maTextView (context : MainActivity)) : TextView (kotlin-call TextView))
+        (extern (maEditText (context : MainActivity)) : EditText (kotlin-call EditText))
+        (extern (maSpinner (context : MainActivity)) : Spinner (kotlin-call Spinner))
+        (extern (maCheckBox (context : MainActivity)) : CheckBox (kotlin-call CheckBox))
+        (extern (maButton (context : MainActivity)) : Button (kotlin-call Button))
+        (extern (maDialog (context : MainActivity)) : Dialog (kotlin-call Dialog))
+        (extern (maLayoutParams (width : Int32) (height : Int32)) : LayoutParams
+          (kotlin-call LinearLayout LayoutParams))
+        (extern (maWeightedLayoutParams (width : Int32) (height : Int32)
+                                        (weight : Float32)) : LayoutParams
+          (kotlin-call LinearLayout LayoutParams))
+        (extern (maStringAdapter (context : MainActivity) (resource : Int32)
+                                 (items : (List String))) : SpinnerAdapter
+          (kotlin-call ArrayAdapter))
+
+        (extern (maLayoutOrientationSet (layout : LinearLayout) (value : Int32)) : Unit
+          (kotlin-member-set orientation))
+        (extern (maLayoutGravitySet (layout : LinearLayout) (value : Int32)) : Unit
+          (kotlin-member-set gravity))
+        (extern (maViewPadding (view : View) (l : Int32) (t : Int32)
+                               (r : Int32) (b : Int32)) : Unit
+          (kotlin-member-call setPadding))
+        (extern (maViewBackgroundColor (view : View) (color : Int32)) : Unit
+          (kotlin-member-call setBackgroundColor))
+        (extern (maViewBackgroundSet (view : View) (background : GradientDrawable)) : Unit
+          (kotlin-member-set background))
+        (extern (maLayoutAddView (layout : LinearLayout) (view : View)) : Unit
+          (kotlin-member-call addView))
+        (extern (maLayoutAddViewParams (layout : LinearLayout) (view : View)
+                                       (params : LayoutParams)) : Unit
+          (kotlin-member-call addView))
+        (extern (maScrollAddView (scroll : ScrollView) (view : View)) : Unit
+          (kotlin-member-call addView))
+        (extern (maFrameAddView (frame : FrameLayout) (view : View)) : Unit
+          (kotlin-member-call addView))
+        (extern (maTextSet (view : TextView) (text : String)) : Unit
+          (kotlin-member-set text))
+        (extern (maTextGet (view : TextView)) : Any (kotlin-member-get text))
+        (extern (maAnyToString (value : Any)) : String (kotlin-member-call toString))
+        (extern (maStringReplace (text : String) (old : String)
+                                 (replacement : String)) : String
           (kotlin-member-call replace))
-        (val UI_BG : Int32
-          (mainActivityColorRgb (int32 6) (int32 10) (int32 16))
-          (modifiers private))
-        (val UI_PANEL_DARK : Int32
-          (mainActivityColorRgb (int32 11) (int32 17) (int32 27))
-          (modifiers private))
-        (val UI_PANEL : Int32
-          (mainActivityColorRgb (int32 18) (int32 27) (int32 40))
-          (modifiers private))
-        (val UI_STROKE : Int32
-          (mainActivityColorRgb (int32 64) (int32 84) (int32 112))
+        (extern (maStringLowercase (text : String)) : String
+          (kotlin-member-call lowercase))
+        (extern (maStringSplitChar (text : String) (separator : Char)) : (List String)
+          (kotlin-member-call split))
+        (extern (maTextSizeSet (view : TextView) (size : Float32)) : Unit
+          (kotlin-member-set textSize))
+        (extern (maTextColorSet (view : TextView) (color : Int32)) : Unit
+          (kotlin-member-call setTextColor))
+        (extern (maTypefaceSet (view : TextView) (face : Typeface)) : Unit
+          (kotlin-member-set typeface))
+        (extern (maHintSet (view : EditText) (text : String)) : Unit
+          (kotlin-member-set hint))
+        (extern (maInputTypeSet (view : EditText) (kind : Int32)) : Unit
+          (kotlin-member-set inputType))
+        (extern (maEditSetText (view : EditText) (text : String)) : Unit
+          (kotlin-member-call setText))
+        (extern (maSingleLine (view : EditText) (enabled : Bool)) : Unit
+          (kotlin-member-call setSingleLine))
+        (extern (maEnabledSet (view : View) (enabled : Bool)) : Unit
+          (kotlin-member-set isEnabled))
+        (extern (maFocusableSet (view : View) (enabled : Bool)) : Unit
+          (kotlin-member-set isFocusable))
+        (extern (maCheckedSet (view : CheckBox) (checked : Bool)) : Unit
+          (kotlin-member-set isChecked))
+        (extern (maCheckedGet (view : CheckBox)) : Bool
+          (kotlin-member-get isChecked))
+        (extern (maButtonAllCaps (view : Button) (enabled : Bool)) : Unit
+          (kotlin-member-call setAllCaps))
+        (extern (maButtonOnClick (view : Button) (listener : (-> View Unit))) : Unit
+          (kotlin-member-call setOnClickListener))
+        (extern (maViewOnLongClick (view : View) (listener : (-> View Bool))) : Unit
+          (kotlin-member-call setOnLongClickListener))
+        (extern (maSpinnerAdapterSet (spinner : Spinner)
+                                     (adapter : SpinnerAdapter)) : Unit
+          (kotlin-member-set adapter))
+        (extern (maSpinnerSelected (spinner : Spinner)) : (Nullable Any)
+          (kotlin-member-get selectedItem))
+        (extern (maSpinnerSelection (spinner : Spinner) (index : Int32)) : Unit
+          (kotlin-member-call setSelection))
+        (extern (maSpinnerSelectedPosition (spinner : Spinner)) : Int32
+          (kotlin-member-get selectedItemPosition))
+        (extern (maSpinnerMinimumHeight (spinner : Spinner) (height : Int32)) : Unit
+          (kotlin-member-set minimumHeight))
+        (extern (maViewMinimumHeight (view : View) (height : Int32)) : Unit
+          (kotlin-member-set minimumHeight))
+        (extern (maViewInvalidate (view : View)) : Unit (kotlin-member-call invalidate))
+
+        (extern (maGradient) : GradientDrawable (kotlin-call GradientDrawable))
+        (extern (maGradientColor (drawable : GradientDrawable) (color : Int32)) : Unit
+          (kotlin-member-call setColor))
+        (extern (maGradientStroke (drawable : GradientDrawable) (width : Int32)
+                                  (color : Int32)) : Unit
+          (kotlin-member-call setStroke))
+        (extern (maGradientRadius (drawable : GradientDrawable) (radius : Float32)) : Unit
+          (kotlin-member-set cornerRadius))
+        (extern (maIntToFloat (value : Int32)) : Float32 (kotlin-member-call toFloat))
+        (extern (maFloatToInt (value : Float32)) : Int32 (kotlin-member-call toInt))
+        (extern (maActivityResources (activity : MainActivity)) : Resources
+          (kotlin-member-get resources))
+        (extern (maResourcesMetrics (resources : Resources)) : DisplayMetrics
+          (kotlin-member-get displayMetrics))
+        (extern (maMetricsDensity (metrics : DisplayMetrics)) : Float32
+          (kotlin-member-get density))
+        (extern (maActivityContext (activity : MainActivity)) : Context
+          (kotlin-cast Context))
+        (extern (maLinearAsView (view : LinearLayout)) : View (kotlin-cast View))
+        (extern (maTextAsView (view : TextView)) : View (kotlin-cast View))
+        (extern (maViewAsTextOrNull (view : View)) : (Nullable TextView)
+          (kotlin-safe-cast TextView))
+        (extern (maEditAsText (view : EditText)) : TextView (kotlin-cast TextView))
+        (extern (maCheckAsText (view : CheckBox)) : TextView (kotlin-cast TextView))
+        (extern (maButtonAsText (view : Button)) : TextView (kotlin-cast TextView))
+        (extern (maEditAsView (view : EditText)) : View (kotlin-cast View))
+        (extern (maSpinnerAsView (view : Spinner)) : View (kotlin-cast View))
+        (extern (maCheckAsView (view : CheckBox)) : View (kotlin-cast View))
+        (extern (maButtonAsView (view : Button)) : View (kotlin-cast View))
+        (extern (maMapAsView (view : TacticalMapView)) : View (kotlin-cast View))
+        (extern (maBridgeAsView (view : BridgeHudView)) : View (kotlin-cast View))
+        (extern (maTimelineAsView (view : CombatTimelineView)) : View (kotlin-cast View))
+        (extern (maLogAsView (view : CombatLogView)) : View (kotlin-cast View))
+        (extern (maCommandAsView (view : BattleCommandView)) : View (kotlin-cast View))
+        (extern (maAvailabilityAsView (view : CommandAvailabilityView)) : View
+          (kotlin-cast View))
+        (extern (maReadinessAsView (view : SystemsReadinessView)) : View
+          (kotlin-cast View))
+        (extern (maIntelAsView (view : Sfc2IntelView)) : View (kotlin-cast View))
+        (extern (maShipStatusAsView (view : ShipStatusView)) : View (kotlin-cast View))
+        (extern (maSsdAsView (view : SsdDamageView)) : View (kotlin-cast View))
+        (extern (maShipArtAsView (view : SfcShipArtView)) : View (kotlin-cast View))
+        (extern (maScrollAsView (view : ScrollView)) : View (kotlin-cast View))
+        (extern (maFrameAsView (view : FrameLayout)) : View (kotlin-cast View))
+
+        (extern (maDialogSetContent (dialog : Dialog) (view : View)) : Unit
+          (kotlin-member-call setContentView))
+        (extern (maDialogSetTitle (dialog : Dialog) (title : String)) : Unit
+          (kotlin-member-call setTitle))
+        (extern (maDialogShow (dialog : Dialog)) : Unit (kotlin-member-call show))
+        (extern (maDialogDismiss (dialog : Dialog)) : Unit (kotlin-member-call dismiss))
+        (extern (maDialogWindow (dialog : Dialog)) : (Nullable Window)
+          (kotlin-member-get window))
+        (extern (maWindowBackground (window : Window) (background : ColorDrawable)) : Unit
+          (kotlin-member-call setBackgroundDrawable))
+        (extern (maWindowLayout (window : Window) (width : Int32) (height : Int32)) : Unit
+          (kotlin-member-call setLayout))
+        (extern (maColorDrawable (color : Int32)) : ColorDrawable
+          (kotlin-call ColorDrawable))
+
+        (extern (maThread (runnable : Runnable)) : Thread (kotlin-call Thread))
+        (extern (maThreadStart (thread : Thread)) : Unit (kotlin-member-call start))
+        (extern (maThreadSleep (millis : Int)) : Unit (kotlin-call Thread sleep))
+        (extern (maThrowableMessage (error : Throwable)) : (Nullable String)
+          (kotlin-member-get message))
+        (extern (maThrowableText (error : Throwable)) : String
+          (kotlin-member-call toString))
+        (extern (maExceptionAsThrowable (error : Exception)) : Throwable
+          (kotlin-cast Throwable))
+
+        (extern (maJsonObject) : JSONObject (kotlin-call JSONObject))
+        (extern (maJsonObjectText (text : String)) : JSONObject (kotlin-call JSONObject))
+        (extern (maJsonArray) : JSONArray (kotlin-call JSONArray))
+        (extern (maJsonPutString (json : JSONObject) (key : String) (value : String)) : JSONObject
+          (kotlin-member-call put))
+        (extern (maJsonPutInt (json : JSONObject) (key : String) (value : Int32)) : JSONObject
+          (kotlin-member-call put))
+        (extern (maJsonPutBool (json : JSONObject) (key : String) (value : Bool)) : JSONObject
+          (kotlin-member-call put))
+        (extern (maJsonPutObject (json : JSONObject) (key : String) (value : JSONObject)) : JSONObject
+          (kotlin-member-call put))
+        (extern (maJsonPutArray (json : JSONObject) (key : String) (value : JSONArray)) : JSONObject
+          (kotlin-member-call put))
+        (extern (maJsonPutAny (json : JSONObject) (key : String) (value : Any)) : JSONObject
+          (kotlin-member-call put))
+        (extern (maJsonText (json : JSONObject)) : String (kotlin-member-call toString))
+        (extern (maJsonPretty (json : JSONObject) (indent : Int32)) : String
+          (kotlin-member-call toString))
+        (extern (maJsonArrayLength (json : JSONArray)) : Int32 (kotlin-member-call length))
+        (extern (maJsonArrayObject (json : JSONArray) (index : Int32)) : (Nullable JSONObject)
+          (kotlin-member-call optJSONObject))
+        (extern (maJsonArrayString (json : JSONArray) (index : Int32)) : String
+          (kotlin-member-call optString))
+        (extern (maJsonArrayAny (json : JSONArray) (index : Int32)) : (Nullable Any)
+          (kotlin-member-call opt))
+        (extern (maJsonArrayPutAny (json : JSONArray) (value : Any)) : JSONArray
+          (kotlin-member-call put))
+        (extern (maJsonArrayPutInt (json : JSONArray) (value : Int32)) : JSONArray
+          (kotlin-member-call put))
+        (extern (maJsonHas (json : JSONObject) (key : String)) : Bool
+          (kotlin-member-call has))
+        (extern (maJsonAny (json : JSONObject) (key : String)) : (Nullable Any)
+          (kotlin-member-call opt))
+        (extern (maJsonKeys (json : JSONObject)) : (Iterator String)
+          (kotlin-member-call keys))
+        (extern (maIteratorHasNext (it : (Iterator String))) : Bool
+          (kotlin-member-call hasNext))
+        (extern (maIteratorNext (it : (Iterator String))) : String
+          (kotlin-member-call next))
+        (extern (maAnyAsNumber (value : Any)) : (Nullable Number)
+          (kotlin-safe-cast Number))
+        (extern (maAnyAsStringValue (value : Any)) : (Nullable String)
+          (kotlin-safe-cast String))
+        (extern (maAnyAsJsonObject (value : Any)) : (Nullable JSONObject)
+          (kotlin-safe-cast JSONObject))
+        (extern (maAnyAsJsonArray (value : Any)) : (Nullable JSONArray)
+          (kotlin-safe-cast JSONArray))
+        (extern (maJsonObjectAsAny (value : JSONObject)) : Any (kotlin-cast Any))
+        (extern (maStringAsAny (value : String)) : Any (kotlin-cast Any))
+        (extern (maNumberInt (value : Number)) : Int32 (kotlin-member-call toInt))
+        (extern (maViewArraySize (views : (Array View))) : Int32
+          (kotlin-member-get size))
+        (extern (maViewArrayGet (views : (Array View)) (index : Int32)) : View
+          (kotlin-member-call get))
+        (extern (maEmptyStringIntMap) : (Map String Int32)
+          (kotlin-call emptyMap))
+        (extern (maMapStringIntKeys (values : (Map String Int32))) : (Set String)
+          (kotlin-member-get keys))
+        (extern (maMutableStringIntMapAsMap (values : (MutableMap String Int32)))
+                : (Map String Int32) (kotlin-cast (Map String Int32)))
+        (extern (maStringSetList (values : (Set String))) : (List String)
+          (kotlin-member-call toList))
+        (extern (maMutableStringListAsList (values : (MutableList String))) : (List String)
+          (kotlin-cast (List String)))
+        (extern (maMutableTargetListAsList (values : (MutableList FireTargetChoice)))
+                : (List FireTargetChoice) (kotlin-cast (List FireTargetChoice)))
+        (extern (maMutableShipListAsList (values : (MutableList ShipChoice)))
+                : (List ShipChoice) (kotlin-cast (List ShipChoice)))
+        (extern (maMutableIntListAsList (values : (MutableList Int32))) : (List Int32)
+          (kotlin-cast (List Int32)))
+        (extern (maStringBuilder) : StringBuilder (kotlin-call StringBuilder))
+        (extern (maStringBuilderAppend (out : StringBuilder) (text : String)) : StringBuilder
+          (kotlin-member-call append))
+        (extern (maStringBuilderText (out : StringBuilder)) : String
+          (kotlin-member-call toString))
+
+        (extern (maRulesClient (context : MainActivity) (endpoint : String)) : RulesClient
+          (kotlin-call RulesClient))
+        (extern (maRulesServiceEndpoint (client : RulesClient)) : String
+          (kotlin-member-call serviceEndpoint))
+        (extern (maRulesHealthEndpoint (client : RulesClient)) : String
+          (kotlin-member-call healthEndpoint))
+        (extern (maRulesMode (client : RulesClient)) : String
+          (kotlin-member-call modeLabel))
+        (extern (maRulesHealth (client : RulesClient) (url : String)) : String
+          (kotlin-member-call getHealth))
+        (extern (maRulesPost (client : RulesClient) (url : String) (body : String)
+                             (timeout : Int32)) : String
+          (kotlin-member-call post))
+        (extern (maAssetsPreload (context : MainActivity)) : Unit
+          (kotlin-call SfcAssets preload))
+        (extern (maAssetsRelease) : Unit (kotlin-call SfcAssets release))
+        (extern (maAssetsPlay (context : MainActivity) (sound : SfcSound) (volume : Float32)) : Unit
+          (kotlin-call SfcAssets play))
+        (extern (maSoundButton) : SfcSound (kotlin-value SfcSound BUTTON))
+        (extern (maSoundConfirm) : SfcSound (kotlin-value SfcSound CONFIRM))
+        (extern (maSoundPhaser) : SfcSound (kotlin-value SfcSound PHASER))
+        (extern (maSoundPhoton) : SfcSound (kotlin-value SfcSound PHOTON))
+        (extern (maSoundPlasma) : SfcSound (kotlin-value SfcSound PLASMA))
+        (extern (maSoundDisruptor) : SfcSound (kotlin-value SfcSound DISRUPTOR))
+        (extern (maSoundShield) : SfcSound (kotlin-value SfcSound SHIELD_HIT))
+        (extern (maSoundHull) : SfcSound (kotlin-value SfcSound HULL_HIT))
+        (extern (maSoundExplosion) : SfcSound (kotlin-value SfcSound EXPLOSION))
+
+        ;; Panel constructors and update calls.
+        (extern (maTacticalMap (context : MainActivity)) : TacticalMapView
+          (kotlin-call TacticalMapView))
+        (extern (maBridgeHud (context : MainActivity)) : BridgeHudView
+          (kotlin-call BridgeHudView))
+        (extern (maTimeline (context : MainActivity)) : CombatTimelineView
+          (kotlin-call CombatTimelineView))
+        (extern (maCombatLog (context : MainActivity)) : CombatLogView
+          (kotlin-call CombatLogView))
+        (extern (maBattleCommand (context : MainActivity)) : BattleCommandView
+          (kotlin-call BattleCommandView))
+        (extern (maCommandAvailability (context : MainActivity)) : CommandAvailabilityView
+          (kotlin-call CommandAvailabilityView))
+        (extern (maSystemsReadiness (context : MainActivity)) : SystemsReadinessView
+          (kotlin-call SystemsReadinessView))
+        (extern (maIntel (context : MainActivity)) : Sfc2IntelView
+          (kotlin-call Sfc2IntelView))
+        (extern (maShipStatus (context : MainActivity)) : ShipStatusView
+          (kotlin-call ShipStatusView))
+        (extern (maSsdDamage (context : MainActivity)) : SsdDamageView
+          (kotlin-call SsdDamageView))
+        (extern (maShipArt (context : MainActivity)) : SfcShipArtView
+          (kotlin-call SfcShipArtView))
+        (extern (maMapSetGame (view : TacticalMapView) (game : (Nullable JSONObject))
+                              (events : JSONArray)) : Unit
+          (kotlin-member-call setGame))
+        (extern (maMapSetStatus (view : TacticalMapView) (status : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setTacticalStatus))
+        (extern (maMapSetDashboard (view : TacticalMapView)
+                                   (dashboard : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setTacticalDashboard))
+        (extern (maBridgeSetData (view : BridgeHudView) (game : (Nullable JSONObject))
+                                 (dashboard : (Nullable JSONObject))
+                                 (events : JSONArray)) : Unit
+          (kotlin-member-call setData))
+        (extern (maTimelineSetGame (view : CombatTimelineView)
+                                   (game : (Nullable JSONObject))
+                                   (events : JSONArray)) : Unit
+          (kotlin-member-call setGame))
+        (extern (maTimelineSetDashboard (view : CombatTimelineView)
+                                        (dashboard : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setTacticalDashboard))
+        (extern (maLogSetData (view : CombatLogView) (game : (Nullable JSONObject))
+                              (events : JSONArray) (dashboard : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setData))
+        (extern (maCommandSetGame (view : BattleCommandView)
+                                  (game : (Nullable JSONObject))
+                                  (events : JSONArray)
+                                  (status : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setGame))
+        (extern (maAvailabilitySet (view : CommandAvailabilityView)
+                                   (alpha : (Nullable JSONObject))
+                                   (beta : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setReports))
+        (extern (maReadinessSet (view : SystemsReadinessView)
+                                (status : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setReport))
+        (extern (maIntelSetDashboard (view : Sfc2IntelView)
+                                     (dashboard : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setDashboard))
+        (extern (maIntelSetStatus (view : Sfc2IntelView)
+                                  (status : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setStatusReport))
+        (extern (maIntelSetTruth (view : Sfc2IntelView)
+                                 (alpha : (Nullable JSONObject))
+                                 (beta : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setTruthReports))
+        (extern (maShipStatusSet (view : ShipStatusView)
+                                 (game : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setGame))
+        (extern (maSsdSetData (view : SsdDamageView) (game : (Nullable JSONObject))
+                              (alpha : (Nullable JSONObject))
+                              (beta : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setData))
+        (extern (maShipArtSet (view : SfcShipArtView)
+                              (game : (Nullable JSONObject))) : Unit
+          (kotlin-member-call setGame))
+
+        ;; The checker treats class members as nominal Kotlin interop.  These
+        ;; declarations keep every intra-activity call typed without embedding
+        ;; source text or raw Kotlin AST nodes.
+        (extern (maSelfBuildUi (activity : MainActivity)) : View
+          (kotlin-member-call buildUi))
+        (extern (maSelfRestore (activity : MainActivity)) : Unit
+          (kotlin-member-call restoreLocalState))
+        (extern (maSelfSave (activity : MainActivity)) : Unit
+          (kotlin-member-call saveLocalState))
+        (extern (maSelfSaveAsync (activity : MainActivity)) : Unit
+          (kotlin-member-call saveLocalStateAsync))
+        (extern (maSelfLoadShips (activity : MainActivity)) : Unit
+          (kotlin-member-call loadShips))
+        (extern (maSelfSetStatus (activity : MainActivity) (text : String)) : Unit
+          (kotlin-member-call setStatus))
+        (extern (maSelfServiceEndpoint (activity : MainActivity)) : String
+          (kotlin-member-call serviceEndpoint))
+        (extern (maSelfHealth (activity : MainActivity)) : Unit
+          (kotlin-member-call getHealth))
+        (extern (maSelfNewGame (activity : MainActivity)) : Unit
+          (kotlin-member-call newGame))
+        (extern (maSelfAutoStep (activity : MainActivity)) : Unit
+          (kotlin-member-call runAutoStep))
+        (extern (maSelfAutoBattle (activity : MainActivity)) : Unit
+          (kotlin-member-call runAutoBattle))
+        (extern (maSelfAutoLoop (activity : MainActivity) (turns : Int32)) : Unit
+          (kotlin-member-call autoBattleLoop))
+        (extern (maSelfStopAuto (activity : MainActivity)) : Unit
+          (kotlin-member-call stopAutoBattle))
+        (extern (maSelfSubmitOrders (activity : MainActivity)) : Unit
+          (kotlin-member-call submitOrders))
+        (extern (maSelfCommitFire (activity : MainActivity)) : Unit
+          (kotlin-member-call commitAndFire))
+        (extern (maSelfFire (activity : MainActivity)) : Unit
+          (kotlin-member-call fireWeapons))
+        (extern (maSelfAdvance (activity : MainActivity)) : Unit
+          (kotlin-member-call advanceImpulse))
+        (extern (maSelfRunCombat (activity : MainActivity)) : Unit
+          (kotlin-member-call runCombat))
+        (extern (maSelfOpenPanel (activity : MainActivity) (title : String)
+                                 (view : View)) : Unit
+          (kotlin-member-call openPanel))
+        (extern (maSelfRefreshPanel (activity : MainActivity) (view : View)) : Unit
+          (kotlin-member-call refreshPanelView))
+        (extern (maSelfShowError (activity : MainActivity) (prefix : String)
+                                 (error : Throwable)) : Unit
+          (kotlin-member-call showError))
+        (extern (maSelfShowServiceError (activity : MainActivity) (prefix : String)
+                                        (error : Throwable) (request : JSONObject)) : Unit
+          (kotlin-member-call showServiceError))
+        (extern (maSelfShowRejected (activity : MainActivity) (response : JSONObject)
+                                    (request : JSONObject)) : Unit
+          (kotlin-member-call showServiceRejected))
+        (extern (maSelfPost (activity : MainActivity) (request : JSONObject)
+                            (busy : String) (handler : (-> JSONObject Unit))) : Unit
+          (kotlin-member-call postService))
+        (extern (maSelfHandleCatalog (activity : MainActivity)
+                                     (response : JSONObject)) : Unit
+          (kotlin-member-call handleShipCatalog))
+        (extern (maSelfSelectedShip (activity : MainActivity) (spinner : Spinner)
+                                    (fallback : String)) : String
+          (kotlin-member-call selectedShipId))
+        (extern (maSelfCreateGame (activity : MainActivity) (alpha : String)
+                                  (beta : String)) : Unit
+          (kotlin-member-call createNewGame))
+        (extern (maSelfGameOrStatus (activity : MainActivity)) : (Nullable JSONObject)
+          (kotlin-member-call gameOrStatus))
+        (extern (maSelfBuildOrders (activity : MainActivity) (game : JSONObject)) : JSONObject
+          (kotlin-member-call buildOrdersRequest))
+        (extern (maSelfPostCurrent (activity : MainActivity) (op : String)
+                                   (busy : String) (title : String)) : Unit
+          (kotlin-member-call postCurrentGame))
+        (extern (maSelfHandleResponse (activity : MainActivity) (response : JSONObject)
+                                      (title : String) (render : Bool)
+                                      (save : Bool)) : Unit
+          (kotlin-member-call handleGameResponse))
+        (extern (maSelfRenderSummary (activity : MainActivity)
+                                     (response : JSONObject)) : String
+          (kotlin-member-call renderGameSummary))
+        (extern (maSelfUpdateHud (activity : MainActivity)) : Unit
+          (kotlin-member-call updateBattleHud))
+        (extern (maSelfQueryPanels (activity : MainActivity) (game : JSONObject)) : Unit
+          (kotlin-member-call queryTacticalPanels))
+        (extern (maSelfQueryReport (activity : MainActivity) (op : String)
+                                   (game : JSONObject)
+                                   (handler : (-> JSONObject Unit))) : Unit
+          (kotlin-member-call queryReport))
+        (extern (maSelfQueryAction (activity : MainActivity) (game : JSONObject)
+                                   (actor : String)) : Unit
+          (kotlin-member-call queryActionAvailability))
+        (extern (maSelfQueryAllActions (activity : MainActivity) (game : JSONObject)) : Unit
+          (kotlin-member-call queryActionAvailability))
+        (extern (maSelfQueryObject (activity : MainActivity) (request : JSONObject)
+                                   (handler : (-> JSONObject Unit))) : Unit
+          (kotlin-member-call queryReportObject))
+        (extern (maSelfPlaySound (activity : MainActivity) (title : String)
+                                 (events : JSONArray)) : Unit
+          (kotlin-member-call playSoundForResponse))
+        (extern (maSelfSoundEvents (activity : MainActivity)
+                                   (events : JSONArray)) : (Nullable SfcSound)
+          (kotlin-member-call soundForEvents))
+        (extern (maSelfSoundWeapon (activity : MainActivity)
+                                   (payload : (Nullable JSONObject))) : SfcSound
+          (kotlin-member-call soundForWeaponPayload))
+        (extern (maSelfQueryTruthById (activity : MainActivity) (endpoint : String)
+                                      (templateId : String)) : (Nullable JSONObject)
+          (kotlin-member-call queryShipSsdTruthById))
+
+        (val UI_BG : Int32 (maColorRgb (int32 6) (int32 10) (int32 16))
           (modifiers private))
-        (val UI_TEXT : Int32
-          (mainActivityColorRgb (int32 231) (int32 238) (int32 248))
+        (val UI_PANEL_DARK : Int32 (maColorRgb (int32 11) (int32 17) (int32 27))
           (modifiers private))
-        (val UI_MUTED : Int32
-          (mainActivityColorRgb (int32 151) (int32 170) (int32 198))
+        (val UI_PANEL : Int32 (maColorRgb (int32 18) (int32 27) (int32 40))
           (modifiers private))
-        (val UI_DIM : Int32
-          (mainActivityColorRgb (int32 102) (int32 120) (int32 148))
+        (val UI_STROKE : Int32 (maColorRgb (int32 64) (int32 84) (int32 112))
           (modifiers private))
-        (val UI_ACCENT : Int32
-          (mainActivityColorRgb (int32 88) (int32 156) (int32 226))
+        (val UI_TEXT : Int32 (maColorRgb (int32 231) (int32 238) (int32 248))
           (modifiers private))
-        (val DEFAULT_ENDPOINT : String
-          "http://127.0.0.1:8788/api/service"
-          (modifiers private const))
-        (val CLIENT_LOG_ENDPOINT : String
-          "http://10.66.60.2:8799/api/client-log"
-          (modifiers private const))
-        (val PREF_ENDPOINT : String
-          "endpoint"
-          (modifiers private const))
-        (val PREF_STATE_SCHEMA_VERSION : String
-          "state_schema_version"
-          (modifiers private const))
-        (val STATE_SCHEMA_VERSION : Int32
-          (int32 2)
-          (modifiers private const))
-        (val GAME_STATE_FILE : String
-          "current_game.json"
-          (modifiers private const))
-        (var clientCrashLoggerInstalled : Bool
-          #f
-          (modifiers @Volatile private))
-        (val PAIR_MARKER : String
-          (string-append "$" "pair")
+        (val UI_MUTED : Int32 (maColorRgb (int32 151) (int32 170) (int32 198))
           (modifiers private))
-        (val PA_PANEL_BOX_CODE : String
-          "52"
-          (modifiers private const))
-        (val STATUS_TEXT_SP : Float32
-          (float32 18.0)
-          (modifiers private const))
-        (val OUTPUT_TEXT_SP : Float32
-          (float32 17.0)
-          (modifiers private const))
-        (val LABEL_TEXT_SP : Float32
-          (float32 18.0)
-          (modifiers private const))
-        (val CONTROL_TEXT_SP : Float32
-          (float32 20.0)
-          (modifiers private const))
-        (val BUTTON_TEXT_SP : Float32
-          (float32 16.0)
-          (modifiers private const))
-        (val SPINNER_TEXT_SP : Float32
-          (float32 19.0)
-          (modifiers private const))
-        (val FIRE_GROUP_ALL : Int32
-          (int32 1)
-          (modifiers private const))
-        (val FIRE_GROUP_HEAVY : Int32
-          (int32 2)
-          (modifiers private const))
-        (val FIRE_GROUP_PHASER : Int32
-          (int32 3)
-          (modifiers private const))
-        (val AUTO_QUIET_STEP_DELAY_MS : Int
-          (int 70)
-          (modifiers private const))
-        (val AUTO_MOVEMENT_STEP_DELAY_MS : Int
-          (int 320)
-          (modifiers private const))
-        (val AUTO_ACTION_EVENT_DELAY_MS : Int
-          (int 430)
-          (modifiers private const))
-        (val AUTO_COMBAT_EVENT_DELAY_MS : Int
-          (int 650)
-          (modifiers private const))
-        (val AUTO_UI_RENDER_INTERVAL_MS : Int
-          (int 450)
-          (modifiers private const))
-        (val SERVICE_READ_TIMEOUT_MS : Int32
-          (int32 30000)
-          (modifiers private const))
-        (val AUTO_BATTLE_READ_TIMEOUT_MS : Int32
-          (int32 30000)
+        (val DEFAULT_ENDPOINT : String "http://127.0.0.1:8788/api/service"
           (modifiers private const))
-        (val CLIENT_LOG_READ_TIMEOUT_MS : Int32
-          (int32 1500)
+        (val PREF_ENDPOINT : String "endpoint" (modifiers private const))
+        (val GAME_STATE_FILE : String "current_game.json" (modifiers private const))
+        (val CLIENT_LOG_ENDPOINT : String "http://127.0.0.1:8799/api/client-log"
           (modifiers private const))
-        (val CLIENT_LOG_CRASH_TIMEOUT_MS : Int32
-          (int32 1500)
-          (modifiers private const))
-        (val CLIENT_LOG_JSON_CHARS : Int32
-          (int32 6000)
-          (modifiers private const))
-        (val CLIENT_LOG_STACK_CHARS : Int32
-          (int32 12000)
-          (modifiers private const))
-        (val AUTO_GAME_EVENT_LIMIT : Int32
-          (int32 32)
-          (modifiers private const))
-        (val STATE_SAVE_DEBOUNCE_MS : Int
-          (int 500)
-          (modifiers private const))
-        (val DASHBOARD_QUERY_MIN_INTERVAL_MS : Int
-          (int 350)
-          (modifiers private const))
-        (val STATUS_QUERY_MIN_INTERVAL_MS : Int
-          (int 350)
-          (modifiers private const))
-        (val ACTION_QUERY_MIN_INTERVAL_MS : Int
-          (int 500)
-          (modifiers private const))
-        (val HUD_ACTION_PRIORITY : (List String)
-          (list-of String
-            "direct-fire"
-            "seeking-launch"
-            "shuttle-operations"
-            "wild-weasel-preparation"
-            "suicide-shuttle"
-            "scatter-pack"
-            "carrier-fighter-operations"
-            "pf-operations"
-            "tractors"
-            "transporters"
-            "shield-control"
-            "continuous-damage-repair"
-            "emergency-damage-repair"
-            "electronic-warfare"
-            "automated-battle")
-          (modifiers private))
+        (val PAIR_MARKER : String "$pair" (modifiers private const))
+        (val PA_PANEL_BOX_CODE : String "52" (modifiers private const))
+        (val SERVICE_READ_TIMEOUT_MS : Int32 (int32 30000) (modifiers private const))
+        (val AUTO_BATTLE_READ_TIMEOUT_MS : Int32 (int32 30000) (modifiers private const))
+        (val FIRE_GROUP_ALL : Int32 (int32 1) (modifiers private const))
+        (val FIRE_GROUP_HEAVY : Int32 (int32 2) (modifiers private const))
+        (val FIRE_GROUP_PHASER : Int32 (int32 3) (modifiers private const))
+        (val AUTO_QUIET_STEP_DELAY_MS : Int (int 70) (modifiers private const))
+        (val AUTO_MOVEMENT_STEP_DELAY_MS : Int (int 320) (modifiers private const))
+        (val AUTO_ACTION_EVENT_DELAY_MS : Int (int 430) (modifiers private const))
+        (val AUTO_COMBAT_EVENT_DELAY_MS : Int (int 650) (modifiers private const))
         (val MANEUVERS : (List String)
-          (list-of String
-            "none" "left" "right"
-            "sideslip-left" "sideslip-right" "het")
+          (list-of String "none" "left" "right" "sideslip-left" "sideslip-right" "het")
           (modifiers private))
         (val DEFAULT_SEEKING_KINDS : (List String)
-          (list-of String
-            "none"
-            "drone"
-            "drone-i-slow"
-            "drone-iv-slow"
-            "plasma"
-            "plasma-f"
-            "plasma-g"
-            "plasma-s"
-            "plasma-r"
-            "plasma-d")
+          (list-of String "none" "drone" "drone-i-slow" "drone-iv-slow"
+                   "plasma" "plasma-f" "plasma-g" "plasma-s" "plasma-r" "plasma-d")
           (modifiers private))
+
         (def (autoEventDelayMillis (type : String)) : Int
           (if (or (equal? type "fire-weapons")
                   (or (equal? type "direct-fire")
                       (or (equal? type "seeking-impact")
-                          (or (equal? type "suicide-shuttle-impact")
-                              (or (equal? type "ship-destroyed")
-                                  (or (equal? type "game-over")
-                                      (equal? type "victory")))))))
-            AUTO_COMBAT_EVENT_DELAY_MS
-            (if (or (equal? type "seeking-launch")
-                    (or (equal? type "defensive-fire")
-                        (or (equal? type "damage-applied")
-                            (or (equal? type "ew-control")
-                                (or (equal? type "ew-support")
-                                    (or (equal? type "ew-support-rejected")
-                                        (or (equal? type "ew-support-lost")
-                                            (or (equal? type "lock-on-control")
-                                                (or (equal? type "shield-control")
-                                                    (or (equal? type "energy-allocation")
-                                                        (or (equal? type "web-created")
-                                                            (or (equal? type "web-reduced")
-                                                                (or (equal? type "web-caster")
-                                                                    (or (equal? type "web-snare")
-                                                                        (or (equal? type "web-breaker")
-                                                                            (or (equal? type "wild-weasel-preparation")
-                                                                                (or (equal? type "scatter-pack")
-                                                                                    (or (equal? type "suicide-shuttle")
-                                                                                        (or (equal? type "turn-blocked")
-                                                                                            (equal? type "maneuver-blocked"))))))))))))))))))))
-              AUTO_ACTION_EVENT_DELAY_MS
-              (if (or (equal? type "movement")
-                      (or (equal? type "turn")
-                          (or (equal? type "sideslip")
-                              (or (equal? type "high-energy-turn")
-                                  (or (equal? type "shuttle-movement")
-                                      (equal? type "seeking-movement"))))))
-                AUTO_MOVEMENT_STEP_DELAY_MS
-                AUTO_QUIET_STEP_DELAY_MS))))
+                          (or (equal? type "ship-destroyed")
+                              (or (equal? type "game-over") (equal? type "victory"))))))
+              AUTO_COMBAT_EVENT_DELAY_MS
+              (if (or (equal? type "seeking-launch")
+                      (or (equal? type "damage-applied")
+                          (or (equal? type "energy-allocation")
+                              (or (equal? type "turn-blocked")
+                                  (equal? type "maneuver-blocked")))))
+                  AUTO_ACTION_EVENT_DELAY_MS
+                  (if (or (equal? type "movement")
+                          (or (equal? type "turn")
+                              (or (equal? type "sideslip")
+                                  (equal? type "high-energy-turn"))))
+                      AUTO_MOVEMENT_STEP_DELAY_MS
+                      AUTO_QUIET_STEP_DELAY_MS))))
         (def (isPhaserWeapon (weapon : String)) : Bool
           (string-starts-with? weapon "phaser"))
         (def (weaponSortBucket (weapon : String)) : Int32
-          (if (isPhaserWeapon weapon)
-            (int32 2)
-            (if (or (string-contains? weapon "drone")
-                    (string-contains? weapon "plasma"))
-              (int32 1)
-              (int32 0))))
+          (if (isPhaserWeapon weapon) (int32 2)
+              (if (or (string-contains? weapon "drone")
+                      (string-contains? weapon "plasma"))
+                  (int32 1) (int32 0))))
         (def (actorLabel (actor : String)) : String
           (if (equal? actor "alpha") "Alpha" "Beta"))
         (def (fireGroupName (group : Int32)) : String
-          (if (= group FIRE_GROUP_HEAVY)
-            "heavy"
-            (if (= group FIRE_GROUP_PHASER) "phaser" "all")))
+          (if (= group FIRE_GROUP_HEAVY) "heavy"
+              (if (= group FIRE_GROUP_PHASER) "phaser" "all")))
         (def (hudActionLabel (id : String)) : String
-          (if (equal? id "direct-fire")
-            "fire"
-            (if (equal? id "seeking-launch")
-              "seek"
-              (if (equal? id "shuttle-operations")
-                "units"
-                (if (equal? id "wild-weasel-preparation")
-                  "ww"
-                  (if (equal? id "suicide-shuttle")
-                    "suicide"
-                    (if (equal? id "scatter-pack")
-                      "scatter"
-                      (if (equal? id "carrier-fighter-operations")
-                        "ftr"
-                        (if (equal? id "pf-operations")
-                          "pf"
-                          (if (equal? id "tractors")
-                            "tractor"
-                            (if (equal? id "transporters")
-                              "tran"
-                              (if (equal? id "shield-control")
-                                "shield"
-                                (if (equal? id "continuous-damage-repair")
-                                  "repair"
-                                  (if (equal? id "emergency-damage-repair")
-                                    "emerg"
-                                    (if (equal? id "electronic-warfare")
-                                      "ew"
-                                      (if (equal? id "automated-battle")
-                                        "auto"
-                                        (mainActivityStringReplace id "-" " ")))))))))))))))))
+          (if (equal? id "direct-fire") "fire"
+              (if (equal? id "seeking-launch") "seek"
+                  (if (equal? id "transporters") "tran"
+                      (maStringReplace id "-" " ")))))
         (def (seekingSortBucket (kind : String)) : Int32
-          (if (string-starts-with? kind "drone")
-            (int32 0)
-            (if (equal? kind "plasma")
-              (int32 1)
-              (if (string-starts-with? kind "plasma")
-                (int32 2)
-                (int32 3)))))
+          (if (string-starts-with? kind "drone") (int32 0)
+              (if (equal? kind "plasma") (int32 1)
+                  (if (string-starts-with? kind "plasma") (int32 2) (int32 3)))))
         (def (shortDefenseKind (kind : String)) : String
           (if (equal? kind "pa-panels") "pa" "sh"))
         (def (truncateForLog (text : String) (limit : Int32)) : String
-          (if (<= (string-length-int32 text) limit)
-            text
-            (string-append
-              (string-take text limit)
-              (string-append
-                "...[truncated "
-                (string-append
-                  (int32->string (- (string-length-int32 text) limit))
-                  " chars]")))))
+          (if (<= (string-length-int32 text) limit) text
+              (string-append (string-take text limit) "...[truncated]")))
         (def (isInterestingEvent (event : JSONObject)) : Bool
-          (let ((type
-                  (mainActivityEventType event "type" "")))
+          (let ((type (json-object-opt-string-default event "type" "")))
             (and (not (string-blank? type))
-                 (not (equal? type "impulse-activity")))))))))
+                 (not (equal? type "impulse-activity")))))
+
+        (record ShipChoice
+          ((id : String) (name : String) (race : String)
+           (source : String) (page : Int32) (display : String)))
+        (record FireTargetChoice
+          ((key : String) (label : String) (target : JSONObject)))
+        (record TruthMatch
+          ((entry : JSONObject) (score : Int32) (overlap : Int32) (diff : Int32)))
+        (record FullscreenPanelSpec
+          ((title : String) (factory : (-> View))))
+        (enum CommandTone ()
+          (NAV) (PRIMARY) (WEAPON) (AUTO) (DANGER) (UTILITY))
+
+        (def (maDp (activity : MainActivity) (value : Int32)) : Int32
+          (maFloatToInt
+            (* (maIntToFloat value)
+               (maMetricsDensity
+                 (maResourcesMetrics (maActivityResources activity))))))
+        (def (maPanelBackground (activity : MainActivity) (color : Int32)) : GradientDrawable
+          (let ((background (maGradient)))
+            (begin
+              (maGradientColor background color)
+              (maGradientStroke background (int32 1) UI_STROKE)
+              (maGradientRadius background (float32 8.0))
+              background)))
+        (def (maRunBackground (action : (-> Unit))) : Unit
+          (maThreadStart
+            (maThread
+              (object Runnable (override (run) : Unit (invoke action))))))
+        (def (maTextOf (view : TextView)) : String
+          (maAnyToString (maTextGet view)))
+        (def (maIntFromText (view : EditText) (fallback : Int32)
+                            (low : Int32) (high : Int32)) : Int32
+          (let ((parsed (string->int32-or-null
+                          (string-trim (maTextOf (maEditAsText view))))))
+            (if (nullable-null? parsed) fallback
+                (let ((value (nullable-get parsed)))
+                  (if (< value low) low (if (> value high) high value))))))
+        (def (maStringAdapterFor (activity : MainActivity)
+                                 (items : (List String))) : SpinnerAdapter
+          (maStringAdapter activity (maSimpleSpinnerItem) items))
+        (def (maSetSpinnerStrings (activity : MainActivity) (spinner : Spinner)
+                                  (items : (List String))) : Unit
+          (maSpinnerAdapterSet spinner (maStringAdapterFor activity items)))
+        (def (maSelectedString (spinner : Spinner) (fallback : String)) : String
+          (let ((selected (maSpinnerSelected spinner)))
+            (if (nullable-null? selected) fallback
+                (maAnyToString (nullable-get selected)))))
+
+        (class MainActivity () (extends Activity)
+          (var endpointInput : EditText (modifiers private lateinit))
+          (var fireImpulseInput : EditText (modifiers private lateinit))
+          (var runImpulsesInput : EditText (modifiers private lateinit))
+          (var autoTurnsInput : EditText (modifiers private lateinit))
+          (var alphaSpeedInput : EditText (modifiers private lateinit))
+          (var betaSpeedInput : EditText (modifiers private lateinit))
+          (var alphaManeuverImpulseInput : EditText (modifiers private lateinit))
+          (var betaManeuverImpulseInput : EditText (modifiers private lateinit))
+          (var alphaSeekingImpulseInput : EditText (modifiers private lateinit))
+          (var betaSeekingImpulseInput : EditText (modifiers private lateinit))
+          (var alphaFireSelectionInput : EditText (modifiers private lateinit))
+          (var betaFireSelectionInput : EditText (modifiers private lateinit))
+          (var alphaDirectFireCheck : CheckBox (modifiers private lateinit))
+          (var betaDirectFireCheck : CheckBox (modifiers private lateinit))
+          (var showRawCheck : CheckBox (modifiers private lateinit))
+          (var alphaSpinner : Spinner (modifiers private lateinit))
+          (var betaSpinner : Spinner (modifiers private lateinit))
+          (var alphaTargetSpinner : Spinner (modifiers private lateinit))
+          (var betaTargetSpinner : Spinner (modifiers private lateinit))
+          (var alphaManeuverSpinner : Spinner (modifiers private lateinit))
+          (var betaManeuverSpinner : Spinner (modifiers private lateinit))
+          (var alphaSeekingSpinner : Spinner (modifiers private lateinit))
+          (var betaSeekingSpinner : Spinner (modifiers private lateinit))
+          (var tacticalMap : TacticalMapView (modifiers private lateinit))
+          (var bridgeHud : BridgeHudView (modifiers private lateinit))
+          (var combatTimeline : CombatTimelineView (modifiers private lateinit))
+          (var combatLog : CombatLogView (modifiers private lateinit))
+          (var battleCommand : BattleCommandView (modifiers private lateinit))
+          (var commandAvailability : CommandAvailabilityView (modifiers private lateinit))
+          (var systemsReadiness : SystemsReadinessView (modifiers private lateinit))
+          (var sfc2Intel : Sfc2IntelView (modifiers private lateinit))
+          (var shipStatus : ShipStatusView (modifiers private lateinit))
+          (var ssdDamage : SsdDamageView (modifiers private lateinit))
+          (var shipArt : SfcShipArtView (modifiers private lateinit))
+          (var status : TextView (modifiers private lateinit))
+          (var battleHud : TextView (modifiers private lateinit))
+          (var output : TextView (modifiers private lateinit))