Move SSD review UI colors to typed Kotlin

ober

a7f0885c81aba52c5319cc5f3f9cb543405b80d2

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 99ed1ae..abf2dd6 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -3702,12 +3702,14 @@
                 selectModeStatus selectionResultStatus
                 reviewPrimaryColor reviewWhiteColor reviewLabelTextColor
                 reviewLabelBackgroundColor reviewCanvasBackgroundColor
+                reviewAccentColor reviewModeColor reviewDarkTextColor
+                reviewNavColor reviewNeutralColor reviewDangerColor
                 groupStrokeColor selectedGroupFillColor
                 ssdAreaFillColor ssdAreaStrokeColor dragFillColor
                 cellStrokeWidth groupBaseStrokeWidth groupStrokeWidth
                 ssdAreaStrokeWidth dragStrokeWidth dragAnchorStrokeWidth
                 dragAnchorArmLength dragAnchorRadius touchPointerStrokeWidth
-                touchPointerOuterRadius touchPointerInnerRadius)
+                touchPointerOuterRadius touchPointerInnerRadius hitGroupPad)
         (type Int32)
         (type Float32)
         (extern (androidColorRgb (red : Int32)
@@ -3886,13 +3888,25 @@
           (androidColorArgb (int32 220) (int32 255) (int32 255) (int32 255)))
         (def (reviewCanvasBackgroundColor) : Int32
           (androidColorRgb (int32 248) (int32 250) (int32 252)))
+        (def (reviewAccentColor) : Int32
+          (androidColorRgb (int32 5) (int32 150) (int32 105)))
+        (def (reviewModeColor) : Int32
+          (androidColorRgb (int32 245) (int32 158) (int32 11)))
+        (def (reviewDarkTextColor) : Int32
+          (androidColorRgb (int32 15) (int32 23) (int32 42)))
+        (def (reviewNavColor) : Int32
+          (androidColorRgb (int32 51) (int32 65) (int32 85)))
+        (def (reviewNeutralColor) : Int32
+          (androidColorRgb (int32 226) (int32 232) (int32 240)))
+        (def (reviewDangerColor) : Int32
+          (androidColorRgb (int32 185) (int32 28) (int32 28)))
         (def (groupStrokeColor (selected : Bool) (status : String)) : Int32
           (if selected
             (reviewPrimaryColor)
             (if (or (equal? status "approved") (equal? status "reviewed"))
-              (androidColorRgb (int32 5) (int32 150) (int32 105))
+              (reviewAccentColor)
               (if (equal? status "rejected")
-                (androidColorRgb (int32 185) (int32 28) (int32 28))
+                (reviewDangerColor)
                 (androidColorArgb (int32 155) (int32 245) (int32 158) (int32 11))))))
         (def (selectedGroupFillColor) : Int32
           (androidColorArgb (int32 45) (int32 37) (int32 99) (int32 235)))
@@ -3926,6 +3940,10 @@
           (float32 9.0))
         (def (touchPointerInnerRadius) : Float32
           (float32 4.0))
+        (def (maxFloat32ForUi (a : Float32) (b : Float32)) : Float32
+          (if (> a b) a b))
+        (def (hitGroupPad (scale : Float32)) : Float32
+          (maxFloat32ForUi (float32 8.0) (scaledPixels (float32 32.0) scale)))
         (def (editedGroupCount (count : (Nullable Int32))
                                (fallback : Int32)) : Int32
           (if (nullable-null? count)
@@ -4974,12 +4992,12 @@
        "    }"
        ""
 	       "    private enum class ButtonKind(val backgroundColor: Int, val foregroundColor: Int, val textSp: Float, val heightDp: Int) {"
-	       "        PRIMARY(Color.rgb(37, 99, 235), Color.WHITE, 18f, 56),"
-	       "        ACCENT(Color.rgb(5, 150, 105), Color.WHITE, 18f, 56),"
-	       "        MODE(Color.rgb(245, 158, 11), Color.rgb(15, 23, 42), 17f, 54),"
-	       "        NAV(Color.rgb(51, 65, 85), Color.WHITE, 17f, 52),"
-	       "        NEUTRAL(Color.rgb(226, 232, 240), Color.rgb(15, 23, 42), 15f, 48),"
-	       "        DANGER(Color.rgb(185, 28, 28), Color.WHITE, 16f, 50)"
+	       "        PRIMARY(reviewPrimaryColor(), reviewWhiteColor(), 18f, 56),"
+	       "        ACCENT(reviewAccentColor(), reviewWhiteColor(), 18f, 56),"
+	       "        MODE(reviewModeColor(), reviewDarkTextColor(), 17f, 54),"
+	       "        NAV(reviewNavColor(), reviewWhiteColor(), 17f, 52),"
+	       "        NEUTRAL(reviewNeutralColor(), reviewDarkTextColor(), 15f, 48),"
+	       "        DANGER(reviewDangerColor(), reviewWhiteColor(), 16f, 50)"
 	       "    }"
 	       ""
 	       "    private fun dp(value: Int): Int = (value * resources.displayMetrics.density + 0.5f).toInt()"
@@ -6226,7 +6244,7 @@
        "                    (page.height * scale).toInt(),"
        "                    Bitmap.Config.ARGB_8888"
        "                )"
-       "                bitmap.eraseColor(android.graphics.Color.WHITE)"
+       "                bitmap.eraseColor(reviewWhiteColor())"
        "                page.render(bitmap, null, Matrix().apply { setScale(scale, scale) }, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)"
        "                return bitmap"
        "            }"
@@ -6680,8 +6698,6 @@
        "import android.view.ScaleGestureDetector"
        "import android.view.View"
        "import kotlin.math.abs"
-       "import kotlin.math.max"
-       "import kotlin.math.min"
        ""
        "class SsdReviewView(context: Context) : View(context) {"
        "    var bitmap: Bitmap? = null"
@@ -7100,7 +7116,7 @@
        ""
        "    private fun hitGroup(x: Float, y: Float): String? {"
        "        val sess = session ?: return null"
-       "        val pad = max(8f, 32f / scale)"
+       "        val pad = hitGroupPad(scale)"
        "        return hitGroupId(sess.groups, x, y, pad)"
        "    }"
        ""