Move SSD remote text fallbacks to typed Kotlin

ober

8a31a99ba43d29a35270fa29b82a7a1096894b58

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index e72c358..4250a8e 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -8778,10 +8778,10 @@
        ""
        "    private fun loadRemoteConfig(): RemoteConfig? {"
        "        val preferences = context.getSharedPreferences(\"ssd_review_remote\", Context.MODE_PRIVATE)"
-       "        val savedEndpoint = preferences.getString(\"base_url\", null)?.trim().orEmpty()"
+       "        val savedEndpoint = nullableTextOrEmpty(preferences.getString(\"base_url\", null)).trim()"
        "        val endpoint = normalizeRemoteEndpoint(savedEndpoint)"
-       "        val pinText = preferences.getString(\"spki_sha256\", null)?.trim().orEmpty()"
-       "        val token = preferences.getString(\"bearer_token\", null)?.trim().orEmpty()"
+       "        val pinText = nullableTextOrEmpty(preferences.getString(\"spki_sha256\", null)).trim()"
+       "        val token = nullableTextOrEmpty(preferences.getString(\"bearer_token\", null)).trim()"
        "        val url = URL(endpoint.trimEnd('/'))"
        "        require(remoteEndpointIsHttps(url.protocol, url.host)) { \"HTTPS endpoint required\" }"
        "        require(safeRemoteUrlParts(url.userInfo, url.query, url.ref)) { \"Unsafe endpoint URL\" }"
@@ -8893,7 +8893,7 @@
        "                if (writeRemoteTruth(remoteTruth, modified)) imported += 1"
        "                if (sameShipTruth(session, remoteTruth)) {"
        "                    val cached = truthForSession(session, remoteTruth)"
-       "                    if (writeRemoteTruth(cached, truthTime(remoteTruth) ?: modified, replaceIfMoreComplete = true)) {"
+       "                    if (writeRemoteTruth(cached, nullableByteCountOrDefault(truthTime(remoteTruth), modified), replaceIfMoreComplete = true)) {"
        "                        imported += 1"
        "                    }"
        "                }"
@@ -9233,11 +9233,15 @@
        "            budget.entries += 1"
        "            if (zipEntryCountExceeded(budget.entries, MAX_ZIP_ENTRIES)) throw IllegalStateException(\"Import tree exceeds entry limit\")"
        "            if (documentFileIsDirectory(child)) {"
-       "                val directoryName = child.name ?: return@forEach"
+       "                val rawDirectoryName = child.name"
+       "                if (!nullableTextPresent(rawDirectoryName)) return@forEach"
+       "                val directoryName = nullableTextOrEmpty(rawDirectoryName)"
        "                if (safePathComponentInvalid(directoryName)) throw IllegalStateException(\"Unsafe import directory\")"
        "                count += importTreeDir(child, File(localDir, directoryName), depth + 1, budget)"
        "            } else if (documentFileIsRegular(child)) {"
-       "                val name = child.name ?: return@forEach"
+       "                val rawName = child.name"
+       "                if (!nullableTextPresent(rawName)) return@forEach"
+       "                val name = nullableTextOrEmpty(rawName)"
        "                if (safeLeafInvalid(name)) return@forEach"
        "                val remaining = MAX_ZIP_TOTAL_BYTES - budget.expandedBytes"
        "                if (nonPositiveByteCount(remaining)) throw IllegalStateException(\"Import tree exceeds byte limit\")"