all repos

onasty @ 336ceb2

a one-time notes service
7 files changed, 315 insertions(+), 122 deletions(-)
web: switch to tailwind (#141)

* setup tailwind

* refactor(web): rewrite header to use tailwind

* refactor(web/header): move duplicating html classes into helper function

* refactor(web): fix semantics of header

* refactor(web): review auth page to use tailwind

* refactor(web/auth): refactor the banners

* web: make linter happy

* fix: center a div

* fixup! fix: center a div

* fix: dont submit page when i want to reset password
Author: Smirnov Oleksandr ss2316544@gmail.com
Committed by: GitHub noreply@github.com
Committed at: 2025-06-21 18:32:16 +0300
Parent: f36f71a
M web/.postcssrc.json
···
        1
        1
         {

      
        2
        2
           "plugins": {

      
        3
        
        -    "postcss-import": {},

      
        4
        
        -    "autoprefixer": {}

      
        
        3
        +    "@tailwindcss/postcss": {}

      
        5
        4
           }

      
        6
        5
         }

      
M web/bun.lock
···
        4
        4
             "": {

      
        5
        5
               "name": "web",

      
        6
        6
               "devDependencies": {

      
        7
        
        -        "autoprefixer": "^10.4.21",

      
        
        7
        +        "@tailwindcss/postcss": "^4.1.10",

      
        8
        8
                 "elm-land": "^0.20.1",

      
        9
        9
                 "elm-review": "^2.13.2",

      
        10
        10
                 "elm-tooling": "^1.15.1",

      
        11
        
        -        "missing.css": "^1.1.3",

      
        12
        11
                 "postcss": "^8.5.6",

      
        13
        12
                 "postcss-import": "^16.1.1",

      
        
        13
        +        "tailwindcss": "^4.1.10",

      
        14
        14
               },

      
        15
        15
             },

      
        16
        16
           },

      
        17
        17
           "packages": {

      
        
        18
        +    "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],

      
        
        19
        +

      
        
        20
        +    "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],

      
        
        21
        +

      
        18
        22
             "@elm_binaries/darwin_arm64": ["@elm_binaries/darwin_arm64@0.19.1-0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mjbsH7BNHEAmoE2SCJFcfk5fIHwFIpxtSgnEAqMsVLpBUFoEtAeX+LQ+N0vSFJB3WAh73+QYx/xSluxxLcL6dA=="],

      
        19
        23
         

      
        20
        24
             "@elm_binaries/darwin_x64": ["@elm_binaries/darwin_x64@0.19.1-0", "", { "os": "darwin", "cpu": "x64" }, "sha512-QGUtrZTPBzaxgi9al6nr+9313wrnUVHuijzUK39UsPS+pa+n6CmWyV/69sHZeX9qy6UfeugE0PzF3qcUiy2GDQ=="],

      ···
        69
        73
         

      
        70
        74
             "@esbuild/win32-x64": ["@esbuild/win32-x64@0.20.2", "", { "os": "win32", "cpu": "x64" }, "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ=="],

      
        71
        75
         

      
        
        76
        +    "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],

      
        
        77
        +

      
        72
        78
             "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="],

      
        73
        79
         

      
        74
        80
             "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],

      ···
        139
        145
         

      
        140
        146
             "@szmarczak/http-timer": ["@szmarczak/http-timer@4.0.6", "", { "dependencies": { "defer-to-connect": "^2.0.0" } }, "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w=="],

      
        141
        147
         

      
        
        148
        +    "@tailwindcss/node": ["@tailwindcss/node@4.1.10", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.10" } }, "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ=="],

      
        
        149
        +

      
        
        150
        +    "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.10", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.10", "@tailwindcss/oxide-darwin-arm64": "4.1.10", "@tailwindcss/oxide-darwin-x64": "4.1.10", "@tailwindcss/oxide-freebsd-x64": "4.1.10", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.10", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.10", "@tailwindcss/oxide-linux-arm64-musl": "4.1.10", "@tailwindcss/oxide-linux-x64-gnu": "4.1.10", "@tailwindcss/oxide-linux-x64-musl": "4.1.10", "@tailwindcss/oxide-wasm32-wasi": "4.1.10", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.10", "@tailwindcss/oxide-win32-x64-msvc": "4.1.10" } }, "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q=="],

      
        
        151
        +

      
        
        152
        +    "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.10", "", { "os": "android", "cpu": "arm64" }, "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ=="],

      
        
        153
        +

      
        
        154
        +    "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ=="],

      
        
        155
        +

      
        
        156
        +    "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ=="],

      
        
        157
        +

      
        
        158
        +    "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.10", "", { "os": "freebsd", "cpu": "x64" }, "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g=="],

      
        
        159
        +

      
        
        160
        +    "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.10", "", { "os": "linux", "cpu": "arm" }, "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ=="],

      
        
        161
        +

      
        
        162
        +    "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA=="],

      
        
        163
        +

      
        
        164
        +    "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ=="],

      
        
        165
        +

      
        
        166
        +    "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.10", "", { "os": "linux", "cpu": "x64" }, "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA=="],

      
        
        167
        +

      
        
        168
        +    "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.10", "", { "os": "linux", "cpu": "x64" }, "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA=="],

      
        
        169
        +

      
        
        170
        +    "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.10", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", "@napi-rs/wasm-runtime": "^0.2.10", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q=="],

      
        
        171
        +

      
        
        172
        +    "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA=="],

      
        
        173
        +

      
        
        174
        +    "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.10", "", { "os": "win32", "cpu": "x64" }, "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA=="],

      
        
        175
        +

      
        
        176
        +    "@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.10", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.10", "@tailwindcss/oxide": "4.1.10", "postcss": "^8.4.41", "tailwindcss": "4.1.10" } }, "sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ=="],

      
        
        177
        +

      
        142
        178
             "@types/cacheable-request": ["@types/cacheable-request@6.0.3", "", { "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", "@types/node": "*", "@types/responselike": "^1.0.0" } }, "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw=="],

      
        143
        179
         

      
        144
        180
             "@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="],

      ···
        161
        197
         

      
        162
        198
             "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],

      
        163
        199
         

      
        164
        
        -    "autoprefixer": ["autoprefixer@10.4.21", "", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="],

      
        165
        
        -

      
        166
        200
             "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],

      
        167
        201
         

      
        168
        202
             "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],

      ···
        175
        209
         

      
        176
        210
             "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],

      
        177
        211
         

      
        178
        
        -    "browserslist": ["browserslist@4.25.0", "", { "dependencies": { "caniuse-lite": "^1.0.30001718", "electron-to-chromium": "^1.5.160", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA=="],

      
        179
        
        -

      
        180
        212
             "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],

      
        181
        213
         

      
        182
        214
             "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],

      ···
        185
        217
         

      
        186
        218
             "cacheable-request": ["cacheable-request@7.0.4", "", { "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", "normalize-url": "^6.0.1", "responselike": "^2.0.0" } }, "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg=="],

      
        187
        219
         

      
        188
        
        -    "caniuse-lite": ["caniuse-lite@1.0.30001723", "", {}, "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw=="],

      
        189
        
        -

      
        190
        220
             "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],

      
        191
        221
         

      
        192
        222
             "chokidar": ["chokidar@3.5.3", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw=="],

      
        
        223
        +

      
        
        224
        +    "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],

      
        193
        225
         

      
        194
        226
             "cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],

      
        195
        227
         

      ···
        217
        249
         

      
        218
        250
             "defer-to-connect": ["defer-to-connect@2.0.1", "", {}, "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="],

      
        219
        251
         

      
        220
        
        -    "electron-to-chromium": ["electron-to-chromium@1.5.170", "", {}, "sha512-GP+M7aeluQo9uAyiTCxgIj/j+PrWhMlY7LFVj8prlsPljd0Fdg9AprlfUi+OCSFWy9Y5/2D/Jrj9HS8Z4rpKWA=="],

      
        
        252
        +    "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],

      
        221
        253
         

      
        222
        254
             "elm": ["elm@0.19.1-6", "", { "optionalDependencies": { "@elm_binaries/darwin_arm64": "0.19.1-0", "@elm_binaries/darwin_x64": "0.19.1-0", "@elm_binaries/linux_x64": "0.19.1-0", "@elm_binaries/win32_x64": "0.19.1-0" }, "bin": { "elm": "bin/elm" } }, "sha512-mKYyierHICPdMx/vhiIacdPmTPnh889gjHOZ75ZAoCxo3lZmSWbGP8HMw78wyctJH0HwvTmeKhlYSWboQNYPeQ=="],

      
        223
        255
         

      ···
        233
        265
         

      
        234
        266
             "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],

      
        235
        267
         

      
        236
        
        -    "esbuild": ["esbuild@0.20.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.20.2", "@esbuild/android-arm": "0.20.2", "@esbuild/android-arm64": "0.20.2", "@esbuild/android-x64": "0.20.2", "@esbuild/darwin-arm64": "0.20.2", "@esbuild/darwin-x64": "0.20.2", "@esbuild/freebsd-arm64": "0.20.2", "@esbuild/freebsd-x64": "0.20.2", "@esbuild/linux-arm": "0.20.2", "@esbuild/linux-arm64": "0.20.2", "@esbuild/linux-ia32": "0.20.2", "@esbuild/linux-loong64": "0.20.2", "@esbuild/linux-mips64el": "0.20.2", "@esbuild/linux-ppc64": "0.20.2", "@esbuild/linux-riscv64": "0.20.2", "@esbuild/linux-s390x": "0.20.2", "@esbuild/linux-x64": "0.20.2", "@esbuild/netbsd-x64": "0.20.2", "@esbuild/openbsd-x64": "0.20.2", "@esbuild/sunos-x64": "0.20.2", "@esbuild/win32-arm64": "0.20.2", "@esbuild/win32-ia32": "0.20.2", "@esbuild/win32-x64": "0.20.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g=="],

      
        
        268
        +    "enhanced-resolve": ["enhanced-resolve@5.18.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg=="],

      
        237
        269
         

      
        238
        
        -    "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],

      
        
        270
        +    "esbuild": ["esbuild@0.20.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.20.2", "@esbuild/android-arm": "0.20.2", "@esbuild/android-arm64": "0.20.2", "@esbuild/android-x64": "0.20.2", "@esbuild/darwin-arm64": "0.20.2", "@esbuild/darwin-x64": "0.20.2", "@esbuild/freebsd-arm64": "0.20.2", "@esbuild/freebsd-x64": "0.20.2", "@esbuild/linux-arm": "0.20.2", "@esbuild/linux-arm64": "0.20.2", "@esbuild/linux-ia32": "0.20.2", "@esbuild/linux-loong64": "0.20.2", "@esbuild/linux-mips64el": "0.20.2", "@esbuild/linux-ppc64": "0.20.2", "@esbuild/linux-riscv64": "0.20.2", "@esbuild/linux-s390x": "0.20.2", "@esbuild/linux-x64": "0.20.2", "@esbuild/netbsd-x64": "0.20.2", "@esbuild/openbsd-x64": "0.20.2", "@esbuild/sunos-x64": "0.20.2", "@esbuild/win32-arm64": "0.20.2", "@esbuild/win32-ia32": "0.20.2", "@esbuild/win32-x64": "0.20.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g=="],

      
        239
        271
         

      
        240
        272
             "fastest-levenshtein": ["fastest-levenshtein@1.0.16", "", {}, "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="],

      
        241
        273
         

      ···
        246
        278
             "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],

      
        247
        279
         

      
        248
        280
             "folder-hash": ["folder-hash@3.3.3", "", { "dependencies": { "debug": "^4.1.1", "graceful-fs": "~4.2.0", "minimatch": "~3.0.4" }, "bin": { "folder-hash": "bin/folder-hash" } }, "sha512-SDgHBgV+RCjrYs8aUwCb9rTgbTVuSdzvFmLaChsLre1yf+D64khCW++VYciaByZ8Rm0uKF8R/XEpXuTRSGUM1A=="],

      
        249
        
        -

      
        250
        
        -    "fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="],

      
        251
        281
         

      
        252
        282
             "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],

      
        253
        283
         

      ···
        291
        321
         

      
        292
        322
             "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],

      
        293
        323
         

      
        
        324
        +    "jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],

      
        
        325
        +

      
        294
        326
             "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],

      
        295
        327
         

      
        296
        328
             "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],

      ···
        299
        331
         

      
        300
        332
             "launch-editor": ["launch-editor@2.6.1", "", { "dependencies": { "picocolors": "^1.0.0", "shell-quote": "^1.8.1" } }, "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw=="],

      
        301
        333
         

      
        
        334
        +    "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],

      
        
        335
        +

      
        
        336
        +    "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],

      
        
        337
        +

      
        
        338
        +    "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],

      
        
        339
        +

      
        
        340
        +    "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],

      
        
        341
        +

      
        
        342
        +    "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],

      
        
        343
        +

      
        
        344
        +    "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],

      
        
        345
        +

      
        
        346
        +    "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],

      
        
        347
        +

      
        
        348
        +    "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],

      
        
        349
        +

      
        
        350
        +    "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],

      
        
        351
        +

      
        
        352
        +    "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],

      
        
        353
        +

      
        
        354
        +    "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],

      
        
        355
        +

      
        302
        356
             "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],

      
        303
        357
         

      
        304
        358
             "log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],

      
        305
        359
         

      
        306
        360
             "lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="],

      
        307
        361
         

      
        
        362
        +    "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],

      
        
        363
        +

      
        308
        364
             "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],

      
        309
        365
         

      
        310
        366
             "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],

      ···
        313
        369
         

      
        314
        370
             "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],

      
        315
        371
         

      
        316
        
        -    "missing.css": ["missing.css@1.1.3", "", {}, "sha512-dkGzliE9Zcv9tGPvuIHy1lpMc4Y5QAc+svF7Nqi+EMl4taRC5HfjARg55YC2jC9cbqOwX0qOUltUxqn57YIQiw=="],

      
        
        372
        +    "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],

      
        
        373
        +

      
        
        374
        +    "minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="],

      
        
        375
        +

      
        
        376
        +    "mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="],

      
        317
        377
         

      
        318
        378
             "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],

      
        319
        379
         

      
        320
        380
             "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],

      
        321
        381
         

      
        322
        
        -    "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="],

      
        323
        
        -

      
        324
        382
             "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],

      
        325
        
        -

      
        326
        
        -    "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="],

      
        327
        383
         

      
        328
        384
             "normalize-url": ["normalize-url@6.1.0", "", {}, "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="],

      
        329
        385
         

      ···
        409
        465
         

      
        410
        466
             "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],

      
        411
        467
         

      
        
        468
        +    "tailwindcss": ["tailwindcss@4.1.10", "", {}, "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA=="],

      
        
        469
        +

      
        
        470
        +    "tapable": ["tapable@2.2.2", "", {}, "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="],

      
        
        471
        +

      
        
        472
        +    "tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="],

      
        
        473
        +

      
        412
        474
             "terminal-link": ["terminal-link@2.1.1", "", { "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" } }, "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ=="],

      
        413
        475
         

      
        414
        476
             "terser": ["terser@5.15.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw=="],

      ···
        425
        487
         

      
        426
        488
             "undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],

      
        427
        489
         

      
        428
        
        -    "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],

      
        429
        
        -

      
        430
        490
             "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],

      
        431
        491
         

      
        432
        492
             "vite": ["vite@5.2.8", "", { "dependencies": { "esbuild": "^0.20.1", "postcss": "^8.4.38", "rollup": "^4.13.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA=="],

      ···
        441
        501
         

      
        442
        502
             "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],

      
        443
        503
         

      
        
        504
        +    "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],

      
        
        505
        +

      
        444
        506
             "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],

      
        
        507
        +

      
        
        508
        +    "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.4.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g=="],

      
        
        509
        +

      
        
        510
        +    "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="],

      
        
        511
        +

      
        
        512
        +    "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA=="],

      
        
        513
        +

      
        
        514
        +    "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.11", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.9.0" }, "bundled": true }, "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA=="],

      
        
        515
        +

      
        
        516
        +    "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="],

      
        
        517
        +

      
        
        518
        +    "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],

      
        445
        519
         

      
        446
        520
             "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],

      
        447
        521
         

      
