diff --git a/mosogepsch/build.gradle.kts b/mosogepsch/build.gradle.kts
index 46e18fe1f499e789573e9bc993e2e69f959b7abc..2a5fd2eb0392cab44fb1385e22e4db70527f07d3 100644
--- a/mosogepsch/build.gradle.kts
+++ b/mosogepsch/build.gradle.kts
@@ -39,7 +39,6 @@ kotlin {
                 implementation(compose.runtime)
                 implementation("app.softwork:bootstrap-compose:0.0.49")
                 implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2")
-                implementation(npm("@js-joda/core", "1.11.0"))
                 implementation(npm("@js-joda/timezone", "2.3.0"))
                 implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.2.1")
             }
diff --git a/mosogepsch/src/jsMain/kotlin/Main.kt b/mosogepsch/src/jsMain/kotlin/Main.kt
index e60a5fdd8e64185efb71856eb2f23ac2aefe79e7..be10abf2e4c145f7be516c12522010abb6d1af10 100644
--- a/mosogepsch/src/jsMain/kotlin/Main.kt
+++ b/mosogepsch/src/jsMain/kotlin/Main.kt
@@ -1,30 +1,27 @@
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
+import androidx.compose.runtime.*
 import app.softwork.bootstrapcompose.*
 import app.softwork.bootstrapcompose.Color
-import components.CardStyle
-import components.content
-import components.credits
-import components.switch
+import components.*
 import kotlinx.browser.localStorage
 import kotlinx.browser.window
 import org.jetbrains.compose.web.css.*
 import org.jetbrains.compose.web.dom.*
 import org.jetbrains.compose.web.renderComposable
+import org.w3c.dom.HTMLDivElement
 import org.w3c.dom.get
 import org.w3c.dom.set
 import styles.LocalStyle
 import styles.Style
 
