diff --git a/src/jsMain/kotlin/HTMLUtils.kt b/src/jsMain/kotlin/HTMLUtils.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e9984968838f721ba2aa15e1f44abc664987cf1b
--- /dev/null
+++ b/src/jsMain/kotlin/HTMLUtils.kt
@@ -0,0 +1,9 @@
+import androidx.compose.runtime.Composable
+import org.jetbrains.compose.web.dom.Div
+
+@Composable
+fun divFloatRight(content: @Composable () -> Unit) {
+    Div({ classes("uk-float-right", "uk-margin-right") }) {
+        content()
+    }
+}
\ No newline at end of file
diff --git a/src/jsMain/kotlin/Main.kt b/src/jsMain/kotlin/Main.kt
index e36b58520a071825d65d3217ccd23c4deac61507..08cac8cb21288074407c07737fb3c33db17ada34 100644
--- a/src/jsMain/kotlin/Main.kt
+++ b/src/jsMain/kotlin/Main.kt
@@ -23,7 +23,7 @@ fun main() {
     renderComposable(root = rootDiv) {
         var state by remember { mutableStateOf<State>(Ready) }
 
-        Div({ classes("uk-float-right", "uk-margin-right") }) {
+        divFloatRight {
             val magicId = "csv-magic"
             Button({
                 classes("uk-button", "uk-button-small", "uk-button-success")
diff --git a/src/jsMain/kotlin/Modal.kt b/src/jsMain/kotlin/Modal.kt
index 0a3d640557284758db9f6bfc7514800652ecb011..b9da873db8402a720c457c017ea1e0119f24b79f 100644
--- a/src/jsMain/kotlin/Modal.kt
+++ b/src/jsMain/kotlin/Modal.kt
@@ -3,8 +3,13 @@ import kotlinx.browser.document
 import kotlinx.browser.window
 import kotlinx.coroutines.DelicateCoroutinesApi
 import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import org.jetbrains.compose.web.attributes.InputType
+import org.jetbrains.compose.web.attributes.disabled
+import org.jetbrains.compose.web.css.background
+import org.jetbrains.compose.web.css.color
+import org.jetbrains.compose.web.css.rgb
 import org.jetbrains.compose.web.dom.*
 import org.w3c.dom.HTMLAnchorElement
 import org.w3c.dom.HTMLElement
@@ -24,53 +29,123 @@ fun modal(setState: (State) -> Unit) {
             Text("CSV import")
         }
         H4 {
-            Text("Paraméterek")
+            Text("Mi is ez?")
+        }
+        Text("Válassz ki egy CSV filet, ami megfelel a következő követelményeknek:")
+        Ul {
+            Li { Text("az első sorában a pontozási elvek szerepelnek") }
+        }
+        Ul {
+            Li { Text("az első oszlopa az emberek neveit tartalmazza") }
+        }
+        Ul {
+            Li { Text("a közte lévő rész értelemszerűen van kitöltve") }
+        }
+        Ul {
+            Li { Text("tartalmazhat a táblázat szumma oszlopokat, " +
+                    "azok automatikusan ignorálva lesznek, amennyiben tartalmazzák a szumma szót") }
+        }
+        P { Text("Példa táblázat:") }
+        Table({classes("uk-table")}) {
+            Thead { Tr {
+                Th { Text("Név") }
+                Th { Text("Gyűlésen alvás") }
+                Th { Text("Közös liftezés") }
+                Th { Text("Szumma munka") }
+            } }
+            Tbody { Tr {
+                Td { Text("Teszt Elek") }
+                Td { Text("5") }
+                Td { Text("8") }
+                Td { Text("13") }
+            } }
+            Tbody { Tr {
+                Td { Text("Techno Kolos ") }
+                Td { Text("7") }
+                Td { Text("3") }
+                Td { Text("10") }
+            } }
         }
-        params()
         Hr {  }
         val scope = rememberCoroutineScope()
         var csvTable by remember { mutableStateOf<CSVTable?>(null) }
+
+        val valassz = "hint: válassz ki fájlt"
+        var hint by remember { mutableStateOf(valassz) }
+
         Input(type = InputType.File, attrs = {
             classes("uk-button", "uk-button-small")
             onChange {
+                if (it.value.isBlank()) {
+                    hint = valassz
+                    return@onChange
+                }
                 scope.launch {
                     val content = it.target.getFileContents()
                     content?.let { csv ->
-                        csvTable = CSVTable(csv)
+                        try {
+                            csvTable = CSVTable(csv)
+                        } catch (e: Exception) {
+                            hint = "hibás CSV fájl (infó a console-ban)"
+                            e.printStackTrace()
+                        }
+                        hint = ""
                     }
                 }
             }
         })
         Hr {  }
-        Button({
-            classes("uk-button", "uk-button-small", "uk-button-danger")
-            onClick {
-                scope.launch {
-                    PekTable.clear { setState(ImportInProgress(it)) }
-                    setState(Ready)
+        divFloatRight {
+            Button({
+                classes("uk-button", "uk-button-primary")
+                onClick {
+                    scope.launch {
+                        try {
+                            csvTable?.process { setState(ImportInProgress(it)) }
+                        } catch (e: ProcessingError) {
+                            delay(100)
+                            window.alert(e.toString())
+                        }
+                        setState(Ready)
+                    }
+                    (document.getElementById(closeId) as HTMLElement).click()
                 }
-                (document.getElementById(closeId) as HTMLElement).click()
+                if (hint.isNotBlank()) {
+                    disabled()
+                }
+            }) {
+                Text("Zsa!")
             }
-        }) {
-            Text("PéKen lévő adatok törlése")
         }
 
-        Button({
-            classes("uk-button", "uk-button-small", "uk-button-primary")
-            onClick {
-                scope.launch {
-                    try {
-                        csvTable?.process { setState(ImportInProgress(it)) }
-                    } catch (e: ProcessingError) {
-                        window.alert(e.toString())
+        divFloatRight {
+            Button({
+                classes("uk-button", "uk-button-danger")
+                onClick {
+                    scope.launch {
+                        PekTable.clear { setState(ImportInProgress(it)) }
+                        setState(Ready)
                     }
-                    setState(Ready)
+                    (document.getElementById(closeId) as HTMLElement).click()
                 }
-                (document.getElementById(closeId) as HTMLElement).click()
+            }) {
+                Text("PéKen lévő adatok törlése")
             }
-        }) {
-            Text("Zsa!")
         }
+        divFloatRight {
+            Button({
+                classes("uk-button")
+                style {
+                    background("#0000")
+                    color(rgb(0x55, 0x55, 0x55))
+                }
+                disabled()
+            }) {
+                Text(hint)
+            }
+        }
+
+        Br {  }
     }
 
 }
\ No newline at end of file
diff --git a/src/jsMain/kotlin/Process.kt b/src/jsMain/kotlin/Process.kt
index b1478a5a1fa3f37cb6f0608a17aa2d6d5d2f34b9..46ad42610c883ce1d13dff41c5ecfa23a8c04f42 100644
--- a/src/jsMain/kotlin/Process.kt
+++ b/src/jsMain/kotlin/Process.kt
@@ -1,4 +1,4 @@
-import kotlinx.coroutines.delay
+import kotlin.math.max
 
 class ProcessingError(val errors: List<String>): Exception(errors.toString()) {
     override fun toString(): String {
@@ -11,9 +11,9 @@ suspend fun CSVTable.process(
     progress: (Double) -> Unit = {}
 ) {
     progress(0.0)
-    val principleMappings = principles.map {
-        it to PekTable.principles.findClosestMatch(it)
-    }.toMap()
+    val principleMappings = principles.associateWith {
+        PekTable.principles.findClosestMatch(it)
+    }
 
     val errors = mutableListOf<String>()
 
@@ -21,7 +21,7 @@ suspend fun CSVTable.process(
         val pekPerson = PekTable.people.findClosestMatch(person)
 
         if (pekPerson == null) {
-            errors += "HIBA: Nem található '$person'"
+            errors += "Nem található '$person'"
             return@forEachIndexed
         }
         principles.forEachIndexed { j, principle ->
@@ -33,10 +33,10 @@ suspend fun CSVTable.process(
             progress(calcProgress(i, j, people.size, principles.size))
 
             if (person != pekPerson) {
-                errors += "WARN: assuming '$person' == '$pekPerson'"
+                errors += "Assuming '$person' == '$pekPerson'"
             }
             if (principle != pekPrinciple) {
-                errors += "WARN: assuming '$principle' == '$pekPrinciple'"
+                errors += "Assuming '$principle' == '$pekPrinciple'"
             }
         }
     }
@@ -49,9 +49,14 @@ fun List<String>.findClosestMatch(
 ): String? {
     val parts = string.split(" ", "-")
     return this.map {
+        val currParts = it.split(" ", "-")
+
+        val needleInHaystack = currParts.count { part -> string.contains(part) }
+        val haystackInNeedle = parts.count { part -> it.contains(part) }
+
         it to when {
             it == string -> Int.MAX_VALUE
-            else -> parts.count { part -> it.contains(part) }
+            else -> max(needleInHaystack, haystackInNeedle)
         }
     }.filter { it.second != 0 }.maxByOrNull { it.second }?.first
 }
\ No newline at end of file
diff --git a/src/jsMain/kotlin/Utils.kt b/src/jsMain/kotlin/Utils.kt
index 0b387da6543e1d0edc1039fe2105aa5d2ec51b6d..50b67b3b199c41a6e7957acb88cdb86832dc9b47 100644
--- a/src/jsMain/kotlin/Utils.kt
+++ b/src/jsMain/kotlin/Utils.kt
@@ -96,10 +96,28 @@ suspend fun PekTable.clear(
 private val saveIconElem = document.getElementById("save-icon") as HTMLDivElement
 val isUpdating get() = saveIconElem.style.display == "block"
 
-suspend fun pekDelay() {
-    delay(10)
-    while (isUpdating) { // még sül
-        delay(100)
+fun observeSaveChange(changed: () -> Unit): MutationObserver {
+    val observer = MutationObserver { _, _ ->
+        changed()
+    }
+    observer.observe(saveIconElem, MutationObserverInit(
+        attributes = true,
+        attributeFilter = arrayOf("style")
+    ))
+    return observer
+}
+
+suspend fun pekDelay() = suspendCoroutine<Unit> { cont ->
+    lateinit var observer: MutationObserver
+    observer = observeSaveChange {
+        if (!isUpdating) {
+            cont.resume(Unit)
+            observer.disconnect()
+        }
+    }
+    if (!isUpdating) {
+        cont.resume(Unit)
+        observer.disconnect()
     }
 }