M web/package.json
···
        4
        4
             "postinstall": "elm-tooling install"

      
        5
        5
           },

      
        6
        6
           "devDependencies": {

      
        7
        
        -    "autoprefixer": "^10.4.21",

      
        
        7
        +    "@tailwindcss/postcss": "^4.1.10",

      
        8
        8
             "elm-land": "^0.20.1",

      
        9
        9
             "elm-review": "^2.13.2",

      
        10
        10
             "elm-tooling": "^1.15.1",

      
        11
        
        -    "missing.css": "^1.1.3",

      
        12
        11
             "postcss": "^8.5.6",

      
        13
        
        -    "postcss-import": "^16.1.1"

      
        
        12
        +    "postcss-import": "^16.1.1",

      
        
        13
        +    "tailwindcss": "^4.1.10"

      
        14
        14
           }

      
        15
        15
         }

      
M web/src/Layouts/Header.elm
···
        2
        2
         

      
        3
        3
         import Auth.User

      
        4
        4
         import Effect exposing (Effect)

      
        5
        
        -import Html exposing (Html)

      
        6
        
        -import Html.Attributes as Attr

      
        7
        
        -import Html.Events

      
        
        5
        +import Html as H exposing (Html)

      
        
        6
        +import Html.Attributes as A

      
        
        7
        +import Html.Events as E

      
        8
        8
         import Layout exposing (Layout)

      
        9
        9
         import Route exposing (Route)

      
        10
        10
         import Route.Path

      ···
        67
        67
         view shared { toContentMsg, content } =

      
        68
        68
             { title = content.title

      
        69
        69
             , body =

      
        70
        
        -        [ viewNavbar shared |> Html.map toContentMsg

      
        71
        
        -        , Html.main_ [] content.body

      
        
        70
        +        [ viewHeader shared.user |> H.map toContentMsg

      
        
        71
        +        , H.main_ [] content.body

      
        72
        72
                 ]

      
        73
        73
             }

      
        74
        74
         

      
        75
        75
         

      
        76
        
        -viewNavbar : Shared.Model -> Html Msg

      
        77
        
        -viewNavbar shared =

      
        78
        
        -    Html.header [ Attr.class "navbar" ]

      
        79
        
        -        [ Html.nav [ Attr.class "f-row justify-content:space-between" ]

      
        80
        
        -            [ Html.ul [ Attr.attribute "role" "list" ]

      
        81
        
        -                [ Html.li [] [ viewNavLink ( "home", Route.Path.Home_ ) ] ]

      
        82
        
        -            , Html.ul [ Attr.attribute "role" "list" ]

      
        83
        
        -                (case shared.user of

      
        84
        
        -                    Auth.User.SignedIn _ ->

      
        85
        
        -                        [ Html.li [] [ viewNavLink ( "profile", Route.Path.Profile_Me ) ]

      
        86
        
        -                        , Html.li [] [ Html.a [ Html.Events.onClick UserClickedLogout ] [ Html.text "logout" ] ]

      
        
        76
        +viewHeader : Auth.User.SignInStatus -> Html Msg

      
        
        77
        +viewHeader user =

      
        
        78
        +    H.header [ A.class "w-full border-b border-gray-200 bg-white" ]

      
        
        79
        +        [ H.div [ A.class "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" ]

      
        
        80
        +            [ H.div [ A.class "flex justify-between items-center h-16" ]

      
        
        81
        +                [ H.div [ A.class "flex items-center" ]

      
        
        82
        +                    [ H.a

      
        
        83
        +                        [ A.class "text-lg font-semibold text-black hover:text-gray-700 transition-colors"

      
        
        84
        +                        , Route.Path.href Route.Path.Home_

      
        87
        85
                                 ]

      
        
        86
        +                        [ H.text "Onasty" ]

      
        
        87
        +                    ]

      
        
        88
        +                , H.nav [ A.class "flex items-center space-x-6" ] (viewNav user)

      
        
        89
        +                ]

      
        
        90
        +            ]

      
        
        91
        +        ]

      
        
        92
        +

      
        
        93
        +

      
        
        94
        +viewNav : Auth.User.SignInStatus -> List (Html Msg)

      
        
        95
        +viewNav user =

      
        
        96
        +    case user of

      
        
        97
        +        Auth.User.SignedIn _ ->

      
        
        98
        +            viewSignedInNav

      
        88
        99
         

      
        89
        
        -                    Auth.User.NotSignedIn ->

      
        90
        
        -                        viewNotSignedInNav

      
        
        100
        +        Auth.User.NotSignedIn ->

      
        
        101
        +            viewNotSignedInNav

      
        
        102
        +

      
        
        103
        +        Auth.User.RefreshingTokens ->

      
        
        104
        +            viewNotSignedInNav

      
        
        105
        +

      
        91
        106
         

      
        92
        
        -                    Auth.User.RefreshingTokens ->

      
        93
        
        -                        viewNotSignedInNav

      
        94
        
        -                )

      
        95
        
        -            ]

      
        
        107
        +viewSignedInNav : List (Html Msg)

      
        
        108
        +viewSignedInNav =

      
        
        109
        +    [ viewLink "Profile" Route.Path.Profile_Me

      
        
        110
        +    , H.button

      
        
        111
        +        [ A.class "text-gray-600 hover:text-red-600 transition-colors"

      
        
        112
        +        , E.onClick UserClickedLogout

      
        96
        113
                 ]

      
        
        114
        +        [ H.text "Logout" ]

      
        
        115
        +    ]

      
        97
        116
         

      
        98
        117
         

      
        99
        
        -viewNotSignedInNav : List (Html msg)

      
        
        118
        +viewNotSignedInNav : List (Html Msg)

      
        100
        119
         viewNotSignedInNav =

      
        101
        
        -    [ Html.li [] [ viewNavLink ( "sign in", Route.Path.Auth ) ]

      
        
        120
        +    -- TODO: or add about page, or delete the link

      
        
        121
        +    [ viewLink "About" Route.Path.Home_

      
        
        122
        +    , H.a

      
        
        123
        +        [ A.class "px-4 py-2 border border-gray-300 rounded-md text-black hover:bg-gray-50 transition-colors"

      
        
        124
        +        , Route.Path.href Route.Path.Auth

      
        
        125
        +        ]

      
        
        126
        +        [ H.text "Sign In/Up" ]

      
        102
        127
             ]

      
        103
        128
         

      
        104
        129
         

      
        105
        
        -viewNavLink : ( String, Route.Path.Path ) -> Html msg

      
        106
        
        -viewNavLink ( label, path ) =

      
        107
        
        -    Html.a

      
        108
        
        -        [ Route.Path.href path ]

      
        109
        
        -        [ Html.text label ]

      
        
        130
        +viewLink : String -> Route.Path.Path -> Html Msg

      
        
        131
        +viewLink text path =

      
        
        132
        +    H.a

      
        
        133
        +        [ A.class "text-gray-600 hover:text-black transition-colors"

      
        
        134
        +        , Route.Path.href path

      
        
        135
        +        ]

      
        
        136
        +        [ H.text text ]

      
M web/src/Pages/Auth.elm
···
        5
        5
         import Auth.User

      
        6
        6
         import Data.Credentials exposing (Credentials)

      
        7
        7
         import Effect exposing (Effect)

      
        8
        
        -import Html exposing (Html)

      
        9
        
        -import Html.Attributes as Attr

      
        10
        
        -import Html.Events

      
        
        8
        +import Html as H exposing (Html)

      
        
        9
        +import Html.Attributes as A

      
        
        10
        +import Html.Events as E

      
        11
        11
         import Layouts

      
        12
        12
         import Page exposing (Page)

      
        13
        13
         import Route exposing (Route)

      ···
        164
        164
         view model =

      
        165
        165
             { title = "Authentication"

      
        166
        166
             , body =

      
        167
        
        -        [ Html.div [ Attr.class "center" ]

      
        168
        
        -            -- TODO: add oauth buttons

      
        169
        
        -            [ viewBanner model.apiError model.gotSignedUp

      
        170
        
        -            , viewChangeVariant model.formVariant

      
        171
        
        -            , viewForm model

      
        172
        
        -            , viewForgotPassword

      
        
        167
        +        [ H.div [ A.class "min-h-screen flex items-center justify-center bg-gray-50 p-4" ]

      
        
        168
        +            [ H.div [ A.class "w-full max-w-md bg-white rounded-lg border border-gray-200 shadow-sm" ]

      
        
        169
        +                -- TODO: add oauth buttons

      
        
        170
        +                [ viewBanner model.apiError model.gotSignedUp

      
        
        171
        +                , viewHeader model.formVariant

      
        
        172
        +                , H.div [ A.class "px-6 pb-6 space-y-4" ]

      
        
        173
        +                    [ viewChangeVariant model.formVariant

      
        
        174
        +                    , H.div [ A.class "border-t border-gray-200" ] []

      
        
        175
        +                    , viewForm model

      
        
        176
        +                    ]

      
        
        177
        +                ]

      
        173
        178
                     ]

      
        174
        179
                 ]

      
        175
        180
             }

      
        176
        181
         

      
        177
        182
         

      
        
        183
        +viewBanner : Maybe Api.Error -> Bool -> Html Msg

      
        
        184
        +viewBanner maybeError gotSignedUp =

      
        
        185
        +    case ( maybeError, gotSignedUp ) of

      
        
        186
        +        ( Just error, False ) ->

      
        
        187
        +            viewBannerError error

      
        
        188
        +

      
        
        189
        +        ( Nothing, True ) ->

      
        
        190
        +            viewBannerSuccess

      
        
        191
        +

      
        
        192
        +        _ ->

      
        
        193
        +            H.text ""

      
        
        194
        +

      
        
        195
        +

      
        
        196
        +viewBannerSuccess : Html Msg

      
        
        197
        +viewBannerSuccess =

      
        
        198
        +    let

      
        
        199
        +        buttonClassesBase : String

      
        
        200
        +        buttonClassesBase =

      
        
        201
        +            "w-full px-4 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 transition-colors mt-3"

      
        
        202
        +

      
        
        203
        +        buttonClasses : Bool -> String

      
        
        204
        +        buttonClasses disabled =

      
        
        205
        +            if disabled then

      
        
        206
        +                buttonClassesBase ++ " border border-gray-300 text-gray-400 cursor-not-allowed"

      
        
        207
        +

      
        
        208
        +            else

      
        
        209
        +                buttonClassesBase ++ " border border-gray-300 text-gray-700 hover:bg-gray-50"

      
        
        210
        +

      
        
        211
        +        isDisabled : Bool

      
        
        212
        +        isDisabled =

      
        
        213
        +            False

      
        
        214
        +    in

      
        
        215
        +    H.div [ A.class "bg-green-50 border border-green-200 rounded-md p-4 mb-4" ]

      
        
        216
        +        [ H.div [ A.class "font-medium text-green-800 mb-2" ] [ H.text "Check your email!" ]

      
        
        217
        +        , H.p [ A.class "text-green-800 text-sm" ] [ H.text "We've sent you a verification link. Please check your email and click the link to activate your account." ]

      
        
        218
        +        , H.button

      
        
        219
        +            -- TODO: implement countdown for resend button

      
        
        220
        +            [ A.class (buttonClasses isDisabled)

      
        
        221
        +            , E.onClick UserClickedResendActivationEmail

      
        
        222
        +            , A.disabled isDisabled

      
        
        223
        +            ]

      
        
        224
        +            [ H.text "Resend verification email" ]

      
        
        225
        +        , if isDisabled then

      
        
        226
        +            H.p [ A.class "text-gray-600 text-xs mt-2" ] [ H.text "You can request a new verification email in N seconds" ]

      
        
        227
        +

      
        
        228
        +          else

      
        
        229
        +            H.text ""

      
        
        230
        +        ]

      
        
        231
        +

      
        
        232
        +

      
        
        233
        +viewBannerError : Api.Error -> Html Msg

      
        
        234
        +viewBannerError error =

      
        
        235
        +    H.div [ A.class "bg-red-50 border border-red-200 rounded-md p-4 mb-3" ]

      
        
        236
        +        [ H.p

      
        
        237
        +            [ A.class "text-red-800 text-sm" ]

      
        
        238
        +            [ H.text (Api.errorMessage error) ]

      
        
        239
        +        ]

      
        
        240
        +

      
        
        241
        +

      
        
        242
        +viewHeader : Variant -> Html Msg

      
        
        243
        +viewHeader variant =

      
        
        244
        +    let

      
        
        245
        +        ( title, description ) =

      
        
        246
        +            case variant of

      
        
        247
        +                SignIn ->

      
        
        248
        +                    ( "Welcome Back", "Enter your credentials to access your account" )

      
        
        249
        +

      
        
        250
        +                SignUp ->

      
        
        251
        +                    ( "Create Account", "Enter your information to create your account" )

      
        
        252
        +    in

      
        
        253
        +    H.div [ A.class "p-6 pb-4" ]

      
        
        254
        +        [ H.h1 [ A.class "text-2xl font-bold text-center mb-2" ] [ H.text title ]

      
        
        255
        +        , H.p [ A.class "text-center text-gray-600 text-sm" ] [ H.text description ]

      
        
        256
        +        ]

      
        
        257
        +

      
        
        258
        +

      
        178
        259
         viewChangeVariant : Variant -> Html Msg

      
        179
        260
         viewChangeVariant variant =

      
        180
        
        -    Html.div [ Attr.class "mb1" ]

      
        181
        
        -        [ Html.button

      
        182
        
        -            [ Attr.disabled (variant == SignIn)

      
        183
        
        -            , Html.Events.onClick (UserChangedFormVariant SignIn)

      
        
        261
        +    let

      
        
        262
        +        base : String

      
        
        263
        +        base =

      
        
        264
        +            "flex-1 px-4 py-2 rounded-md font-medium transition-colors"

      
        
        265
        +

      
        
        266
        +        buttonClasses : Bool -> String

      
        
        267
        +        buttonClasses active =

      
        
        268
        +            if active then

      
        
        269
        +                base ++ " bg-black text-white"

      
        
        270
        +

      
        
        271
        +            else

      
        
        272
        +                base ++ " bg-white text-black border border-gray-300 hover:bg-gray-50"

      
        
        273
        +    in

      
        
        274
        +    H.div [ A.class "flex gap-2" ]

      
        
        275
        +        [ H.button

      
        
        276
        +            [ A.class (buttonClasses (variant == SignIn))

      
        
        277
        +            , A.disabled (variant == SignIn)

      
        
        278
        +            , E.onClick (UserChangedFormVariant SignIn)

      
        184
        279
                     ]

      
        185
        
        -            [ Html.text "Sign In" ]

      
        186
        
        -        , Html.button

      
        187
        
        -            [ Attr.disabled (variant == SignUp)

      
        188
        
        -            , Html.Events.onClick (UserChangedFormVariant SignUp)

      
        
        280
        +            [ H.text "Sign In" ]

      
        
        281
        +        , H.button

      
        
        282
        +            [ A.class (buttonClasses (variant == SignUp))

      
        
        283
        +            , A.disabled (variant == SignUp)

      
        
        284
        +            , E.onClick (UserChangedFormVariant SignUp)

      
        189
        285
                     ]

      
        190
        
        -            [ Html.text "Sign Up" ]

      
        
        286
        +            [ H.text "Sign Up" ]

      
        191
        287
                 ]

      
        192
        288
         

      
        193
        289
         

      
        194
        290
         viewForm : Model -> Html Msg

      
        195
        291
         viewForm model =

      
        196
        
        -    Html.form [ Html.Events.onSubmit UserClickedSubmit ]

      
        
        292
        +    H.form

      
        
        293
        +        [ A.class "space-y-4"

      
        
        294
        +        , E.onSubmit UserClickedSubmit

      
        
        295
        +        ]

      
        197
        296
                 (case model.formVariant of

      
        198
        297
                     SignIn ->

      
        199
        298
                         [ viewFormInput { field = Email, value = model.email }

      
        200
        299
                         , viewFormInput { field = Password, value = model.password }

      
        
        300
        +                , viewForgotPassword

      
        201
        301
                         , viewSubmitButton model

      
        202
        302
                         ]

      
        203
        303
         

      ···
        210
        310
                 )

      
        211
        311
         

      
        212
        312
         

      
        213
        
        -viewBanner : Maybe Api.Error -> Bool -> Html Msg

      
        214
        
        -viewBanner maybeError gotSignedUp =

      
        215
        
        -    case ( maybeError, gotSignedUp ) of

      
        216
        
        -        ( Just error, _ ) ->

      
        217
        
        -            Html.div [ Attr.class "box bad" ]

      
        218
        
        -                [ Html.strong [ Attr.class "block titlebar" ] [ Html.text "Error" ]

      
        219
        
        -                , Html.text (Api.errorMessage error)

      
        220
        
        -                ]

      
        221
        
        -

      
        222
        
        -        ( Nothing, True ) ->

      
        223
        
        -            Html.div [ Attr.class "box ok" ]

      
        224
        
        -                [ Html.strong [ Attr.class "block titlebar" ] [ Html.text "Successfully signed up!" ]

      
        225
        
        -                , Html.p []

      
        226
        
        -                    [ Html.text "Please check your email to activate your account."

      
        227
        
        -                    , Html.text " If you don't see the email, please check your spam folder."

      
        228
        
        -                    , Html.button [ Html.Events.onClick UserClickedResendActivationEmail ]

      
        229
        
        -                        [ Html.text "Resend activation email"

      
        230
        
        -                        ]

      
        231
        
        -                    ]

      
        232
        
        -                ]

      
        233
        
        -

      
        234
        
        -        ( Nothing, False ) ->

      
        235
        
        -            Html.text ""

      
        236
        
        -

      
        237
        
        -

      
        238
        313
         viewFormInput : { field : Field, value : String } -> Html Msg

      
        239
        314
         viewFormInput opts =

      
        240
        
        -    Html.div [ Attr.class "mb1" ]

      
        241
        
        -        [ Html.label [] [ Html.text (fromFieldToLabel opts.field) ]

      
        242
        
        -        , Html.div []

      
        243
        
        -            [ Html.input

      
        244
        
        -                [ Attr.type_ (fromFieldToInputType opts.field)

      
        245
        
        -                , Attr.value opts.value

      
        246
        
        -                , Html.Events.onInput (UserUpdatedInput opts.field)

      
        
        315
        +    H.div [ A.class "space-y-2" ]

      
        
        316
        +        [ H.label

      
        
        317
        +            [ A.class "block text-sm font-medium text-gray-700" ]

      
        
        318
        +            [ H.text (fromFieldToLabel opts.field) ]

      
        
        319
        +        , H.div []

      
        
        320
        +            [ H.input

      
        
        321
        +                [ A.class "w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-black focus:border-transparent"

      
        
        322
        +                , A.type_ (fromFieldToInputType opts.field)

      
        
        323
        +                , A.value opts.value

      
        
        324
        +                , A.placeholder (fromFieldToLabel opts.field)

      
        
        325
        +                , E.onInput (UserUpdatedInput opts.field)

      
        247
        326
                         ]

      
        248
        327
                         []

      
        249
        328
                     ]

      ···
        252
        331
         

      
        253
        332
         viewForgotPassword : Html Msg

      
        254
        333
         viewForgotPassword =

      
        255
        
        -    Html.div []

      
        256
        
        -        [ Html.a

      
        257
        
        -            [ Attr.href "/forgot-password" ]

      
        258
        
        -            [ Html.text "Forgot password?" ]

      
        
        334
        +    H.div [ A.class "text-right" ]

      
        
        335
        +        [ H.button

      
        
        336
        +            [ A.class "text-sm text-black hover:underline focus:outline-none"

      
        
        337
        +            , A.type_ "button"

      
        
        338
        +

      
        
        339
        +            -- TODO: implement forgot password

      
        
        340
        +            -- , E.onClick (UserChangedFormVariant ForgotPassword)

      
        
        341
        +            ]

      
        
        342
        +            [ H.text "Forgot password?" ]

      
        259
        343
                 ]

      
        260
        344
         

      
        261
        345
         

      
        262
        346
         viewSubmitButton : Model -> Html Msg

      
        263
        347
         viewSubmitButton model =

      
        264
        
        -    Html.div [ Attr.class "mb1" ]

      
        265
        
        -        [ Html.button

      
        266
        
        -            [ Attr.disabled (isFormDisabled model) ]

      
        267
        
        -            [ Html.text (fromVariantToLabel model.formVariant) ]

      
        
        348
        +    H.button

      
        
        349
        +        [ A.type_ "submit"

      
        
        350
        +        , A.disabled (isFormDisabled model)

      
        
        351
        +        , A.class

      
        
        352
        +            (if isFormDisabled model then

      
        
        353
        +                "w-full px-4 py-2 bg-gray-300 text-gray-500 rounded-md cursor-not-allowed transition-colors"

      
        
        354
        +

      
        
        355
        +             else

      
        
        356
        +                "w-full px-4 py-2 bg-black text-white rounded-md hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 transition-colors"

      
        
        357
        +            )

      
        268
        358
                 ]

      
        
        359
        +        [ H.text (fromVariantToLabel model.formVariant) ]

      
        269
        360
         

      
        270
        361
         

      
        271
        362
         isFormDisabled : Model -> Bool

      ···
        304
        395
                     "Password"

      
        305
        396
         

      
        306
        397
                 PasswordAgain ->

      
        307
        
        -            "Password again"

      
        
        398
        +            "Confirm password"

      
        308
        399
         

      
        309
        400
         

      
        310
        401
         fromFieldToInputType : Field -> String

      
M web/src/Pages/Home_.elm
···
        1
        1
         module Pages.Home_ exposing (Model, Msg, page)

      
        2
        2
         

      
        3
        3
         import Effect exposing (Effect)

      
        4
        
        -import Html

      
        5
        
        -import Html.Events

      
        
        4
        +import Html as H

      
        
        5
        +import Html.Attributes as A

      
        
        6
        +import Html.Events as E

      
        6
        7
         import Layouts

      
        7
        8
         import Page exposing (Page)

      
        8
        9
         import Route exposing (Route)

      ···
        65
        66
         view : Shared.Model -> Model -> View Msg

      
        66
        67
         view _ _ =

      
        67
        68
             { title = "Homepage"

      
        68
        
        -    , body = [ Html.p [ Html.Events.onClick NoOp ] [ Html.text "Hello, world!" ] ]

      
        
        69
        +    , body =

      
        
        70
        +        [ H.div [ A.class "w-full max-w-6xl mx-auto" ]

      
        
        71
        +            [ H.p [ E.onClick NoOp ] [ H.text "Hello, world!" ] ]

      
        
        72
        +        ]

      
        69
        73
             }

      
M web/src/styles.css
···
        1
        
        -@import "missing.css";

      
        2
        
        -

      
        3
        
        -.mb1 {

      
        4
        
        -  margin-bottom: 1rem;

      
        5
        
        -}

      
        
        1
        +@import "tailwindcss";

      
        
        2
        +@source './**/*.{js,elm,ts,css,html}';

      
        
        3
        +@source '../.elm-land/**/*.{js,elm,ts,css,html}';