-//@JsModule("@js-joda/timezone")
-//@JsNonModule
-//external object JsJodaTimeZoneModule
-
-//private val jsJodaTz = JsJodaTimeZoneModule
+@JsModule("@js-joda/timezone")
+@JsNonModule
+external object JsJodaTimeZoneModule
+private val jsJodaTz: dynamic = JsJodaTimeZoneModule
 
 fun main() {
+    val alma: dynamic = window
+    alma.alma = jsJodaTz
+
     val dark = localStorage["darkMode"]?.equals("true")
         ?: window.matchMedia("(prefers-color-scheme: dark)").matches
 
@@ -33,14 +30,22 @@ fun main() {
         val mosogepStyle = Style(darkTheme)
         Style(mosogepStyle)
         Style(CardStyle)
+        Style(FloorStyle)
         CompositionLocalProvider(LocalStyle provides mosogepStyle) {
             Header {
                 Navbar(
-                    attrs = { classes("bg-secondary") },
+                    attrs = {
+                        style {
+                            backgroundColor(mosogepStyle.colors.appBarColor)
+                        }
+                    },
                     placement = NavbarPlacement.StickyTop,
                     collapseBehavior = NavbarCollapseBehavior.AtBreakpoint(Breakpoint.Large),
                     colorScheme = Color.Dark,
                 ) {
+                    DomSideEffect {
+                        it.setImportantBg(mosogepStyle.colors.appBarColor)
+                    }
                     Brand { Text("MosógépSCH") }
                     switch(
                         label = "Sötét téma",
@@ -56,7 +61,7 @@ fun main() {
                 content()
             }
             Footer(
-                attrs = { classes("footer", "mt-auto") }
+                attrs = { classes("footer", "mt-auto", mosogepStyle.footer) }
             ) {
                 Container { credits() }
             }
@@ -64,3 +69,8 @@ fun main() {
     }
 }
 
+@NoLiveLiterals
+private fun HTMLDivElement.setImportantBg(color: CSSColorValue) {
+    val alma: dynamic = parentElement
+    alma.style.setProperty("background-color", color.toString(), "important")
+}
\ No newline at end of file
diff --git a/mosogepsch/src/jsMain/kotlin/api/Api.kt b/mosogepsch/src/jsMain/kotlin/api/Api.kt
index 2f4d59ccae67175ef0c47f3581094ff03e397321..72ecb6bf62d5d48ae8fcb954aa909873f07603a1 100644
--- a/mosogepsch/src/jsMain/kotlin/api/Api.kt
+++ b/mosogepsch/src/jsMain/kotlin/api/Api.kt
@@ -5,9 +5,14 @@ import kotlinx.serialization.decodeFromString
 import kotlinx.serialization.json.Json
 
 
-@OptIn(ExperimentalSerializationApi::class)
-fun Api(): Response {
-    val jsonStr = """        
+object Api {
+    private val json = Json {
+        ignoreUnknownKeys = true
+    }
+
+    @OptIn(ExperimentalSerializationApi::class)
+    fun getOnce(): Response {
+        val jsonStr = """        
 {
   "floors": [
     {
@@ -184,5 +189,10 @@ fun Api(): Response {
   ]
 }
     """.trimIndent()
-    return Json.decodeFromString(jsonStr)
+        val dec = json.decodeFromString<Response>(jsonStr)
+        val floors = dec.floors.map { floor ->
+            floor.copy(machines = floor.machines.sortedBy { it.kindOf })
+        }.sortedBy { it.id }
+        return dec.copy(floors = floors)
+    }
 }
\ No newline at end of file
diff --git a/mosogepsch/src/jsMain/kotlin/api/Types.kt b/mosogepsch/src/jsMain/kotlin/api/Types.kt
index e1617a2086ad14a38c5a714fa1e71af9f6ecb18e..5fe877e25852d21725b05f3777e73745dfb29a5f 100644
--- a/mosogepsch/src/jsMain/kotlin/api/Types.kt
+++ b/mosogepsch/src/jsMain/kotlin/api/Types.kt
@@ -1,7 +1,14 @@
 package api
 
 import kotlinx.datetime.Instant
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.SerialName
 import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
 
 @Serializable
 data class Response(
@@ -18,12 +25,22 @@ data class Floor(
 data class Machine(
     val id: Int,
     val kindOf: MachineKind,
-    val status: MachineStatus,
-    val lastQueryTime: Instant,
-    val unixTimeStamp: Int,
+    var status: MachineStatus,
+
+    @SerialName("unixTimeStamp")
+    @Serializable(with = UnixDateSerializer::class)
+    var lastQueryTime: Instant,
 )
 
 @Serializable
 enum class MachineKind { Dryer, Washer }
 @Serializable
-enum class MachineStatus { NotAvailable, Available }
\ No newline at end of file
+enum class MachineStatus { NotAvailable, Available }
+
+object UnixDateSerializer : KSerializer<Instant> {
+    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Instant", PrimitiveKind.LONG)
+
+    override fun serialize(encoder: Encoder, value: Instant) = encoder.encodeLong(value.epochSeconds)
+
+    override fun deserialize(decoder: Decoder): Instant = Instant.fromEpochSeconds(decoder.decodeLong())
+}
\ No newline at end of file
diff --git a/mosogepsch/src/jsMain/kotlin/components/Card.kt b/mosogepsch/src/jsMain/kotlin/components/Card.kt
index f768d773f4a270d25bd1b235ae33da0206a23f96..0bd53f1ba068e654265c89b47c99bfd71e4a8b25 100644
--- a/mosogepsch/src/jsMain/kotlin/components/Card.kt
+++ b/mosogepsch/src/jsMain/kotlin/components/Card.kt
@@ -1,8 +1,6 @@
 package components
 
 import androidx.compose.runtime.Composable
-import kotlinx.browser.document
-import org.jetbrains.compose.web.attributes.AttrsBuilder
 import org.jetbrains.compose.web.css.*
 import org.jetbrains.compose.web.dom.AttrBuilderContext
 import org.jetbrains.compose.web.dom.Div
diff --git a/mosogepsch/src/jsMain/kotlin/components/Content.kt b/mosogepsch/src/jsMain/kotlin/components/Content.kt
index f36d380b3dbc0ea0654db0754be237ab6565125d..cb91f97dc74f6991a85c676b4b6506cc6ca9576b 100644
--- a/mosogepsch/src/jsMain/kotlin/components/Content.kt
+++ b/mosogepsch/src/jsMain/kotlin/components/Content.kt
@@ -1,21 +1,25 @@
 package components
 
-import androidx.compose.runtime.Composable
+import androidx.compose.runtime.*
+import api.Api
 import app.softwork.bootstrapcompose.Container
 import org.jetbrains.compose.web.css.*
 
 @Composable
 fun content() {
+    val data by remember { mutableStateOf(Api.getOnce()) }
+
     Container(attrs = {
         style {
             display(DisplayStyle.Flex)
             flexDirection(FlexDirection.Row)
             flexWrap(FlexWrap.Wrap)
             justifyContent(JustifyContent.Center)
+            paddingTop(1.em)
         }
     }) {
-        repeat(50) {
-            mosogep(it)
+        data.floors.forEach {
+            floor(it)
         }
     }
 }
\ No newline at end of file
diff --git a/mosogepsch/src/jsMain/kotlin/components/Floor.kt b/mosogepsch/src/jsMain/kotlin/components/Floor.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2afb63a5ca63ed98930aaf5ec4b0eeb1b7f24108
--- /dev/null
+++ b/mosogepsch/src/jsMain/kotlin/components/Floor.kt
@@ -0,0 +1,145 @@
+package components
+
+import styles.LocalStyle
+import androidx.compose.runtime.*
+import api.Floor
+import api.Machine
+import api.MachineKind
+import api.MachineStatus
+import org.jetbrains.compose.web.css.*
+import org.jetbrains.compose.web.dom.*
+
+object FloorStyle: StyleSheet() {
+    val container by style {
+        display(DisplayStyle.Flex)
+        flexDirection(FlexDirection.Column)
+        justifyContent(JustifyContent.SpaceAround)
+        alignItems(AlignItems.Center)
+        position(Position.Relative)
+    }
+
+    val card by style {
+        maxWidth(20.em)
+        width(20.em)
+        flexDirection(FlexDirection.Row)
+        justifyContent(JustifyContent.SpaceAround)
+    }
+
+    val floorNum by style {
+        minWidth(2.75.ch)
+        textAlign("right")
+    }
+
+    val machine by style {
+        flexGrow(1)
+    }
+
+    val absCnt by style {
+        position(Position.Absolute)
+        left(0.px)
+        bottom(4.em)
+        width(0.px)
+        height(0.px)
+        property("z-index", -1)
+    }
+    val relCnt by style {
+        position(Position.Relative)
+        width(0.px)
+        height(0.px)
+    }
+    val underflowCnt by style {
+        margin(0.px)
+        padding(0.px)
+        marginLeft(1.em)
+        width(20.em)
+        property("transition", "max-height 0.75s")
+        overflow("hidden")
+    }
+    val underflowCard by style {
+        flexDirection(FlexDirection.Column)
+        margin(0.px)
+        width(100.percent)
+        paddingTop(5.em)
+    }
+}
+
+@Composable
+fun floor(floor: Floor) {
+    val colors = LocalStyle.current.colors
+    fun MachineStatus.toColor(): CSSColorValue = when (this) {
+        MachineStatus.Available -> colors.offColor
+        MachineStatus.NotAvailable -> colors.onColor
+    }
+    fun MachineKind.toIcon(): String { return "${this.name[0]}" }
+
+    val zIndex = 200 - floor.id*2
+
+    Div(attrs = {
+        classes(FloorStyle.container)
+        style {
+            property("z-index", zIndex)
+        }
+    }) {
+        var selectedMachine by remember { mutableStateOf<Machine>(floor.machines[0]) }
+        var machineSelected by remember { mutableStateOf(false) }
+
+        card(attrs = {
+            classes(FloorStyle.card)
+            style {
+                backgroundColor(colors.cardBg)
+            }
+        }) {
+            H3(attrs = {
+                classes(FloorStyle.floorNum)
+            }) { Text("${floor.id}.") }
+            floor.machines.forEach { machine ->
+                card(attrs = {
+                    classes(FloorStyle.machine)
+                    style {
+                        backgroundColor(machine.status.toColor())
+                    }
+                    onClick {
+                        if (selectedMachine == machine) {
+                            machineSelected = !machineSelected
+                        } else {
+                            machineSelected = true
+                        }
+                        selectedMachine = machine
+                    }
+                }) { H3 { Text(machine.kindOf.toIcon()) } }
+            }
+        }
+
+        floor.machines.forEach {
+            Div(attrs = {
+                classes(FloorStyle.absCnt)
+            }) {
+                Div(attrs = {
+                    classes(FloorStyle.relCnt)
+                }) {
+                    Div(attrs = {
+                        classes(FloorStyle.underflowCnt)
+                        style {
+                            if (machineSelected && selectedMachine == it) {
+                                maxHeight(20.em)
+                            } else {
+                                maxHeight(0.px)
+                            }
+                        }
+                    }) {
+                        card(attrs = {
+                            classes(FloorStyle.underflowCard)
+                            style {
+                                backgroundColor(it.status.toColor())
+                            }
+                        }) {
+                            P { Text(it.status.name) }
+                        }
+                    }
+                }
+            }
+        }
+
+    }
+}
+
diff --git a/mosogepsch/src/jsMain/kotlin/components/Mosogep.kt b/mosogepsch/src/jsMain/kotlin/components/Mosogep.kt
deleted file mode 100644
index 5d1e8ab208a32cbd1301a55acac3390c0bcaec95..0000000000000000000000000000000000000000
--- a/mosogepsch/src/jsMain/kotlin/components/Mosogep.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package components
-
-import styles.LocalStyle
-import androidx.compose.runtime.Composable
-import app.softwork.bootstrapcompose.Card
-import org.jetbrains.compose.web.css.*
-import org.jetbrains.compose.web.dom.*
-
-@Composable
-fun mosogep(floor: Int) {
-    card(attrs = {
-        style {
-            maxWidth(20.em)
-            width(20.em)
-            flexDirection(FlexDirection.Row)
-            justifyContent(JustifyContent.SpaceAround)
-        }
-    }) {
-        H3(attrs = {
-            style {
-                minWidth(2.75.ch)
-                textAlign("right")
-            }
-        }) { Text("$floor.") }
-        card(attrs = {
-            style {
-                backgroundColor(Color("#ff8a65cc"))
-                flexGrow(1)
-            }
-        }) { H3 { Text("M") } }
-        card(attrs = {
-            style {
-                backgroundColor(Color("#aed581cc"))
-                flexGrow(1)
-            }
-        }) { H3 { Text("Sz") } }
-    }
-}
\ No newline at end of file
diff --git a/mosogepsch/src/jsMain/kotlin/styles/Style.kt b/mosogepsch/src/jsMain/kotlin/styles/Style.kt
index 26c6a4a2a7e3aa9ee81211193f00f2b71535b8c7..bf32c50bafdf6ba8bdfedcdc5392117a9405a831 100644
--- a/mosogepsch/src/jsMain/kotlin/styles/Style.kt
+++ b/mosogepsch/src/jsMain/kotlin/styles/Style.kt
@@ -1,11 +1,27 @@
+@file:Suppress("NonAsciiCharacters")
 package styles
 
 import androidx.compose.runtime.compositionLocalOf
 import org.jetbrains.compose.web.css.*
 
+
+
+private val kszkék = Color("#3051bf")
+private val vilagosKszkék = Color("#3faef7")
+
+
+class Colors(val dark: Boolean) {
+    val appBarColor = kszkék
+    val cardBg = if (dark) kszkék else vilagosKszkék
+    val onColor = Color(if (dark) "#bd5b40" else "#DB6748")
+    val offColor = Color(if (dark) "#57af00" else "#94DB40")
+}
+
 class Style(val dark: Boolean = false): StyleSheet() {
     private val footHeight = 4.em
 
+    val colors = Colors(dark)
+
     init {
         "html, body, #root" style {
             position(Position.Relative)
@@ -16,12 +32,9 @@ class Style(val dark: Boolean = false): StyleSheet() {
             marginBottom(0.px)
         }
         ".footer" style {
-            position(Position.Absolute)
-            bottom(0.px)
-            width(100.percent)
-            height(footHeight)
-            lineHeight(footHeight)
-            backgroundColor(Color("#0000007f"))
+        }
+        "*" {
+            property("transition", "background-color 0.75s")
         }
     }
 
@@ -30,6 +43,15 @@ class Style(val dark: Boolean = false): StyleSheet() {
         height(100.percent)
         paddingBottom(footHeight * 2)
     }
+    val footer by style {
+        position(Position.Absolute)
+        bottom(0.px)
+        width(100.percent)
+        height(footHeight)
+        lineHeight(footHeight)
+        backgroundColor(Color("#0000007f"))
+        property("z-index", 2000)
+    }
 }
 
 val LocalStyle = compositionLocalOf { Style() }
\ No newline at end of file