Felix Zieger commited on
Commit
1a45d5d
·
1 Parent(s): fc6c570
package-lock.json CHANGED
@@ -43,6 +43,7 @@
43
  "class-variance-authority": "^0.7.1",
44
  "clsx": "^2.1.1",
45
  "cmdk": "^1.0.0",
 
46
  "date-fns": "^3.6.0",
47
  "embla-carousel-react": "^8.3.0",
48
  "framer-motion": "^12.0.5",
@@ -86,6 +87,7 @@
86
  "version": "5.2.0",
87
  "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
88
  "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
 
89
  "license": "MIT",
90
  "engines": {
91
  "node": ">=10"
@@ -783,6 +785,7 @@
783
  "version": "8.0.2",
784
  "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
785
  "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
 
786
  "license": "ISC",
787
  "dependencies": {
788
  "string-width": "^5.1.2",
@@ -800,6 +803,7 @@
800
  "version": "0.3.5",
801
  "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
802
  "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
 
803
  "license": "MIT",
804
  "dependencies": {
805
  "@jridgewell/set-array": "^1.2.1",
@@ -814,6 +818,7 @@
814
  "version": "3.1.2",
815
  "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
816
  "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
 
817
  "license": "MIT",
818
  "engines": {
819
  "node": ">=6.0.0"
@@ -823,6 +828,7 @@
823
  "version": "1.2.1",
824
  "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
825
  "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
 
826
  "license": "MIT",
827
  "engines": {
828
  "node": ">=6.0.0"
@@ -832,12 +838,14 @@
832
  "version": "1.5.0",
833
  "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
834
  "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
 
835
  "license": "MIT"
836
  },
837
  "node_modules/@jridgewell/trace-mapping": {
838
  "version": "0.3.25",
839
  "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
840
  "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
 
841
  "license": "MIT",
842
  "dependencies": {
843
  "@jridgewell/resolve-uri": "^3.1.0",
@@ -856,6 +864,7 @@
856
  "version": "2.1.5",
857
  "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
858
  "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
 
859
  "license": "MIT",
860
  "dependencies": {
861
  "@nodelib/fs.stat": "2.0.5",
@@ -869,6 +878,7 @@
869
  "version": "2.0.5",
870
  "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
871
  "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
 
872
  "license": "MIT",
873
  "engines": {
874
  "node": ">= 8"
@@ -878,6 +888,7 @@
878
  "version": "1.2.8",
879
  "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
880
  "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
 
881
  "license": "MIT",
882
  "dependencies": {
883
  "@nodelib/fs.scandir": "2.1.5",
@@ -891,6 +902,7 @@
891
  "version": "0.11.0",
892
  "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
893
  "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
 
894
  "license": "MIT",
895
  "optional": true,
896
  "engines": {
@@ -2970,14 +2982,14 @@
2970
  "version": "15.7.13",
2971
  "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
2972
  "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
2973
- "devOptional": true,
2974
  "license": "MIT"
2975
  },
2976
  "node_modules/@types/react": {
2977
  "version": "18.3.12",
2978
  "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
2979
  "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
2980
- "devOptional": true,
2981
  "license": "MIT",
2982
  "dependencies": {
2983
  "@types/prop-types": "*",
@@ -2988,7 +3000,7 @@
2988
  "version": "18.3.1",
2989
  "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
2990
  "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
2991
- "devOptional": true,
2992
  "license": "MIT",
2993
  "dependencies": {
2994
  "@types/react": "*"
@@ -3289,6 +3301,7 @@
3289
  "version": "6.1.0",
3290
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
3291
  "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
 
3292
  "license": "MIT",
3293
  "engines": {
3294
  "node": ">=12"
@@ -3301,6 +3314,7 @@
3301
  "version": "4.3.0",
3302
  "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
3303
  "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
 
3304
  "license": "MIT",
3305
  "dependencies": {
3306
  "color-convert": "^2.0.1"
@@ -3316,12 +3330,14 @@
3316
  "version": "1.3.0",
3317
  "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
3318
  "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
 
3319
  "license": "MIT"
3320
  },
3321
  "node_modules/anymatch": {
3322
  "version": "3.1.3",
3323
  "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
3324
  "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
 
3325
  "license": "ISC",
3326
  "dependencies": {
3327
  "normalize-path": "^3.0.0",
@@ -3335,6 +3351,7 @@
3335
  "version": "5.0.2",
3336
  "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
3337
  "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
 
3338
  "license": "MIT"
3339
  },
3340
  "node_modules/argparse": {
@@ -3415,12 +3432,14 @@
3415
  "version": "1.0.2",
3416
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
3417
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
 
3418
  "license": "MIT"
3419
  },
3420
  "node_modules/binary-extensions": {
3421
  "version": "2.3.0",
3422
  "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
3423
  "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
 
3424
  "license": "MIT",
3425
  "engines": {
3426
  "node": ">=8"
@@ -3444,6 +3463,7 @@
3444
  "version": "3.0.3",
3445
  "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
3446
  "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
 
3447
  "license": "MIT",
3448
  "dependencies": {
3449
  "fill-range": "^7.1.1"
@@ -3499,6 +3519,7 @@
3499
  "version": "2.0.1",
3500
  "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
3501
  "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
 
3502
  "license": "MIT",
3503
  "engines": {
3504
  "node": ">= 6"
@@ -3546,6 +3567,7 @@
3546
  "version": "3.6.0",
3547
  "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
3548
  "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
 
3549
  "license": "MIT",
3550
  "dependencies": {
3551
  "anymatch": "~3.1.2",
@@ -3570,6 +3592,7 @@
3570
  "version": "5.1.2",
3571
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
3572
  "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
 
3573
  "license": "ISC",
3574
  "dependencies": {
3575
  "is-glob": "^4.0.1"
@@ -3980,6 +4003,7 @@
3980
  "version": "2.0.1",
3981
  "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
3982
  "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
 
3983
  "license": "MIT",
3984
  "dependencies": {
3985
  "color-name": "~1.1.4"
@@ -3992,6 +4016,7 @@
3992
  "version": "1.1.4",
3993
  "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
3994
  "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
 
3995
  "license": "MIT"
3996
  },
3997
  "node_modules/combined-stream": {
@@ -4010,11 +4035,26 @@
4010
  "version": "4.1.1",
4011
  "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
4012
  "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
 
4013
  "license": "MIT",
4014
  "engines": {
4015
  "node": ">= 6"
4016
  }
4017
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4018
  "node_modules/concat-map": {
4019
  "version": "0.0.1",
4020
  "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -4026,6 +4066,7 @@
4026
  "version": "7.0.6",
4027
  "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
4028
  "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
 
4029
  "dependencies": {
4030
  "path-key": "^3.1.0",
4031
  "shebang-command": "^2.0.0",
@@ -4039,6 +4080,7 @@
4039
  "version": "3.0.0",
4040
  "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
4041
  "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
 
4042
  "license": "MIT",
4043
  "bin": {
4044
  "cssesc": "bin/cssesc"
@@ -4234,12 +4276,14 @@
4234
  "version": "1.2.2",
4235
  "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
4236
  "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
 
4237
  "license": "Apache-2.0"
4238
  },
4239
  "node_modules/dlv": {
4240
  "version": "1.1.3",
4241
  "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
4242
  "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
 
4243
  "license": "MIT"
4244
  },
4245
  "node_modules/dom-helpers": {
@@ -4256,8 +4300,18 @@
4256
  "version": "0.2.0",
4257
  "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
4258
  "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
 
4259
  "license": "MIT"
4260
  },
 
 
 
 
 
 
 
 
 
4261
  "node_modules/electron-to-chromium": {
4262
  "version": "1.5.45",
4263
  "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.45.tgz",
@@ -4297,6 +4351,7 @@
4297
  "version": "9.2.2",
4298
  "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
4299
  "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
 
4300
  "license": "MIT"
4301
  },
4302
  "node_modules/esbuild": {
@@ -4575,6 +4630,7 @@
4575
  "version": "3.3.2",
4576
  "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
4577
  "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
 
4578
  "license": "MIT",
4579
  "dependencies": {
4580
  "@nodelib/fs.stat": "^2.0.2",
@@ -4591,6 +4647,7 @@
4591
  "version": "5.1.2",
4592
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
4593
  "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
 
4594
  "license": "ISC",
4595
  "dependencies": {
4596
  "is-glob": "^4.0.1"
@@ -4617,6 +4674,7 @@
4617
  "version": "1.17.1",
4618
  "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
4619
  "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
 
4620
  "license": "ISC",
4621
  "dependencies": {
4622
  "reusify": "^1.0.4"
@@ -4639,6 +4697,7 @@
4639
  "version": "7.1.1",
4640
  "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
4641
  "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
 
4642
  "license": "MIT",
4643
  "dependencies": {
4644
  "to-regex-range": "^5.0.1"
@@ -4709,6 +4768,7 @@
4709
  "version": "3.3.0",
4710
  "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
4711
  "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
 
4712
  "license": "ISC",
4713
  "dependencies": {
4714
  "cross-spawn": "^7.0.0",
@@ -4780,6 +4840,7 @@
4780
  "version": "2.3.3",
4781
  "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
4782
  "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
 
4783
  "hasInstallScript": true,
4784
  "license": "MIT",
4785
  "optional": true,
@@ -4794,6 +4855,7 @@
4794
  "version": "1.1.2",
4795
  "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
4796
  "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
 
4797
  "license": "MIT",
4798
  "funding": {
4799
  "url": "https://github.com/sponsors/ljharb"
@@ -4812,6 +4874,7 @@
4812
  "version": "10.4.5",
4813
  "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
4814
  "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
 
4815
  "license": "ISC",
4816
  "dependencies": {
4817
  "foreground-child": "^3.1.0",
@@ -4832,6 +4895,7 @@
4832
  "version": "6.0.2",
4833
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
4834
  "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
 
4835
  "license": "ISC",
4836
  "dependencies": {
4837
  "is-glob": "^4.0.3"
@@ -4844,6 +4908,7 @@
4844
  "version": "2.0.1",
4845
  "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
4846
  "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
 
4847
  "license": "MIT",
4848
  "dependencies": {
4849
  "balanced-match": "^1.0.0"
@@ -4853,6 +4918,7 @@
4853
  "version": "9.0.5",
4854
  "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
4855
  "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
 
4856
  "license": "ISC",
4857
  "dependencies": {
4858
  "brace-expansion": "^2.0.1"
@@ -4877,6 +4943,15 @@
4877
  "url": "https://github.com/sponsors/sindresorhus"
4878
  }
4879
  },
 
 
 
 
 
 
 
 
 
4880
  "node_modules/graphemer": {
4881
  "version": "1.4.0",
4882
  "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
@@ -4898,6 +4973,7 @@
4898
  "version": "2.0.2",
4899
  "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
4900
  "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
 
4901
  "license": "MIT",
4902
  "dependencies": {
4903
  "function-bind": "^1.1.2"
@@ -4975,6 +5051,7 @@
4975
  "version": "2.1.0",
4976
  "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
4977
  "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
 
4978
  "license": "MIT",
4979
  "dependencies": {
4980
  "binary-extensions": "^2.0.0"
@@ -4987,6 +5064,7 @@
4987
  "version": "2.15.1",
4988
  "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
4989
  "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
 
4990
  "license": "MIT",
4991
  "dependencies": {
4992
  "hasown": "^2.0.2"
@@ -5002,6 +5080,7 @@
5002
  "version": "2.1.1",
5003
  "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
5004
  "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
 
5005
  "license": "MIT",
5006
  "engines": {
5007
  "node": ">=0.10.0"
@@ -5011,6 +5090,7 @@
5011
  "version": "3.0.0",
5012
  "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
5013
  "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
 
5014
  "license": "MIT",
5015
  "engines": {
5016
  "node": ">=8"
@@ -5020,6 +5100,7 @@
5020
  "version": "4.0.3",
5021
  "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
5022
  "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
 
5023
  "license": "MIT",
5024
  "dependencies": {
5025
  "is-extglob": "^2.1.1"
@@ -5032,6 +5113,7 @@
5032
  "version": "7.0.0",
5033
  "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
5034
  "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
 
5035
  "license": "MIT",
5036
  "engines": {
5037
  "node": ">=0.12.0"
@@ -5041,12 +5123,14 @@
5041
  "version": "2.0.0",
5042
  "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
5043
  "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
 
5044
  "license": "ISC"
5045
  },
5046
  "node_modules/jackspeak": {
5047
  "version": "3.4.3",
5048
  "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
5049
  "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
 
5050
  "license": "BlueOak-1.0.0",
5051
  "dependencies": {
5052
  "@isaacs/cliui": "^8.0.2"
@@ -5062,6 +5146,7 @@
5062
  "version": "1.21.6",
5063
  "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
5064
  "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
 
5065
  "license": "MIT",
5066
  "bin": {
5067
  "jiti": "bin/jiti.js"
@@ -5135,6 +5220,7 @@
5135
  "version": "2.1.0",
5136
  "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
5137
  "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
 
5138
  "license": "MIT",
5139
  "engines": {
5140
  "node": ">=10"
@@ -5144,6 +5230,7 @@
5144
  "version": "1.2.4",
5145
  "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
5146
  "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
 
5147
  "license": "MIT"
5148
  },
5149
  "node_modules/locate-path": {
@@ -5219,6 +5306,7 @@
5219
  "version": "10.4.3",
5220
  "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
5221
  "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
 
5222
  "license": "ISC"
5223
  },
5224
  "node_modules/lucide-react": {
@@ -5243,6 +5331,7 @@
5243
  "version": "1.4.1",
5244
  "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
5245
  "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
 
5246
  "license": "MIT",
5247
  "engines": {
5248
  "node": ">= 8"
@@ -5252,6 +5341,7 @@
5252
  "version": "4.0.8",
5253
  "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
5254
  "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
 
5255
  "license": "MIT",
5256
  "dependencies": {
5257
  "braces": "^3.0.3",
@@ -5299,6 +5389,7 @@
5299
  "version": "7.1.2",
5300
  "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
5301
  "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
 
5302
  "license": "ISC",
5303
  "engines": {
5304
  "node": ">=16 || 14 >=14.17"
@@ -5330,6 +5421,7 @@
5330
  "version": "2.7.0",
5331
  "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
5332
  "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
 
5333
  "license": "MIT",
5334
  "dependencies": {
5335
  "any-promise": "^1.0.0",
@@ -5341,6 +5433,7 @@
5341
  "version": "3.3.7",
5342
  "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
5343
  "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
 
5344
  "funding": [
5345
  {
5346
  "type": "github",
@@ -5383,6 +5476,7 @@
5383
  "version": "3.0.0",
5384
  "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
5385
  "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
 
5386
  "license": "MIT",
5387
  "engines": {
5388
  "node": ">=0.10.0"
@@ -5411,6 +5505,7 @@
5411
  "version": "3.0.0",
5412
  "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
5413
  "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
 
5414
  "license": "MIT",
5415
  "engines": {
5416
  "node": ">= 6"
@@ -5470,6 +5565,7 @@
5470
  "version": "1.0.1",
5471
  "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
5472
  "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
 
5473
  "license": "BlueOak-1.0.0"
5474
  },
5475
  "node_modules/parent-module": {
@@ -5499,6 +5595,7 @@
5499
  "version": "3.1.1",
5500
  "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
5501
  "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
 
5502
  "license": "MIT",
5503
  "engines": {
5504
  "node": ">=8"
@@ -5508,12 +5605,14 @@
5508
  "version": "1.0.7",
5509
  "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
5510
  "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
 
5511
  "license": "MIT"
5512
  },
5513
  "node_modules/path-scurry": {
5514
  "version": "1.11.1",
5515
  "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
5516
  "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
 
5517
  "license": "BlueOak-1.0.0",
5518
  "dependencies": {
5519
  "lru-cache": "^10.2.0",
@@ -5530,12 +5629,14 @@
5530
  "version": "1.1.1",
5531
  "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
5532
  "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
 
5533
  "license": "ISC"
5534
  },
5535
  "node_modules/picomatch": {
5536
  "version": "2.3.1",
5537
  "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
5538
  "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
 
5539
  "license": "MIT",
5540
  "engines": {
5541
  "node": ">=8.6"
@@ -5548,6 +5649,7 @@
5548
  "version": "2.3.0",
5549
  "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
5550
  "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
 
5551
  "license": "MIT",
5552
  "engines": {
5553
  "node": ">=0.10.0"
@@ -5557,6 +5659,7 @@
5557
  "version": "4.0.6",
5558
  "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
5559
  "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
 
5560
  "license": "MIT",
5561
  "engines": {
5562
  "node": ">= 6"
@@ -5566,6 +5669,7 @@
5566
  "version": "8.4.47",
5567
  "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
5568
  "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
 
5569
  "funding": [
5570
  {
5571
  "type": "opencollective",
@@ -5594,6 +5698,7 @@
5594
  "version": "15.1.0",
5595
  "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
5596
  "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
 
5597
  "license": "MIT",
5598
  "dependencies": {
5599
  "postcss-value-parser": "^4.0.0",
@@ -5611,6 +5716,7 @@
5611
  "version": "4.0.1",
5612
  "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
5613
  "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
 
5614
  "license": "MIT",
5615
  "dependencies": {
5616
  "camelcase-css": "^2.0.1"
@@ -5630,6 +5736,7 @@
5630
  "version": "4.0.2",
5631
  "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
5632
  "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
 
5633
  "funding": [
5634
  {
5635
  "type": "opencollective",
@@ -5665,6 +5772,7 @@
5665
  "version": "3.1.2",
5666
  "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
5667
  "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
 
5668
  "license": "MIT",
5669
  "engines": {
5670
  "node": ">=14"
@@ -5677,6 +5785,7 @@
5677
  "version": "6.2.0",
5678
  "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
5679
  "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
 
5680
  "funding": [
5681
  {
5682
  "type": "opencollective",
@@ -5702,6 +5811,7 @@
5702
  "version": "6.1.2",
5703
  "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
5704
  "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
 
5705
  "license": "MIT",
5706
  "dependencies": {
5707
  "cssesc": "^3.0.0",
@@ -5715,6 +5825,7 @@
5715
  "version": "4.2.0",
5716
  "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
5717
  "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
 
5718
  "license": "MIT"
5719
  },
5720
  "node_modules/prelude-ls": {
@@ -5764,6 +5875,7 @@
5764
  "version": "1.2.3",
5765
  "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
5766
  "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
 
5767
  "funding": [
5768
  {
5769
  "type": "github",
@@ -5988,6 +6100,7 @@
5988
  "version": "1.0.0",
5989
  "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
5990
  "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
 
5991
  "license": "MIT",
5992
  "dependencies": {
5993
  "pify": "^2.3.0"
@@ -5997,6 +6110,7 @@
5997
  "version": "3.6.0",
5998
  "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
5999
  "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
 
6000
  "license": "MIT",
6001
  "dependencies": {
6002
  "picomatch": "^2.2.1"
@@ -6047,6 +6161,7 @@
6047
  "version": "1.22.8",
6048
  "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
6049
  "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
 
6050
  "license": "MIT",
6051
  "dependencies": {
6052
  "is-core-module": "^2.13.0",
@@ -6074,6 +6189,7 @@
6074
  "version": "1.0.4",
6075
  "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
6076
  "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
 
6077
  "license": "MIT",
6078
  "engines": {
6079
  "iojs": ">=1.0.0",
@@ -6120,6 +6236,7 @@
6120
  "version": "1.2.0",
6121
  "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
6122
  "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
 
6123
  "funding": [
6124
  {
6125
  "type": "github",
@@ -6165,6 +6282,7 @@
6165
  "version": "2.0.0",
6166
  "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
6167
  "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
 
6168
  "license": "MIT",
6169
  "dependencies": {
6170
  "shebang-regex": "^3.0.0"
@@ -6177,6 +6295,7 @@
6177
  "version": "3.0.0",
6178
  "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
6179
  "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
 
6180
  "license": "MIT",
6181
  "engines": {
6182
  "node": ">=8"
@@ -6186,6 +6305,7 @@
6186
  "version": "4.1.0",
6187
  "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
6188
  "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
 
6189
  "license": "ISC",
6190
  "engines": {
6191
  "node": ">=14"
@@ -6208,6 +6328,7 @@
6208
  "version": "1.2.1",
6209
  "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
6210
  "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
 
6211
  "license": "BSD-3-Clause",
6212
  "engines": {
6213
  "node": ">=0.10.0"
@@ -6217,6 +6338,7 @@
6217
  "version": "5.1.2",
6218
  "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
6219
  "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
 
6220
  "license": "MIT",
6221
  "dependencies": {
6222
  "eastasianwidth": "^0.2.0",
@@ -6235,6 +6357,7 @@
6235
  "version": "4.2.3",
6236
  "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
6237
  "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
 
6238
  "license": "MIT",
6239
  "dependencies": {
6240
  "emoji-regex": "^8.0.0",
@@ -6249,6 +6372,7 @@
6249
  "version": "5.0.1",
6250
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
6251
  "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
 
6252
  "license": "MIT",
6253
  "engines": {
6254
  "node": ">=8"
@@ -6258,12 +6382,14 @@
6258
  "version": "8.0.0",
6259
  "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
6260
  "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
 
6261
  "license": "MIT"
6262
  },
6263
  "node_modules/string-width-cjs/node_modules/strip-ansi": {
6264
  "version": "6.0.1",
6265
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6266
  "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
 
6267
  "license": "MIT",
6268
  "dependencies": {
6269
  "ansi-regex": "^5.0.1"
@@ -6276,6 +6402,7 @@
6276
  "version": "7.1.0",
6277
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
6278
  "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
 
6279
  "license": "MIT",
6280
  "dependencies": {
6281
  "ansi-regex": "^6.0.1"
@@ -6292,6 +6419,7 @@
6292
  "version": "6.0.1",
6293
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6294
  "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
 
6295
  "license": "MIT",
6296
  "dependencies": {
6297
  "ansi-regex": "^5.0.1"
@@ -6304,6 +6432,7 @@
6304
  "version": "5.0.1",
6305
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
6306
  "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
 
6307
  "license": "MIT",
6308
  "engines": {
6309
  "node": ">=8"
@@ -6326,6 +6455,7 @@
6326
  "version": "3.35.0",
6327
  "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
6328
  "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
 
6329
  "license": "MIT",
6330
  "dependencies": {
6331
  "@jridgewell/gen-mapping": "^0.3.2",
@@ -6344,6 +6474,12 @@
6344
  "node": ">=16 || 14 >=14.17"
6345
  }
6346
  },
 
 
 
 
 
 
6347
  "node_modules/supports-color": {
6348
  "version": "7.2.0",
6349
  "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -6361,6 +6497,7 @@
6361
  "version": "1.0.0",
6362
  "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
6363
  "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
 
6364
  "license": "MIT",
6365
  "engines": {
6366
  "node": ">= 0.4"
@@ -6383,6 +6520,7 @@
6383
  "version": "3.4.14",
6384
  "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
6385
  "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
 
6386
  "license": "MIT",
6387
  "dependencies": {
6388
  "@alloc/quick-lru": "^5.2.0",
@@ -6436,6 +6574,7 @@
6436
  "version": "3.3.1",
6437
  "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
6438
  "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
 
6439
  "license": "MIT",
6440
  "dependencies": {
6441
  "any-promise": "^1.0.0"
@@ -6445,6 +6584,7 @@
6445
  "version": "1.6.0",
6446
  "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
6447
  "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
 
6448
  "license": "MIT",
6449
  "dependencies": {
6450
  "thenify": ">= 3.1.0 < 4"
@@ -6463,6 +6603,7 @@
6463
  "version": "5.0.1",
6464
  "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
6465
  "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
 
6466
  "license": "MIT",
6467
  "dependencies": {
6468
  "is-number": "^7.0.0"
@@ -6494,6 +6635,7 @@
6494
  "version": "0.1.13",
6495
  "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
6496
  "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
 
6497
  "license": "Apache-2.0"
6498
  },
6499
  "node_modules/tslib": {
@@ -6647,6 +6789,7 @@
6647
  "version": "1.0.2",
6648
  "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
6649
  "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
 
6650
  "license": "MIT"
6651
  },
6652
  "node_modules/vaul": {
@@ -6764,6 +6907,7 @@
6764
  "version": "2.0.2",
6765
  "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
6766
  "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
 
6767
  "license": "ISC",
6768
  "dependencies": {
6769
  "isexe": "^2.0.0"
@@ -6789,6 +6933,7 @@
6789
  "version": "8.1.0",
6790
  "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
6791
  "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
 
6792
  "license": "MIT",
6793
  "dependencies": {
6794
  "ansi-styles": "^6.1.0",
@@ -6807,6 +6952,7 @@
6807
  "version": "7.0.0",
6808
  "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
6809
  "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
 
6810
  "license": "MIT",
6811
  "dependencies": {
6812
  "ansi-styles": "^4.0.0",
@@ -6824,6 +6970,7 @@
6824
  "version": "5.0.1",
6825
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
6826
  "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
 
6827
  "license": "MIT",
6828
  "engines": {
6829
  "node": ">=8"
@@ -6833,12 +6980,14 @@
6833
  "version": "8.0.0",
6834
  "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
6835
  "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
 
6836
  "license": "MIT"
6837
  },
6838
  "node_modules/wrap-ansi-cjs/node_modules/string-width": {
6839
  "version": "4.2.3",
6840
  "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
6841
  "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
 
6842
  "license": "MIT",
6843
  "dependencies": {
6844
  "emoji-regex": "^8.0.0",
@@ -6853,6 +7002,7 @@
6853
  "version": "6.0.1",
6854
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6855
  "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
 
6856
  "license": "MIT",
6857
  "dependencies": {
6858
  "ansi-regex": "^5.0.1"
@@ -6865,6 +7015,7 @@
6865
  "version": "6.2.1",
6866
  "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
6867
  "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
 
6868
  "license": "MIT",
6869
  "engines": {
6870
  "node": ">=12"
@@ -6898,6 +7049,7 @@
6898
  "version": "2.6.0",
6899
  "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
6900
  "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
 
6901
  "license": "ISC",
6902
  "bin": {
6903
  "yaml": "bin.mjs"
 
43
  "class-variance-authority": "^0.7.1",
44
  "clsx": "^2.1.1",
45
  "cmdk": "^1.0.0",
46
+ "compromise": "^14.12.0",
47
  "date-fns": "^3.6.0",
48
  "embla-carousel-react": "^8.3.0",
49
  "framer-motion": "^12.0.5",
 
87
  "version": "5.2.0",
88
  "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
89
  "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
90
+ "dev": true,
91
  "license": "MIT",
92
  "engines": {
93
  "node": ">=10"
 
785
  "version": "8.0.2",
786
  "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
787
  "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
788
+ "dev": true,
789
  "license": "ISC",
790
  "dependencies": {
791
  "string-width": "^5.1.2",
 
803
  "version": "0.3.5",
804
  "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
805
  "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
806
+ "dev": true,
807
  "license": "MIT",
808
  "dependencies": {
809
  "@jridgewell/set-array": "^1.2.1",
 
818
  "version": "3.1.2",
819
  "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
820
  "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
821
+ "dev": true,
822
  "license": "MIT",
823
  "engines": {
824
  "node": ">=6.0.0"
 
828
  "version": "1.2.1",
829
  "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
830
  "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
831
+ "dev": true,
832
  "license": "MIT",
833
  "engines": {
834
  "node": ">=6.0.0"
 
838
  "version": "1.5.0",
839
  "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
840
  "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
841
+ "dev": true,
842
  "license": "MIT"
843
  },
844
  "node_modules/@jridgewell/trace-mapping": {
845
  "version": "0.3.25",
846
  "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
847
  "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
848
+ "dev": true,
849
  "license": "MIT",
850
  "dependencies": {
851
  "@jridgewell/resolve-uri": "^3.1.0",
 
864
  "version": "2.1.5",
865
  "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
866
  "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
867
+ "dev": true,
868
  "license": "MIT",
869
  "dependencies": {
870
  "@nodelib/fs.stat": "2.0.5",
 
878
  "version": "2.0.5",
879
  "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
880
  "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
881
+ "dev": true,
882
  "license": "MIT",
883
  "engines": {
884
  "node": ">= 8"
 
888
  "version": "1.2.8",
889
  "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
890
  "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
891
+ "dev": true,
892
  "license": "MIT",
893
  "dependencies": {
894
  "@nodelib/fs.scandir": "2.1.5",
 
902
  "version": "0.11.0",
903
  "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
904
  "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
905
+ "dev": true,
906
  "license": "MIT",
907
  "optional": true,
908
  "engines": {
 
2982
  "version": "15.7.13",
2983
  "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
2984
  "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
2985
+ "dev": true,
2986
  "license": "MIT"
2987
  },
2988
  "node_modules/@types/react": {
2989
  "version": "18.3.12",
2990
  "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
2991
  "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
2992
+ "dev": true,
2993
  "license": "MIT",
2994
  "dependencies": {
2995
  "@types/prop-types": "*",
 
3000
  "version": "18.3.1",
3001
  "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
3002
  "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
3003
+ "dev": true,
3004
  "license": "MIT",
3005
  "dependencies": {
3006
  "@types/react": "*"
 
3301
  "version": "6.1.0",
3302
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
3303
  "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
3304
+ "dev": true,
3305
  "license": "MIT",
3306
  "engines": {
3307
  "node": ">=12"
 
3314
  "version": "4.3.0",
3315
  "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
3316
  "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
3317
+ "dev": true,
3318
  "license": "MIT",
3319
  "dependencies": {
3320
  "color-convert": "^2.0.1"
 
3330
  "version": "1.3.0",
3331
  "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
3332
  "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
3333
+ "dev": true,
3334
  "license": "MIT"
3335
  },
3336
  "node_modules/anymatch": {
3337
  "version": "3.1.3",
3338
  "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
3339
  "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
3340
+ "dev": true,
3341
  "license": "ISC",
3342
  "dependencies": {
3343
  "normalize-path": "^3.0.0",
 
3351
  "version": "5.0.2",
3352
  "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
3353
  "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
3354
+ "dev": true,
3355
  "license": "MIT"
3356
  },
3357
  "node_modules/argparse": {
 
3432
  "version": "1.0.2",
3433
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
3434
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
3435
+ "dev": true,
3436
  "license": "MIT"
3437
  },
3438
  "node_modules/binary-extensions": {
3439
  "version": "2.3.0",
3440
  "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
3441
  "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
3442
+ "dev": true,
3443
  "license": "MIT",
3444
  "engines": {
3445
  "node": ">=8"
 
3463
  "version": "3.0.3",
3464
  "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
3465
  "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
3466
+ "dev": true,
3467
  "license": "MIT",
3468
  "dependencies": {
3469
  "fill-range": "^7.1.1"
 
3519
  "version": "2.0.1",
3520
  "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
3521
  "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
3522
+ "dev": true,
3523
  "license": "MIT",
3524
  "engines": {
3525
  "node": ">= 6"
 
3567
  "version": "3.6.0",
3568
  "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
3569
  "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
3570
+ "dev": true,
3571
  "license": "MIT",
3572
  "dependencies": {
3573
  "anymatch": "~3.1.2",
 
3592
  "version": "5.1.2",
3593
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
3594
  "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
3595
+ "dev": true,
3596
  "license": "ISC",
3597
  "dependencies": {
3598
  "is-glob": "^4.0.1"
 
4003
  "version": "2.0.1",
4004
  "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
4005
  "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
4006
+ "dev": true,
4007
  "license": "MIT",
4008
  "dependencies": {
4009
  "color-name": "~1.1.4"
 
4016
  "version": "1.1.4",
4017
  "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
4018
  "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
4019
+ "dev": true,
4020
  "license": "MIT"
4021
  },
4022
  "node_modules/combined-stream": {
 
4035
  "version": "4.1.1",
4036
  "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
4037
  "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
4038
+ "dev": true,
4039
  "license": "MIT",
4040
  "engines": {
4041
  "node": ">= 6"
4042
  }
4043
  },
4044
+ "node_modules/compromise": {
4045
+ "version": "14.12.0",
4046
+ "resolved": "https://registry.npmjs.org/compromise/-/compromise-14.12.0.tgz",
4047
+ "integrity": "sha512-IVJ+ZXgm7Nc9Zobgl8glEir9QYJUc241EggW0JjKBdpRXJjvKB2Y7F+tiJ+vrVk9RQkHoQH5QhPgFX5jX+qL7A==",
4048
+ "license": "MIT",
4049
+ "dependencies": {
4050
+ "efrt": "2.7.0",
4051
+ "grad-school": "0.0.5",
4052
+ "suffix-thumb": "5.0.2"
4053
+ },
4054
+ "engines": {
4055
+ "node": ">=12.0.0"
4056
+ }
4057
+ },
4058
  "node_modules/concat-map": {
4059
  "version": "0.0.1",
4060
  "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
 
4066
  "version": "7.0.6",
4067
  "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
4068
  "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
4069
+ "dev": true,
4070
  "dependencies": {
4071
  "path-key": "^3.1.0",
4072
  "shebang-command": "^2.0.0",
 
4080
  "version": "3.0.0",
4081
  "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
4082
  "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
4083
+ "dev": true,
4084
  "license": "MIT",
4085
  "bin": {
4086
  "cssesc": "bin/cssesc"
 
4276
  "version": "1.2.2",
4277
  "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
4278
  "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
4279
+ "dev": true,
4280
  "license": "Apache-2.0"
4281
  },
4282
  "node_modules/dlv": {
4283
  "version": "1.1.3",
4284
  "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
4285
  "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
4286
+ "dev": true,
4287
  "license": "MIT"
4288
  },
4289
  "node_modules/dom-helpers": {
 
4300
  "version": "0.2.0",
4301
  "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
4302
  "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
4303
+ "dev": true,
4304
  "license": "MIT"
4305
  },
4306
+ "node_modules/efrt": {
4307
+ "version": "2.7.0",
4308
+ "resolved": "https://registry.npmjs.org/efrt/-/efrt-2.7.0.tgz",
4309
+ "integrity": "sha512-/RInbCy1d4P6Zdfa+TMVsf/ufZVotat5hCw3QXmWtjU+3pFEOvOQ7ibo3aIxyCJw2leIeAMjmPj+1SLJiCpdrQ==",
4310
+ "license": "MIT",
4311
+ "engines": {
4312
+ "node": ">=12.0.0"
4313
+ }
4314
+ },
4315
  "node_modules/electron-to-chromium": {
4316
  "version": "1.5.45",
4317
  "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.45.tgz",
 
4351
  "version": "9.2.2",
4352
  "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
4353
  "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
4354
+ "dev": true,
4355
  "license": "MIT"
4356
  },
4357
  "node_modules/esbuild": {
 
4630
  "version": "3.3.2",
4631
  "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
4632
  "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
4633
+ "dev": true,
4634
  "license": "MIT",
4635
  "dependencies": {
4636
  "@nodelib/fs.stat": "^2.0.2",
 
4647
  "version": "5.1.2",
4648
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
4649
  "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
4650
+ "dev": true,
4651
  "license": "ISC",
4652
  "dependencies": {
4653
  "is-glob": "^4.0.1"
 
4674
  "version": "1.17.1",
4675
  "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
4676
  "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
4677
+ "dev": true,
4678
  "license": "ISC",
4679
  "dependencies": {
4680
  "reusify": "^1.0.4"
 
4697
  "version": "7.1.1",
4698
  "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
4699
  "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
4700
+ "dev": true,
4701
  "license": "MIT",
4702
  "dependencies": {
4703
  "to-regex-range": "^5.0.1"
 
4768
  "version": "3.3.0",
4769
  "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
4770
  "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
4771
+ "dev": true,
4772
  "license": "ISC",
4773
  "dependencies": {
4774
  "cross-spawn": "^7.0.0",
 
4840
  "version": "2.3.3",
4841
  "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
4842
  "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
4843
+ "dev": true,
4844
  "hasInstallScript": true,
4845
  "license": "MIT",
4846
  "optional": true,
 
4855
  "version": "1.1.2",
4856
  "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
4857
  "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
4858
+ "dev": true,
4859
  "license": "MIT",
4860
  "funding": {
4861
  "url": "https://github.com/sponsors/ljharb"
 
4874
  "version": "10.4.5",
4875
  "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
4876
  "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
4877
+ "dev": true,
4878
  "license": "ISC",
4879
  "dependencies": {
4880
  "foreground-child": "^3.1.0",
 
4895
  "version": "6.0.2",
4896
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
4897
  "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
4898
+ "dev": true,
4899
  "license": "ISC",
4900
  "dependencies": {
4901
  "is-glob": "^4.0.3"
 
4908
  "version": "2.0.1",
4909
  "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
4910
  "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
4911
+ "dev": true,
4912
  "license": "MIT",
4913
  "dependencies": {
4914
  "balanced-match": "^1.0.0"
 
4918
  "version": "9.0.5",
4919
  "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
4920
  "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
4921
+ "dev": true,
4922
  "license": "ISC",
4923
  "dependencies": {
4924
  "brace-expansion": "^2.0.1"
 
4943
  "url": "https://github.com/sponsors/sindresorhus"
4944
  }
4945
  },
4946
+ "node_modules/grad-school": {
4947
+ "version": "0.0.5",
4948
+ "resolved": "https://registry.npmjs.org/grad-school/-/grad-school-0.0.5.tgz",
4949
+ "integrity": "sha512-rXunEHF9M9EkMydTBux7+IryYXEZinRk6g8OBOGDBzo/qWJjhTxy86i5q7lQYpCLHN8Sqv1XX3OIOc7ka2gtvQ==",
4950
+ "license": "MIT",
4951
+ "engines": {
4952
+ "node": ">=8.0.0"
4953
+ }
4954
+ },
4955
  "node_modules/graphemer": {
4956
  "version": "1.4.0",
4957
  "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
 
4973
  "version": "2.0.2",
4974
  "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
4975
  "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
4976
+ "dev": true,
4977
  "license": "MIT",
4978
  "dependencies": {
4979
  "function-bind": "^1.1.2"
 
5051
  "version": "2.1.0",
5052
  "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
5053
  "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
5054
+ "dev": true,
5055
  "license": "MIT",
5056
  "dependencies": {
5057
  "binary-extensions": "^2.0.0"
 
5064
  "version": "2.15.1",
5065
  "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
5066
  "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
5067
+ "dev": true,
5068
  "license": "MIT",
5069
  "dependencies": {
5070
  "hasown": "^2.0.2"
 
5080
  "version": "2.1.1",
5081
  "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
5082
  "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
5083
+ "dev": true,
5084
  "license": "MIT",
5085
  "engines": {
5086
  "node": ">=0.10.0"
 
5090
  "version": "3.0.0",
5091
  "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
5092
  "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
5093
+ "dev": true,
5094
  "license": "MIT",
5095
  "engines": {
5096
  "node": ">=8"
 
5100
  "version": "4.0.3",
5101
  "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
5102
  "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
5103
+ "dev": true,
5104
  "license": "MIT",
5105
  "dependencies": {
5106
  "is-extglob": "^2.1.1"
 
5113
  "version": "7.0.0",
5114
  "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
5115
  "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
5116
+ "dev": true,
5117
  "license": "MIT",
5118
  "engines": {
5119
  "node": ">=0.12.0"
 
5123
  "version": "2.0.0",
5124
  "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
5125
  "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
5126
+ "dev": true,
5127
  "license": "ISC"
5128
  },
5129
  "node_modules/jackspeak": {
5130
  "version": "3.4.3",
5131
  "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
5132
  "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
5133
+ "dev": true,
5134
  "license": "BlueOak-1.0.0",
5135
  "dependencies": {
5136
  "@isaacs/cliui": "^8.0.2"
 
5146
  "version": "1.21.6",
5147
  "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
5148
  "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
5149
+ "dev": true,
5150
  "license": "MIT",
5151
  "bin": {
5152
  "jiti": "bin/jiti.js"
 
5220
  "version": "2.1.0",
5221
  "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
5222
  "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
5223
+ "dev": true,
5224
  "license": "MIT",
5225
  "engines": {
5226
  "node": ">=10"
 
5230
  "version": "1.2.4",
5231
  "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
5232
  "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
5233
+ "dev": true,
5234
  "license": "MIT"
5235
  },
5236
  "node_modules/locate-path": {
 
5306
  "version": "10.4.3",
5307
  "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
5308
  "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
5309
+ "dev": true,
5310
  "license": "ISC"
5311
  },
5312
  "node_modules/lucide-react": {
 
5331
  "version": "1.4.1",
5332
  "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
5333
  "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
5334
+ "dev": true,
5335
  "license": "MIT",
5336
  "engines": {
5337
  "node": ">= 8"
 
5341
  "version": "4.0.8",
5342
  "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
5343
  "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
5344
+ "dev": true,
5345
  "license": "MIT",
5346
  "dependencies": {
5347
  "braces": "^3.0.3",
 
5389
  "version": "7.1.2",
5390
  "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
5391
  "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
5392
+ "dev": true,
5393
  "license": "ISC",
5394
  "engines": {
5395
  "node": ">=16 || 14 >=14.17"
 
5421
  "version": "2.7.0",
5422
  "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
5423
  "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
5424
+ "dev": true,
5425
  "license": "MIT",
5426
  "dependencies": {
5427
  "any-promise": "^1.0.0",
 
5433
  "version": "3.3.7",
5434
  "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
5435
  "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
5436
+ "dev": true,
5437
  "funding": [
5438
  {
5439
  "type": "github",
 
5476
  "version": "3.0.0",
5477
  "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
5478
  "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
5479
+ "dev": true,
5480
  "license": "MIT",
5481
  "engines": {
5482
  "node": ">=0.10.0"
 
5505
  "version": "3.0.0",
5506
  "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
5507
  "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
5508
+ "dev": true,
5509
  "license": "MIT",
5510
  "engines": {
5511
  "node": ">= 6"
 
5565
  "version": "1.0.1",
5566
  "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
5567
  "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
5568
+ "dev": true,
5569
  "license": "BlueOak-1.0.0"
5570
  },
5571
  "node_modules/parent-module": {
 
5595
  "version": "3.1.1",
5596
  "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
5597
  "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
5598
+ "dev": true,
5599
  "license": "MIT",
5600
  "engines": {
5601
  "node": ">=8"
 
5605
  "version": "1.0.7",
5606
  "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
5607
  "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
5608
+ "dev": true,
5609
  "license": "MIT"
5610
  },
5611
  "node_modules/path-scurry": {
5612
  "version": "1.11.1",
5613
  "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
5614
  "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
5615
+ "dev": true,
5616
  "license": "BlueOak-1.0.0",
5617
  "dependencies": {
5618
  "lru-cache": "^10.2.0",
 
5629
  "version": "1.1.1",
5630
  "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
5631
  "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
5632
+ "dev": true,
5633
  "license": "ISC"
5634
  },
5635
  "node_modules/picomatch": {
5636
  "version": "2.3.1",
5637
  "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
5638
  "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
5639
+ "dev": true,
5640
  "license": "MIT",
5641
  "engines": {
5642
  "node": ">=8.6"
 
5649
  "version": "2.3.0",
5650
  "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
5651
  "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
5652
+ "dev": true,
5653
  "license": "MIT",
5654
  "engines": {
5655
  "node": ">=0.10.0"
 
5659
  "version": "4.0.6",
5660
  "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
5661
  "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
5662
+ "dev": true,
5663
  "license": "MIT",
5664
  "engines": {
5665
  "node": ">= 6"
 
5669
  "version": "8.4.47",
5670
  "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
5671
  "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
5672
+ "dev": true,
5673
  "funding": [
5674
  {
5675
  "type": "opencollective",
 
5698
  "version": "15.1.0",
5699
  "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
5700
  "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
5701
+ "dev": true,
5702
  "license": "MIT",
5703
  "dependencies": {
5704
  "postcss-value-parser": "^4.0.0",
 
5716
  "version": "4.0.1",
5717
  "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
5718
  "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
5719
+ "dev": true,
5720
  "license": "MIT",
5721
  "dependencies": {
5722
  "camelcase-css": "^2.0.1"
 
5736
  "version": "4.0.2",
5737
  "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
5738
  "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
5739
+ "dev": true,
5740
  "funding": [
5741
  {
5742
  "type": "opencollective",
 
5772
  "version": "3.1.2",
5773
  "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
5774
  "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
5775
+ "dev": true,
5776
  "license": "MIT",
5777
  "engines": {
5778
  "node": ">=14"
 
5785
  "version": "6.2.0",
5786
  "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
5787
  "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
5788
+ "dev": true,
5789
  "funding": [
5790
  {
5791
  "type": "opencollective",
 
5811
  "version": "6.1.2",
5812
  "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
5813
  "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
5814
+ "dev": true,
5815
  "license": "MIT",
5816
  "dependencies": {
5817
  "cssesc": "^3.0.0",
 
5825
  "version": "4.2.0",
5826
  "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
5827
  "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
5828
+ "dev": true,
5829
  "license": "MIT"
5830
  },
5831
  "node_modules/prelude-ls": {
 
5875
  "version": "1.2.3",
5876
  "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
5877
  "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
5878
+ "dev": true,
5879
  "funding": [
5880
  {
5881
  "type": "github",
 
6100
  "version": "1.0.0",
6101
  "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
6102
  "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
6103
+ "dev": true,
6104
  "license": "MIT",
6105
  "dependencies": {
6106
  "pify": "^2.3.0"
 
6110
  "version": "3.6.0",
6111
  "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
6112
  "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
6113
+ "dev": true,
6114
  "license": "MIT",
6115
  "dependencies": {
6116
  "picomatch": "^2.2.1"
 
6161
  "version": "1.22.8",
6162
  "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
6163
  "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
6164
+ "dev": true,
6165
  "license": "MIT",
6166
  "dependencies": {
6167
  "is-core-module": "^2.13.0",
 
6189
  "version": "1.0.4",
6190
  "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
6191
  "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
6192
+ "dev": true,
6193
  "license": "MIT",
6194
  "engines": {
6195
  "iojs": ">=1.0.0",
 
6236
  "version": "1.2.0",
6237
  "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
6238
  "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
6239
+ "dev": true,
6240
  "funding": [
6241
  {
6242
  "type": "github",
 
6282
  "version": "2.0.0",
6283
  "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
6284
  "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
6285
+ "dev": true,
6286
  "license": "MIT",
6287
  "dependencies": {
6288
  "shebang-regex": "^3.0.0"
 
6295
  "version": "3.0.0",
6296
  "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
6297
  "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
6298
+ "dev": true,
6299
  "license": "MIT",
6300
  "engines": {
6301
  "node": ">=8"
 
6305
  "version": "4.1.0",
6306
  "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
6307
  "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
6308
+ "dev": true,
6309
  "license": "ISC",
6310
  "engines": {
6311
  "node": ">=14"
 
6328
  "version": "1.2.1",
6329
  "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
6330
  "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
6331
+ "dev": true,
6332
  "license": "BSD-3-Clause",
6333
  "engines": {
6334
  "node": ">=0.10.0"
 
6338
  "version": "5.1.2",
6339
  "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
6340
  "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
6341
+ "dev": true,
6342
  "license": "MIT",
6343
  "dependencies": {
6344
  "eastasianwidth": "^0.2.0",
 
6357
  "version": "4.2.3",
6358
  "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
6359
  "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
6360
+ "dev": true,
6361
  "license": "MIT",
6362
  "dependencies": {
6363
  "emoji-regex": "^8.0.0",
 
6372
  "version": "5.0.1",
6373
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
6374
  "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
6375
+ "dev": true,
6376
  "license": "MIT",
6377
  "engines": {
6378
  "node": ">=8"
 
6382
  "version": "8.0.0",
6383
  "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
6384
  "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
6385
+ "dev": true,
6386
  "license": "MIT"
6387
  },
6388
  "node_modules/string-width-cjs/node_modules/strip-ansi": {
6389
  "version": "6.0.1",
6390
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6391
  "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
6392
+ "dev": true,
6393
  "license": "MIT",
6394
  "dependencies": {
6395
  "ansi-regex": "^5.0.1"
 
6402
  "version": "7.1.0",
6403
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
6404
  "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
6405
+ "dev": true,
6406
  "license": "MIT",
6407
  "dependencies": {
6408
  "ansi-regex": "^6.0.1"
 
6419
  "version": "6.0.1",
6420
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6421
  "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
6422
+ "dev": true,
6423
  "license": "MIT",
6424
  "dependencies": {
6425
  "ansi-regex": "^5.0.1"
 
6432
  "version": "5.0.1",
6433
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
6434
  "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
6435
+ "dev": true,
6436
  "license": "MIT",
6437
  "engines": {
6438
  "node": ">=8"
 
6455
  "version": "3.35.0",
6456
  "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
6457
  "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
6458
+ "dev": true,
6459
  "license": "MIT",
6460
  "dependencies": {
6461
  "@jridgewell/gen-mapping": "^0.3.2",
 
6474
  "node": ">=16 || 14 >=14.17"
6475
  }
6476
  },
6477
+ "node_modules/suffix-thumb": {
6478
+ "version": "5.0.2",
6479
+ "resolved": "https://registry.npmjs.org/suffix-thumb/-/suffix-thumb-5.0.2.tgz",
6480
+ "integrity": "sha512-I5PWXAFKx3FYnI9a+dQMWNqTxoRt6vdBdb0O+BJ1sxXCWtSoQCusc13E58f+9p4MYx/qCnEMkD5jac6K2j3dgA==",
6481
+ "license": "MIT"
6482
+ },
6483
  "node_modules/supports-color": {
6484
  "version": "7.2.0",
6485
  "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
 
6497
  "version": "1.0.0",
6498
  "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
6499
  "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
6500
+ "dev": true,
6501
  "license": "MIT",
6502
  "engines": {
6503
  "node": ">= 0.4"
 
6520
  "version": "3.4.14",
6521
  "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
6522
  "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
6523
+ "dev": true,
6524
  "license": "MIT",
6525
  "dependencies": {
6526
  "@alloc/quick-lru": "^5.2.0",
 
6574
  "version": "3.3.1",
6575
  "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
6576
  "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
6577
+ "dev": true,
6578
  "license": "MIT",
6579
  "dependencies": {
6580
  "any-promise": "^1.0.0"
 
6584
  "version": "1.6.0",
6585
  "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
6586
  "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
6587
+ "dev": true,
6588
  "license": "MIT",
6589
  "dependencies": {
6590
  "thenify": ">= 3.1.0 < 4"
 
6603
  "version": "5.0.1",
6604
  "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
6605
  "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
6606
+ "dev": true,
6607
  "license": "MIT",
6608
  "dependencies": {
6609
  "is-number": "^7.0.0"
 
6635
  "version": "0.1.13",
6636
  "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
6637
  "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
6638
+ "dev": true,
6639
  "license": "Apache-2.0"
6640
  },
6641
  "node_modules/tslib": {
 
6789
  "version": "1.0.2",
6790
  "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
6791
  "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
6792
+ "dev": true,
6793
  "license": "MIT"
6794
  },
6795
  "node_modules/vaul": {
 
6907
  "version": "2.0.2",
6908
  "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
6909
  "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
6910
+ "dev": true,
6911
  "license": "ISC",
6912
  "dependencies": {
6913
  "isexe": "^2.0.0"
 
6933
  "version": "8.1.0",
6934
  "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
6935
  "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
6936
+ "dev": true,
6937
  "license": "MIT",
6938
  "dependencies": {
6939
  "ansi-styles": "^6.1.0",
 
6952
  "version": "7.0.0",
6953
  "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
6954
  "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
6955
+ "dev": true,
6956
  "license": "MIT",
6957
  "dependencies": {
6958
  "ansi-styles": "^4.0.0",
 
6970
  "version": "5.0.1",
6971
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
6972
  "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
6973
+ "dev": true,
6974
  "license": "MIT",
6975
  "engines": {
6976
  "node": ">=8"
 
6980
  "version": "8.0.0",
6981
  "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
6982
  "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
6983
+ "dev": true,
6984
  "license": "MIT"
6985
  },
6986
  "node_modules/wrap-ansi-cjs/node_modules/string-width": {
6987
  "version": "4.2.3",
6988
  "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
6989
  "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
6990
+ "dev": true,
6991
  "license": "MIT",
6992
  "dependencies": {
6993
  "emoji-regex": "^8.0.0",
 
7002
  "version": "6.0.1",
7003
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
7004
  "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
7005
+ "dev": true,
7006
  "license": "MIT",
7007
  "dependencies": {
7008
  "ansi-regex": "^5.0.1"
 
7015
  "version": "6.2.1",
7016
  "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
7017
  "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
7018
+ "dev": true,
7019
  "license": "MIT",
7020
  "engines": {
7021
  "node": ">=12"
 
7049
  "version": "2.6.0",
7050
  "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
7051
  "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
7052
+ "dev": true,
7053
  "license": "ISC",
7054
  "bin": {
7055
  "yaml": "bin.mjs"
package.json CHANGED
@@ -46,6 +46,7 @@
46
  "class-variance-authority": "^0.7.1",
47
  "clsx": "^2.1.1",
48
  "cmdk": "^1.0.0",
 
49
  "date-fns": "^3.6.0",
50
  "embla-carousel-react": "^8.3.0",
51
  "framer-motion": "^12.0.5",
 
46
  "class-variance-authority": "^0.7.1",
47
  "clsx": "^2.1.1",
48
  "cmdk": "^1.0.0",
49
+ "compromise": "^14.12.0",
50
  "date-fns": "^3.6.0",
51
  "embla-carousel-react": "^8.3.0",
52
  "framer-motion": "^12.0.5",
src/components/GameContainer.tsx CHANGED
@@ -1,7 +1,7 @@
1
  import { useState, KeyboardEvent, useEffect, useContext } from "react";
2
  import { useSearchParams, useParams, useNavigate, useLocation } from "react-router-dom";
3
  import { motion } from "framer-motion";
4
- import { generateAIResponse, guessWord } from "@/services/mistralService";
5
  import { createGame, createSession } from "@/services/gameService";
6
  import { getDailyGame } from "@/services/dailyGameService";
7
  import { useToast } from "@/components/ui/use-toast";
@@ -15,17 +15,10 @@ import { useTranslation } from "@/hooks/useTranslation";
15
  import { LanguageContext } from "@/contexts/LanguageContext";
16
  import { supabase } from "@/integrations/supabase/client";
17
  import { Language } from "@/i18n/translations";
 
18
 
19
  type GameState = "welcome" | "theme-selection" | "building-sentence" | "showing-guess" | "game-review" | "invitation";
20
 
21
- const normalizeWord = (word: string): string => {
22
- return word.normalize('NFD')
23
- .replace(/[\u0300-\u036f]/g, '')
24
- .toLowerCase()
25
- .replace(/[^a-z]/g, '')
26
- .trim();
27
- };
28
-
29
  export const GameContainer = () => {
30
  const [searchParams] = useSearchParams();
31
  const { gameId: urlGameId } = useParams();
@@ -43,6 +36,7 @@ export const GameContainer = () => {
43
  const [sentence, setSentence] = useState<string[]>([]);
44
  const [isAiThinking, setIsAiThinking] = useState(false);
45
  const [aiGuess, setAiGuess] = useState<string>("");
 
46
  const [successfulRounds, setSuccessfulRounds] = useState<number>(0);
47
  const [totalWordsInSuccessfulRounds, setTotalWordsInSuccessfulRounds] = useState<number>(0);
48
  const { toast } = useToast();
@@ -230,7 +224,7 @@ export const GameContainer = () => {
230
  }
231
  };
232
 
233
- const saveGameResult = async (sentenceString: string, aiGuess: string, isCorrect: boolean) => {
234
  try {
235
  const { error } = await supabase
236
  .from('game_results')
@@ -239,7 +233,8 @@ export const GameContainer = () => {
239
  description: sentenceString,
240
  ai_guess: aiGuess,
241
  is_correct: isCorrect,
242
- session_id: sessionId
 
243
  });
244
 
245
  if (error) {
@@ -265,16 +260,17 @@ export const GameContainer = () => {
265
  if (finalSentence.length === 0) return;
266
 
267
  const sentenceString = finalSentence.join(' ');
268
- const guess = await guessWord(sentenceString, language);
269
  setAiGuess(guess);
 
270
 
271
- const isCorrect = normalizeWord(guess) === normalizeWord(currentWord);
272
 
273
  if (isCorrect) {
274
  setTotalWordsInSuccessfulRounds(prev => prev + finalSentence.length);
275
  }
276
 
277
- await saveGameResult(sentenceString, guess, isCorrect);
278
  setGameState("showing-guess");
279
  } catch (error) {
280
  console.error('Error getting AI guess:', error);
@@ -335,7 +331,7 @@ export const GameContainer = () => {
335
  }
336
 
337
  const isGuessCorrect = () => {
338
- return normalizeWord(aiGuess) === normalizeWord(currentWord);
339
  };
340
 
341
  const getAverageWordsPerSuccessfulRound = () => {
@@ -366,7 +362,7 @@ export const GameContainer = () => {
366
  onInputChange={setPlayerInput}
367
  onSubmitWord={handlePlayerWord}
368
  onMakeGuess={handleMakeGuess}
369
- normalizeWord={normalizeWord}
370
  onBack={handleBack}
371
  onClose={handleBack}
372
  />
@@ -382,7 +378,7 @@ export const GameContainer = () => {
382
  avgWordsPerRound={getAverageWordsPerSuccessfulRound()}
383
  sessionId={sessionId}
384
  currentTheme={currentTheme}
385
- normalizeWord={normalizeWord}
386
  />
387
  ) : (
388
  <GameReview
 
1
  import { useState, KeyboardEvent, useEffect, useContext } from "react";
2
  import { useSearchParams, useParams, useNavigate, useLocation } from "react-router-dom";
3
  import { motion } from "framer-motion";
4
+ import { generateAIResponse, guessWord } from "@/services/aiService";
5
  import { createGame, createSession } from "@/services/gameService";
6
  import { getDailyGame } from "@/services/dailyGameService";
7
  import { useToast } from "@/components/ui/use-toast";
 
15
  import { LanguageContext } from "@/contexts/LanguageContext";
16
  import { supabase } from "@/integrations/supabase/client";
17
  import { Language } from "@/i18n/translations";
18
+ import { normalizeWord } from "@/lib/wordProcessing";
19
 
20
  type GameState = "welcome" | "theme-selection" | "building-sentence" | "showing-guess" | "game-review" | "invitation";
21
 
 
 
 
 
 
 
 
 
22
  export const GameContainer = () => {
23
  const [searchParams] = useSearchParams();
24
  const { gameId: urlGameId } = useParams();
 
36
  const [sentence, setSentence] = useState<string[]>([]);
37
  const [isAiThinking, setIsAiThinking] = useState(false);
38
  const [aiGuess, setAiGuess] = useState<string>("");
39
+ const [aiModel, setAiModel] = useState<string>("");
40
  const [successfulRounds, setSuccessfulRounds] = useState<number>(0);
41
  const [totalWordsInSuccessfulRounds, setTotalWordsInSuccessfulRounds] = useState<number>(0);
42
  const { toast } = useToast();
 
224
  }
225
  };
226
 
227
+ const saveGameResult = async (sentenceString: string, aiGuess: string, isCorrect: boolean, model: string) => {
228
  try {
229
  const { error } = await supabase
230
  .from('game_results')
 
233
  description: sentenceString,
234
  ai_guess: aiGuess,
235
  is_correct: isCorrect,
236
+ session_id: sessionId,
237
+ model_used: model
238
  });
239
 
240
  if (error) {
 
260
  if (finalSentence.length === 0) return;
261
 
262
  const sentenceString = finalSentence.join(' ');
263
+ const { guess, model } = await guessWord(sentenceString, language);
264
  setAiGuess(guess);
265
+ setAiModel(model);
266
 
267
+ const isCorrect = normalizeWord(guess, language) === normalizeWord(currentWord, language);
268
 
269
  if (isCorrect) {
270
  setTotalWordsInSuccessfulRounds(prev => prev + finalSentence.length);
271
  }
272
 
273
+ await saveGameResult(sentenceString, guess, isCorrect, model);
274
  setGameState("showing-guess");
275
  } catch (error) {
276
  console.error('Error getting AI guess:', error);
 
331
  }
332
 
333
  const isGuessCorrect = () => {
334
+ return normalizeWord(aiGuess, language) === normalizeWord(currentWord, language);
335
  };
336
 
337
  const getAverageWordsPerSuccessfulRound = () => {
 
362
  onInputChange={setPlayerInput}
363
  onSubmitWord={handlePlayerWord}
364
  onMakeGuess={handleMakeGuess}
365
+ normalizeWord={(word: string) => normalizeWord(word, language)}
366
  onBack={handleBack}
367
  onClose={handleBack}
368
  />
 
378
  avgWordsPerRound={getAverageWordsPerSuccessfulRound()}
379
  sessionId={sessionId}
380
  currentTheme={currentTheme}
381
+ normalizeWord={(word: string) => normalizeWord(word, language)}
382
  />
383
  ) : (
384
  <GameReview
src/components/game/WelcomeScreen.tsx CHANGED
@@ -1,5 +1,6 @@
 
1
  import { motion } from "framer-motion";
2
- import { useEffect, useState } from "react";
3
  import { HighScoreBoard } from "../HighScoreBoard";
4
  import { Dialog, DialogContent } from "@/components/ui/dialog";
5
  import { LanguageSelector } from "./LanguageSelector";
@@ -10,6 +11,7 @@ import { MainActions } from "./welcome/MainActions";
10
  import { HowToPlayDialog } from "./welcome/HowToPlayDialog";
11
  import { CreditsDialog } from "./welcome/CreditsDialog";
12
  import { Mail } from "lucide-react";
 
13
 
14
  interface WelcomeScreenProps {
15
  onStartDaily: () => void;
@@ -20,19 +22,9 @@ export const WelcomeScreen = ({ onStartDaily, onStartNew }: WelcomeScreenProps)
20
  const [showHighScores, setShowHighScores] = useState(false);
21
  const [showHowToPlay, setShowHowToPlay] = useState(false);
22
  const [showCredits, setShowCredits] = useState(false);
 
23
  const t = useTranslation();
24
 
25
- useEffect(() => {
26
- const handleKeyPress = (e: KeyboardEvent) => {
27
- if (e.key === 'Enter') {
28
- onStartDaily()
29
- }
30
- };
31
-
32
- window.addEventListener('keydown', handleKeyPress);
33
- return () => window.removeEventListener('keydown', handleKeyPress);
34
- }, [onStartDaily]);
35
-
36
  return (
37
  <>
38
  <motion.div
@@ -81,6 +73,13 @@ export const WelcomeScreen = ({ onStartDaily, onStartNew }: WelcomeScreenProps)
81
  <Mail className="w-4 h-4" />
82
  <span>Feedback</span>
83
  </a>
 
 
 
 
 
 
 
84
  </div>
85
  </div>
86
  </motion.div>
@@ -103,6 +102,11 @@ export const WelcomeScreen = ({ onStartDaily, onStartNew }: WelcomeScreenProps)
103
  open={showCredits}
104
  onOpenChange={setShowCredits}
105
  />
 
 
 
 
 
106
  </>
107
  );
108
- };
 
1
+
2
  import { motion } from "framer-motion";
3
+ import { useState } from "react";
4
  import { HighScoreBoard } from "../HighScoreBoard";
5
  import { Dialog, DialogContent } from "@/components/ui/dialog";
6
  import { LanguageSelector } from "./LanguageSelector";
 
11
  import { HowToPlayDialog } from "./welcome/HowToPlayDialog";
12
  import { CreditsDialog } from "./welcome/CreditsDialog";
13
  import { Mail } from "lucide-react";
14
+ import { StatsDialog } from "./welcome/StatsDialog";
15
 
16
  interface WelcomeScreenProps {
17
  onStartDaily: () => void;
 
22
  const [showHighScores, setShowHighScores] = useState(false);
23
  const [showHowToPlay, setShowHowToPlay] = useState(false);
24
  const [showCredits, setShowCredits] = useState(false);
25
+ const [showStats, setShowStats] = useState(false);
26
  const t = useTranslation();
27
 
 
 
 
 
 
 
 
 
 
 
 
28
  return (
29
  <>
30
  <motion.div
 
73
  <Mail className="w-4 h-4" />
74
  <span>Feedback</span>
75
  </a>
76
+ <span>•</span>
77
+ <button
78
+ onClick={() => setShowStats(true)}
79
+ className="text-primary hover:text-primary/80 transition-colors"
80
+ >
81
+ {t.welcome.stats.title}
82
+ </button>
83
  </div>
84
  </div>
85
  </motion.div>
 
102
  open={showCredits}
103
  onOpenChange={setShowCredits}
104
  />
105
+
106
+ <StatsDialog
107
+ open={showStats}
108
+ onOpenChange={setShowStats}
109
+ />
110
  </>
111
  );
112
+ };
src/components/game/welcome/CreditsDialog.tsx CHANGED
@@ -1,3 +1,4 @@
 
1
  import { Dialog, DialogContent } from "@/components/ui/dialog";
2
 
3
  interface CreditsDialogProps {
@@ -12,18 +13,16 @@ export const CreditsDialog = ({ open, onOpenChange }: CreditsDialogProps) => {
12
  <h2 className="text-2xl font-bold mb-4">Credits</h2>
13
  <div className="space-y-2 text-gray-600">
14
  <p>
15
- Made with ❤️ by the M1X team:
 
 
 
 
 
 
16
  </p>
17
- <div className="space-y-1">
18
- <a href="https://www.linkedin.com/in/sandro-mikautadze/" target="_blank" rel="noopener noreferrer" className="block text-primary hover:underline">Sandro</a>
19
- <a href="https://www.linkedin.com/in/alessandro-pranzo/" target="_blank" rel="noopener noreferrer" className="block text-primary hover:underline">Alessandro</a>
20
- <a href="https://www.linkedin.com/in/mattia-martino-528363225/" target="_blank" rel="noopener noreferrer" className="block text-primary hover:underline">Mattia</a>
21
- <a href="https://www.linkedin.com/in/michael-sheroubi/" target="_blank" rel="noopener noreferrer" className="block text-primary hover:underline">Michael</a>
22
- <a href="https://www.linkedin.com/in/michael-sheroubi/" target="_blank" rel="noopener noreferrer" className="block text-primary hover:underline">Emiliano</a>
23
- <a href="https://felixzieger.de/" target="_blank" rel="noopener noreferrer" className="block text-primary hover:underline">Felix</a>
24
- </div>
25
  </div>
26
  </DialogContent>
27
  </Dialog>
28
  );
29
- };
 
1
+
2
  import { Dialog, DialogContent } from "@/components/ui/dialog";
3
 
4
  interface CreditsDialogProps {
 
13
  <h2 className="text-2xl font-bold mb-4">Credits</h2>
14
  <div className="space-y-2 text-gray-600">
15
  <p>
16
+ Made by M1X. We are{" "}
17
+ <a href="https://www.linkedin.com/in/sandro-mikautadze/" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">Sandro</a>,{" "}
18
+ <a href="https://www.linkedin.com/in/alessandro-pranzo/" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">Alessandro</a>,{" "}
19
+ <a href="https://www.linkedin.com/in/mattia-martino-528363225/" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">Mattia</a>,{" "}
20
+ <a href="https://www.linkedin.com/in/michael-sheroubi/" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">Michael</a>,{" "}
21
+ <a href="https://www.linkedin.com/in/michael-sheroubi/" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">Emiliano</a>,{" "}
22
+ and <a href="https://felixzieger.de/" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">Felix</a>.
23
  </p>
 
 
 
 
 
 
 
 
24
  </div>
25
  </DialogContent>
26
  </Dialog>
27
  );
28
+ };
src/components/game/welcome/StatsDialog.tsx ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import { Dialog, DialogContent } from "@/components/ui/dialog";
3
+ import { useTranslation } from "@/hooks/useTranslation";
4
+ import { ExternalLink } from "lucide-react";
5
+ import { useQuery } from "@tanstack/react-query";
6
+ import { supabase } from "@/integrations/supabase/client";
7
+
8
+ export const StatsDialog = ({
9
+ open,
10
+ onOpenChange,
11
+ }: {
12
+ open: boolean;
13
+ onOpenChange: (open: boolean) => void;
14
+ }) => {
15
+ const t = useTranslation();
16
+
17
+ const { data: todayResults } = useQuery({
18
+ queryKey: ["game-results-today"],
19
+ queryFn: async () => {
20
+ const today = new Date();
21
+ today.setHours(0, 0, 0, 0);
22
+
23
+ const { count } = await supabase
24
+ .from("game_results")
25
+ .select("*", { count: "exact" })
26
+ .gte("created_at", today.toISOString());
27
+
28
+ return count || 0;
29
+ },
30
+ });
31
+
32
+ const { data: totalResults } = useQuery({
33
+ queryKey: ["game-results-total"],
34
+ queryFn: async () => {
35
+ const { count } = await supabase
36
+ .from("game_results")
37
+ .select("*", { count: "exact" });
38
+
39
+ return count || 0;
40
+ },
41
+ });
42
+
43
+ return (
44
+ <Dialog open={open} onOpenChange={onOpenChange}>
45
+ <DialogContent>
46
+ <div className="space-y-4">
47
+ <div>
48
+ <h3 className="font-semibold text-lg">{t.welcome.stats.title}</h3>
49
+ </div>
50
+ <div className="space-y-2">
51
+ <p>
52
+ {t.welcome.stats.dailyGuesses}: {todayResults || 0}
53
+ </p>
54
+ <p>
55
+ {t.welcome.stats.totalGuesses}: {totalResults || 0}
56
+ </p>
57
+ </div>
58
+ <div>
59
+ <a
60
+ href="https://plausible.sonnenhof-zieger.de/think-in-sync.com"
61
+ target="_blank"
62
+ rel="noopener noreferrer"
63
+ className="inline-flex items-center gap-2 text-primary hover:text-primary/80 transition-colors"
64
+ >
65
+ {t.welcome.stats.visitDashboard}
66
+ <ExternalLink className="w-4 h-4" />
67
+ </a>
68
+ </div>
69
+ </div>
70
+ </DialogContent>
71
+ </Dialog>
72
+ );
73
+ };
src/i18n/translations/de.ts CHANGED
@@ -133,6 +133,12 @@ export const de = {
133
  leaderboard: "Bestenliste",
134
  credits: "Erstellt während des",
135
  likeGameText: "Wenn du dieses Spiel unterstützen möchtest",
 
 
 
 
 
 
136
  contest: {
137
  prize: "Wir kochen etwas...",
138
  terms: "Erfahre mehr",
@@ -175,4 +181,4 @@ export const de = {
175
  ]
176
  }
177
  }
178
- };
 
133
  leaderboard: "Bestenliste",
134
  credits: "Erstellt während des",
135
  likeGameText: "Wenn du dieses Spiel unterstützen möchtest",
136
+ stats: {
137
+ title: "Statistiken",
138
+ dailyGuesses: "Heute erratene Wörter",
139
+ totalGuesses: "Insgesamt erratene Wörter",
140
+ visitDashboard: "Dashboard besuchen"
141
+ },
142
  contest: {
143
  prize: "Wir kochen etwas...",
144
  terms: "Erfahre mehr",
 
181
  ]
182
  }
183
  }
184
+ };
src/i18n/translations/en.ts CHANGED
@@ -132,6 +132,12 @@ export const en = {
132
  leaderboard: "Leaderboard",
133
  credits: "Created during the",
134
  likeGameText: "If you want to support this game",
 
 
 
 
 
 
135
  contest: {
136
  prize: "We are cooking something...",
137
  terms: "Find out more",
@@ -174,4 +180,4 @@ export const en = {
174
  ]
175
  }
176
  }
177
- };
 
132
  leaderboard: "Leaderboard",
133
  credits: "Created during the",
134
  likeGameText: "If you want to support this game",
135
+ stats: {
136
+ title: "Statistics",
137
+ dailyGuesses: "Words guessed today",
138
+ totalGuesses: "Total words guessed",
139
+ visitDashboard: "Visit Dashboard"
140
+ },
141
  contest: {
142
  prize: "We are cooking something...",
143
  terms: "Find out more",
 
180
  ]
181
  }
182
  }
183
+ };
src/i18n/translations/es.ts CHANGED
@@ -133,6 +133,12 @@ export const es = {
133
  leaderboard: "Clasificación",
134
  credits: "Creado durante el",
135
  likeGameText: "Si quieres apoyar este juego",
 
 
 
 
 
 
136
  contest: {
137
  prize: "Estamos cocinando algo...",
138
  terms: "Descubre más",
@@ -175,4 +181,4 @@ export const es = {
175
  ]
176
  }
177
  }
178
- };
 
133
  leaderboard: "Clasificación",
134
  credits: "Creado durante el",
135
  likeGameText: "Si quieres apoyar este juego",
136
+ stats: {
137
+ title: "Estadísticas",
138
+ dailyGuesses: "Palabras adivinadas hoy",
139
+ totalGuesses: "Total de palabras adivinadas",
140
+ visitDashboard: "Visitar Dashboard"
141
+ },
142
  contest: {
143
  prize: "Estamos cocinando algo...",
144
  terms: "Descubre más",
 
181
  ]
182
  }
183
  }
184
+ };
src/i18n/translations/fr.ts CHANGED
@@ -132,6 +132,12 @@ export const fr = {
132
  leaderboard: "Classement",
133
  credits: "Créé pendant le",
134
  likeGameText: "Si vous voulez soutenir ce jeu,",
 
 
 
 
 
 
135
  contest: {
136
  prize: "Nous préparons quelque chose...",
137
  terms: "En savoir plus",
@@ -174,4 +180,4 @@ export const fr = {
174
  ]
175
  }
176
  }
177
- };
 
132
  leaderboard: "Classement",
133
  credits: "Créé pendant le",
134
  likeGameText: "Si vous voulez soutenir ce jeu,",
135
+ stats: {
136
+ title: "Statistiques",
137
+ dailyGuesses: "Mots devinés aujourd'hui",
138
+ totalGuesses: "Total des mots devinés",
139
+ visitDashboard: "Visiter le Dashboard"
140
+ },
141
  contest: {
142
  prize: "Nous préparons quelque chose...",
143
  terms: "En savoir plus",
 
180
  ]
181
  }
182
  }
183
+ };
src/i18n/translations/it.ts CHANGED
@@ -134,6 +134,12 @@ export const it = {
134
  leaderboard: "Classifica",
135
  credits: "Creato durante il",
136
  likeGameText: "Se vuoi supportare questo gioco",
 
 
 
 
 
 
137
  contest: {
138
  prize: "Stiamo preparando qualcosa...",
139
  terms: "Scopri di più",
@@ -176,4 +182,4 @@ export const it = {
176
  ]
177
  }
178
  }
179
- };
 
134
  leaderboard: "Classifica",
135
  credits: "Creato durante il",
136
  likeGameText: "Se vuoi supportare questo gioco",
137
+ stats: {
138
+ title: "Statistiche",
139
+ dailyGuesses: "Parole indovinate oggi",
140
+ totalGuesses: "Totale parole indovinate",
141
+ visitDashboard: "Visita il Dashboard"
142
+ },
143
  contest: {
144
  prize: "Stiamo preparando qualcosa...",
145
  terms: "Scopri di più",
 
182
  ]
183
  }
184
  }
185
+ };
src/i18n/translations/pt.ts CHANGED
@@ -1,3 +1,4 @@
 
1
  export const pt = {
2
  game: {
3
  title: "Think in Sync",
@@ -133,6 +134,12 @@ export const pt = {
133
  leaderboard: "Placar",
134
  credits: "Criado durante o",
135
  likeGameText: "Se você quiser apoiar este jogo",
 
 
 
 
 
 
136
  contest: {
137
  prize: "Estamos preparando algo...",
138
  terms: "Descubra mais",
 
1
+
2
  export const pt = {
3
  game: {
4
  title: "Think in Sync",
 
134
  leaderboard: "Placar",
135
  credits: "Criado durante o",
136
  likeGameText: "Se você quiser apoiar este jogo",
137
+ stats: {
138
+ title: "Estatísticas",
139
+ dailyGuesses: "Palavras adivinhadas hoje",
140
+ totalGuesses: "Total de palavras adivinhadas",
141
+ visitDashboard: "Visitar Dashboard"
142
+ },
143
  contest: {
144
  prize: "Estamos preparando algo...",
145
  terms: "Descubra mais",
src/integrations/supabase/types.ts CHANGED
@@ -45,6 +45,7 @@ export type Database = {
45
  description: string
46
  id: string
47
  is_correct: boolean
 
48
  session_id: string
49
  target_word: string
50
  }
@@ -54,6 +55,7 @@ export type Database = {
54
  description: string
55
  id?: string
56
  is_correct: boolean
 
57
  session_id?: string
58
  target_word: string
59
  }
@@ -63,6 +65,7 @@ export type Database = {
63
  description?: string
64
  id?: string
65
  is_correct?: boolean
 
66
  session_id?: string
67
  target_word?: string
68
  }
@@ -138,16 +141,19 @@ export type Database = {
138
  created_at: string
139
  game_id: string
140
  id: string
 
141
  }
142
  Insert: {
143
  created_at?: string
144
  game_id: string
145
  id?: string
 
146
  }
147
  Update: {
148
  created_at?: string
149
  game_id?: string
150
  id?: string
 
151
  }
152
  Relationships: [
153
  {
 
45
  description: string
46
  id: string
47
  is_correct: boolean
48
+ model_used: string | null
49
  session_id: string
50
  target_word: string
51
  }
 
55
  description: string
56
  id?: string
57
  is_correct: boolean
58
+ model_used?: string | null
59
  session_id?: string
60
  target_word: string
61
  }
 
65
  description?: string
66
  id?: string
67
  is_correct?: boolean
68
+ model_used?: string | null
69
  session_id?: string
70
  target_word?: string
71
  }
 
141
  created_at: string
142
  game_id: string
143
  id: string
144
+ lives: number
145
  }
146
  Insert: {
147
  created_at?: string
148
  game_id: string
149
  id?: string
150
+ lives?: number
151
  }
152
  Update: {
153
  created_at?: string
154
  game_id?: string
155
  id?: string
156
+ lives?: number
157
  }
158
  Relationships: [
159
  {
src/lib/wordProcessing.ts ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import nlp from 'compromise';
3
+
4
+ export const normalizeWord = (word: string, language: string = 'en'): string => {
5
+ let processedWord = word;
6
+
7
+ // Only apply compromise for English
8
+ if (language === 'en') {
9
+ const doc = nlp(word);
10
+ processedWord = doc.nouns().toSingular().out('text');
11
+
12
+ // Handle cases where compromise doesn't produce output
13
+ if (!processedWord) {
14
+ processedWord = word;
15
+ }
16
+ }
17
+
18
+ // Apply standard normalization for all languages
19
+ return processedWord
20
+ .normalize('NFD')
21
+ .replace(/[\u0300-\u036f]/g, '')
22
+ .toLowerCase()
23
+ .replace(/[^a-z]/g, '')
24
+ .trim();
25
+ };
src/lib/words-standard.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { portugueseFoodWords } from "./words-food";
2
-
3
  export const englishWords = [
4
  "DOG",
5
  "CAT",
@@ -81,7 +79,7 @@ export const englishWords = [
81
  "BRUSH",
82
  "TOOTH",
83
  "HAND",
84
- "FEET",
85
  "EYE",
86
  "NOSE",
87
  "EAR",
@@ -114,7 +112,6 @@ export const englishWords = [
114
  "TELEVISION",
115
  "RADIO",
116
  "BATTERY",
117
- "CANDLE",
118
  "FENCE",
119
  "MAILBOX",
120
  "BRICK",
@@ -161,7 +158,7 @@ export const englishWords = [
161
  "HAT",
162
  "CAP",
163
  "MASK",
164
- "SUNGALASSES",
165
  "WATCH",
166
  "NECKLACE",
167
  "BRACELET",
@@ -180,14 +177,11 @@ export const englishWords = [
180
  "SLEEPINGBAG",
181
  "PICNIC",
182
  "BENCH",
183
- "FENCE",
184
  "GATE",
185
  "SIGN",
186
  "CROSSWALK",
187
  "TRAFFICLIGHT",
188
  "SIDEWALK",
189
- "LANTERN",
190
- "BALLOON",
191
  "POSTCARD",
192
  "STAMP",
193
  "LETTER",
@@ -195,7 +189,6 @@ export const englishWords = [
195
  "PARKING",
196
  "STREET",
197
  "HIGHWAY",
198
- "BRIDGE",
199
  "TUNNEL",
200
  "STATUE",
201
  "FOUNTAIN",
@@ -209,7 +202,6 @@ export const englishWords = [
209
  "TELESCOPE",
210
  "MICROSCOPE",
211
  "MAGNET",
212
- "BATTERY",
213
  "BULB",
214
  "SOCKET",
215
  "PLUG",
@@ -225,7 +217,73 @@ export const englishWords = [
225
  "SPEAKER",
226
  "HEADPHONE",
227
  "PHONE",
228
- "CAMERA"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  ];
230
  export const germanWords = [
231
  "HUND",
@@ -308,7 +366,7 @@ export const germanWords = [
308
  "PINSEL",
309
  "ZAHN",
310
  "HAND",
311
- "FÜSSE",
312
  "AUGE",
313
  "NASE",
314
  "OHR",
@@ -341,7 +399,6 @@ export const germanWords = [
341
  "FERNSEHER",
342
  "RADIO",
343
  "BATTERIE",
344
- "KERZE", // duplicate
345
  "ZAUN",
346
  "BRIEFKASTEN",
347
  "BACKSTEIN",
@@ -359,7 +416,6 @@ export const germanWords = [
359
  "TROCKNER",
360
  "OFEN",
361
  "VENTILATOR",
362
- "PINSEL", // paintbrush (same as index 78 but used for “brush” too)
363
  "EIMER",
364
  "SCHWAMM",
365
  "SEIFE",
@@ -385,11 +441,9 @@ export const germanWords = [
385
  "SOCKE",
386
  "STIEFEL",
387
  "SANDALE",
388
- "HUT", // duplicate
389
  "MÜTZE",
390
  "MASKE",
391
  "SONNENBRILLE",
392
- "UHR",
393
  "HALSKETTE",
394
  "ARMBAND",
395
  "RING",
@@ -407,14 +461,11 @@ export const germanWords = [
407
  "SCHLAFSACK",
408
  "PICKNICK",
409
  "BANK",
410
- "ZAUN", // duplicate
411
  "TOR",
412
  "SCHILD",
413
  "ZEBRASTREIFEN",
414
  "VERKEHRSAMPEL",
415
  "BÜRGERSTEIG",
416
- "LATERNE", // duplicate
417
- "BALLON", // duplicate
418
  "POSTKARTE",
419
  "BRIEFMARKE",
420
  "BRIEF",
@@ -422,7 +473,6 @@ export const germanWords = [
422
  "PARKPLATZ",
423
  "STRAßE",
424
  "AUTOBAHN",
425
- "BRÜCKE", // duplicate
426
  "TUNNEL",
427
  "STATUE",
428
  "BRUNNEN",
@@ -436,7 +486,6 @@ export const germanWords = [
436
  "TELESKOP",
437
  "MIKROSKOP",
438
  "MAGNET",
439
- "BATTERIE", // duplicate
440
  "GLÜHBIRNE",
441
  "STECKDOSE",
442
  "STECKER",
@@ -535,7 +584,7 @@ export const frenchWords = [
535
  "PINCEAU",
536
  "DENT",
537
  "MAIN",
538
- "PIEDS",
539
  "ŒIL",
540
  "NEZ",
541
  "OREILLE",
@@ -568,7 +617,6 @@ export const frenchWords = [
568
  "TÉLÉVISION",
569
  "RADIO",
570
  "PILE",
571
- "BOUGIE", // duplicate
572
  "CLÔTURE",
573
  "BRIQUE",
574
  "LANTERNE",
@@ -585,7 +633,6 @@ export const frenchWords = [
585
  "SÈCHE-LINGE",
586
  "FOURNAISE",
587
  "VENTILATEUR",
588
- "PINCEAU", // paintbrush
589
  "SEAU",
590
  "ÉPONGE",
591
  "SAVON",
@@ -610,7 +657,6 @@ export const frenchWords = [
610
  "CHAUSSETTE",
611
  "BOTTE",
612
  "SANDALE",
613
- "CHAPEAU", // duplicate
614
  "CASQUETTE",
615
  "MASQUE",
616
  "MONTRE",
@@ -626,19 +672,15 @@ export const frenchWords = [
626
  "TENTE",
627
  "PIQUE-NIQUE",
628
  "BANC",
629
- "CLÔTURE", // duplicate
630
  "PORTAIL",
631
  "PANNEAU",
632
  "TROTTOIR",
633
- "LANTERNE", // duplicate
634
- "BALLON", // duplicate
635
  "TIMBRE",
636
  "LETTRE",
637
  "ENVELOPPE",
638
  "PARKING",
639
  "RUE",
640
  "AUTOROUTE",
641
- "PONT", // duplicate
642
  "TUNNEL",
643
  "STATUE",
644
  "FONTAINE",
@@ -652,11 +694,9 @@ export const frenchWords = [
652
  "TÉLESCOPE",
653
  "MICROSCOPE",
654
  "AIMANT",
655
- "PILE", // duplicate
656
  "AMPOULE",
657
  "PRISE",
658
  "FICHE",
659
- "FIL",
660
  "INTERRUPTEUR",
661
  "CIRCUIT",
662
  "ROBOT",
@@ -717,8 +757,8 @@ export const italianWords = [
717
  "AEREO",
718
  "TRENO",
719
  "CARAMELLA",
720
- "AQUILONE",
721
- "PALLONCINO",
722
  "PARCO",
723
  "SPIAGGIA",
724
  "GIOCATTOLO",
@@ -748,10 +788,10 @@ export const italianWords = [
748
  "NIDO",
749
  "ROCCIA",
750
  "FOGLIA",
751
- "PENNELLO",
752
  "DENTE",
753
  "MANO",
754
- "PIEDI",
755
  "OCCHIO",
756
  "NASO",
757
  "ORECCHIO",
@@ -784,7 +824,6 @@ export const italianWords = [
784
  "TELEVISIONE",
785
  "RADIO",
786
  "BATTERIA",
787
- "CANDELA", // duplicate
788
  "RECINTO",
789
  "MATTONE",
790
  "LANTERNA",
@@ -801,7 +840,7 @@ export const italianWords = [
801
  "ASCIUGATRICE",
802
  "FORNO",
803
  "VENTILATORE",
804
- "PENNELLO", // paintbrush
805
  "SECCHIO",
806
  "SPUGNA",
807
  "SAPONE",
@@ -818,16 +857,14 @@ export const italianWords = [
818
  "MOFFOLA",
819
  "SCIARPA",
820
  "GUANTO",
821
- "PANTALONI",
822
  "CAMICIA",
823
  "GIACCA",
824
  "VESTITO",
825
  "GONNA",
826
  "CALZINO",
827
- "STIVALE", // corrected translation for BOOT
828
  "SANDALO",
829
- "CAPPELLO", // duplicate
830
- "BERRETTO", // instead of MÜTZE, let's keep it consistent in Italian
831
  "MASCHERA",
832
  "OROLOGIO",
833
  "COLLANA",
@@ -845,13 +882,10 @@ export const italianWords = [
845
  "TENDA",
846
  "PICNIC",
847
  "PANCHINA",
848
- "RECINTO", // duplicate
849
  "CANCELLO",
850
  "SEGNALE",
851
  "SEMAFORO",
852
  "MARCIAPIEDE",
853
- "LANTERNA", // duplicate
854
- "PALLONCINO", // duplicate
855
  "CARTOLINA",
856
  "FRANCOBOLLO",
857
  "LETTERA",
@@ -859,7 +893,6 @@ export const italianWords = [
859
  "PARCHEGGIO",
860
  "STRADA",
861
  "AUTOSTRADA",
862
- "PONTE", // duplicate
863
  "TUNNEL",
864
  "STATUA",
865
  "FONTANA",
@@ -873,7 +906,6 @@ export const italianWords = [
873
  "TELESCOPIO",
874
  "MICROSCOPIO",
875
  "MAGNETE",
876
- "BATTERIA", // duplicate
877
  "LAMPADINA",
878
  "PRESA",
879
  "SPINA",
@@ -1004,7 +1036,6 @@ export const spanishWords = [
1004
  "TELEVISIÓN",
1005
  "RADIO",
1006
  "BATERÍA",
1007
- "VELA", // duplicate
1008
  "VALLA",
1009
  "BUZÓN",
1010
  "LADRILLO",
@@ -1022,7 +1053,6 @@ export const spanishWords = [
1022
  "SECADORA",
1023
  "HORNO",
1024
  "VENTILADOR",
1025
- "PINCEL", // paintbrush
1026
  "CUBO",
1027
  "ESPONJA",
1028
  "JABÓN",
@@ -1030,7 +1060,6 @@ export const spanishWords = [
1030
  "TELA",
1031
  "TIJERAS",
1032
  "CINTA",
1033
- "CINTA", // RIBBON (could also say “LISTÓN”)
1034
  "HILO",
1035
  "AGUJA",
1036
  "BOTÓN",
@@ -1040,7 +1069,7 @@ export const spanishWords = [
1040
  "MANOPLA",
1041
  "BUFANDA",
1042
  "GUANTE",
1043
- "PANTALONES",
1044
  "CAMISA",
1045
  "CHAQUETA",
1046
  "VESTIDO",
@@ -1048,7 +1077,6 @@ export const spanishWords = [
1048
  "CALCETÍN",
1049
  "BOTA",
1050
  "SANDALIA",
1051
- "SOMBRERO", // duplicate
1052
  "GORRA",
1053
  "MÁSCARA",
1054
  "RELOJ",
@@ -1067,13 +1095,9 @@ export const spanishWords = [
1067
  "HOGUERA",
1068
  "PICNIC",
1069
  "BANCO",
1070
- "VALLA", // duplicate
1071
- "PUERTA", // gate can be “PUERTA” or “PORTÓN”; used PUERTA earlier for “door,” so let's keep “PORTÓN” for gate below
1072
  "SEÑAL",
1073
  "SEMÁFORO",
1074
  "ACERA",
1075
- "FAROL", // duplicate
1076
- "GLOBO", // duplicate
1077
  "POSTAL",
1078
  "SELLO",
1079
  "CARTA",
@@ -1081,7 +1105,6 @@ export const spanishWords = [
1081
  "ESTACIONAMIENTO",
1082
  "CALLE",
1083
  "AUTOPISTA",
1084
- "PUENTE", // duplicate
1085
  "TÚNEL",
1086
  "ESTATUA",
1087
  "FUENTE",
@@ -1095,10 +1118,8 @@ export const spanishWords = [
1095
  "TELESCOPIO",
1096
  "MICROSCOPIO",
1097
  "IMÁN",
1098
- "BATERÍA", // duplicate
1099
  "BOMBILLA",
1100
  "ENCHUFE",
1101
- "ENCHUFE", // PLUG (maybe “CLAVIJA,” but “ENCHUFE” is also used)
1102
  "CABLE",
1103
  "INTERRUPTOR",
1104
  "CIRCUITO",
@@ -1176,7 +1197,7 @@ export const portugueseWords = [
1176
  "CAMA",
1177
  "XÍCARA",
1178
  "CHAVE",
1179
- "PORTA",
1180
  "FRANGO",
1181
  "PATO",
1182
  "OVELHA",
@@ -1194,7 +1215,7 @@ export const portugueseWords = [
1194
  "PINCEL",
1195
  "DENTE",
1196
  "MÃO",
1197
- "PÉS",
1198
  "OLHO",
1199
  "NARIZ",
1200
  "ORELHA",
@@ -1227,7 +1248,6 @@ export const portugueseWords = [
1227
  "TELEVISÃO",
1228
  "RÁDIO",
1229
  "BATERIA",
1230
- "VELA", // duplicado
1231
  "CERCA",
1232
  "CAIXA DE CORREIO",
1233
  "TIJOLO",
@@ -1240,12 +1260,11 @@ export const portugueseWords = [
1240
  "BICICLETA",
1241
  "FOGÃO",
1242
  "GELADEIRA",
1243
- "MICRO-ONDAS",
1244
  "MÁQUINA DE LAVAR",
1245
  "SECADORA",
1246
  "FORNO",
1247
  "VENTILADOR",
1248
- "PINCEI", // pincel de pintura
1249
  "BALDE",
1250
  "ESPONJA",
1251
  "SABÃO",
@@ -1253,7 +1272,6 @@ export const portugueseWords = [
1253
  "TECIDO",
1254
  "TESOURA",
1255
  "FITA",
1256
- "FITA", // FITA (pode ser “LAÇO” para diferenciar)
1257
  "LINHA",
1258
  "AGULHA",
1259
  "BOTÃO",
@@ -1263,7 +1281,7 @@ export const portugueseWords = [
1263
  "LUVAS SEM DEDOS",
1264
  "CACHECOL",
1265
  "LUVAS",
1266
- "CALÇAS",
1267
  "CAMISA",
1268
  "JAQUETA",
1269
  "VESTIDO",
@@ -1271,10 +1289,9 @@ export const portugueseWords = [
1271
  "MEIA",
1272
  "BOTA",
1273
  "SANDÁLIA",
1274
- "CHAPÉU", // duplicado
1275
  "BONÉ",
1276
  "MÁSCARA",
1277
- "RELÓGIO", // duplicado
1278
  "COLAR",
1279
  "PULSEIRA",
1280
  "ANEL",
@@ -1286,17 +1303,13 @@ export const portugueseWords = [
1286
  "MAPA",
1287
  "BÚSSOLA",
1288
  "TOCHA",
1289
- "LANTERNA",
1290
  "FOGUEIRA",
1291
  "PIQUENIQUE",
1292
  "BANCO",
1293
- "CERCA", // duplicado
1294
  "PORTÃO",
1295
  "PLACA",
1296
  "SEMAFÓRO",
1297
  "CALÇADA",
1298
- "LANTERNA", // duplicado
1299
- "BALÃO", // duplicado
1300
  "CARTÃO POSTAL",
1301
  "SELO",
1302
  "CARTA",
@@ -1304,7 +1317,6 @@ export const portugueseWords = [
1304
  "ESTACIONAMENTO",
1305
  "RUA",
1306
  "RODOVIA",
1307
- "PONTE", // duplicado
1308
  "TÚNEL",
1309
  "ESTÁTUA",
1310
  "FONTE",
@@ -1318,10 +1330,8 @@ export const portugueseWords = [
1318
  "TELESCÓPIO",
1319
  "MICROSCÓPIO",
1320
  "ÍMÃ",
1321
- "BATERIA", // duplicado
1322
  "LÂMPADA",
1323
  "TOMADA",
1324
- "TOMADA", // PLUG (pode ser “PLUGUE,” mas “TOMADA” também é comum)
1325
  "CABO",
1326
  "INTERRUPTOR",
1327
  "CIRCUITO",
@@ -1332,7 +1342,6 @@ export const portugueseWords = [
1332
  "TELA",
1333
  "IMPRESSORA",
1334
  "ALTO-FALANTE",
1335
- "FONES DE OUVIDO",
1336
  "TELEFONE",
1337
  "CÂMERA"
1338
  ];
 
 
 
1
  export const englishWords = [
2
  "DOG",
3
  "CAT",
 
79
  "BRUSH",
80
  "TOOTH",
81
  "HAND",
82
+ "FOOT",
83
  "EYE",
84
  "NOSE",
85
  "EAR",
 
112
  "TELEVISION",
113
  "RADIO",
114
  "BATTERY",
 
115
  "FENCE",
116
  "MAILBOX",
117
  "BRICK",
 
158
  "HAT",
159
  "CAP",
160
  "MASK",
161
+ "SUNGLASSES",
162
  "WATCH",
163
  "NECKLACE",
164
  "BRACELET",
 
177
  "SLEEPINGBAG",
178
  "PICNIC",
179
  "BENCH",
 
180
  "GATE",
181
  "SIGN",
182
  "CROSSWALK",
183
  "TRAFFICLIGHT",
184
  "SIDEWALK",
 
 
185
  "POSTCARD",
186
  "STAMP",
187
  "LETTER",
 
189
  "PARKING",
190
  "STREET",
191
  "HIGHWAY",
 
192
  "TUNNEL",
193
  "STATUE",
194
  "FOUNTAIN",
 
202
  "TELESCOPE",
203
  "MICROSCOPE",
204
  "MAGNET",
 
205
  "BULB",
206
  "SOCKET",
207
  "PLUG",
 
217
  "SPEAKER",
218
  "HEADPHONE",
219
  "PHONE",
220
+ "CAMERA",
221
+ "VIOLIN",
222
+ "GUITAR",
223
+ "TRUMPET",
224
+ "TROMBONE",
225
+ "DRUM",
226
+ "FLUTE",
227
+ "HARP",
228
+ "PIANO",
229
+ "ORCHESTRA",
230
+ "MUSEUM",
231
+ "THEATER",
232
+ "CIRCUS",
233
+ "ANT",
234
+ "SPIDER",
235
+ "MOTH",
236
+ "BEAN",
237
+ "PEACH",
238
+ "GRAPE",
239
+ "LEMON",
240
+ "ORANGE",
241
+ "PINEAPPLE",
242
+ "STRAWBERRY",
243
+ "BLUEBERRY",
244
+ "RASPBERRY",
245
+ "CUCUMBER",
246
+ "CARROT",
247
+ "POTATO",
248
+ "TOMATO",
249
+ "LETTUCE",
250
+ "BROCCOLI",
251
+ "CABBAGE",
252
+ "GARLIC",
253
+ "ONION",
254
+ "PEPPER",
255
+ "PUMPKIN",
256
+ "MUSHROOM",
257
+ "CHESS",
258
+ "PUZZLE",
259
+ "DICE",
260
+ "MARBLE",
261
+ "DOLPHIN",
262
+ "WHALE",
263
+ "BARN",
264
+ "WAGON",
265
+ "FERRY",
266
+ "HARVEST",
267
+ "PLOW",
268
+ "SILO",
269
+ "VILLAGE",
270
+ "MARKET",
271
+ "BREEZEWAY",
272
+ "MEADOW",
273
+ "STREAM",
274
+ "CLIFF",
275
+ "CANYON",
276
+ "VALLEY",
277
+ "DESERT",
278
+ "GLACIER",
279
+ "WATERFALL",
280
+ "VOLCANO",
281
+ "CAVE",
282
+ "LAGOON",
283
+ "HURRICANE",
284
+ "TORNADO",
285
+ "EARTHQUAKE",
286
+ "SAVANNA",
287
  ];
288
  export const germanWords = [
289
  "HUND",
 
366
  "PINSEL",
367
  "ZAHN",
368
  "HAND",
369
+ "FUSS",
370
  "AUGE",
371
  "NASE",
372
  "OHR",
 
399
  "FERNSEHER",
400
  "RADIO",
401
  "BATTERIE",
 
402
  "ZAUN",
403
  "BRIEFKASTEN",
404
  "BACKSTEIN",
 
416
  "TROCKNER",
417
  "OFEN",
418
  "VENTILATOR",
 
419
  "EIMER",
420
  "SCHWAMM",
421
  "SEIFE",
 
441
  "SOCKE",
442
  "STIEFEL",
443
  "SANDALE",
 
444
  "MÜTZE",
445
  "MASKE",
446
  "SONNENBRILLE",
 
447
  "HALSKETTE",
448
  "ARMBAND",
449
  "RING",
 
461
  "SCHLAFSACK",
462
  "PICKNICK",
463
  "BANK",
 
464
  "TOR",
465
  "SCHILD",
466
  "ZEBRASTREIFEN",
467
  "VERKEHRSAMPEL",
468
  "BÜRGERSTEIG",
 
 
469
  "POSTKARTE",
470
  "BRIEFMARKE",
471
  "BRIEF",
 
473
  "PARKPLATZ",
474
  "STRAßE",
475
  "AUTOBAHN",
 
476
  "TUNNEL",
477
  "STATUE",
478
  "BRUNNEN",
 
486
  "TELESKOP",
487
  "MIKROSKOP",
488
  "MAGNET",
 
489
  "GLÜHBIRNE",
490
  "STECKDOSE",
491
  "STECKER",
 
584
  "PINCEAU",
585
  "DENT",
586
  "MAIN",
587
+ "PIED",
588
  "ŒIL",
589
  "NEZ",
590
  "OREILLE",
 
617
  "TÉLÉVISION",
618
  "RADIO",
619
  "PILE",
 
620
  "CLÔTURE",
621
  "BRIQUE",
622
  "LANTERNE",
 
633
  "SÈCHE-LINGE",
634
  "FOURNAISE",
635
  "VENTILATEUR",
 
636
  "SEAU",
637
  "ÉPONGE",
638
  "SAVON",
 
657
  "CHAUSSETTE",
658
  "BOTTE",
659
  "SANDALE",
 
660
  "CASQUETTE",
661
  "MASQUE",
662
  "MONTRE",
 
672
  "TENTE",
673
  "PIQUE-NIQUE",
674
  "BANC",
 
675
  "PORTAIL",
676
  "PANNEAU",
677
  "TROTTOIR",
 
 
678
  "TIMBRE",
679
  "LETTRE",
680
  "ENVELOPPE",
681
  "PARKING",
682
  "RUE",
683
  "AUTOROUTE",
 
684
  "TUNNEL",
685
  "STATUE",
686
  "FONTAINE",
 
694
  "TÉLESCOPE",
695
  "MICROSCOPE",
696
  "AIMANT",
 
697
  "AMPOULE",
698
  "PRISE",
699
  "FICHE",
 
700
  "INTERRUPTEUR",
701
  "CIRCUIT",
702
  "ROBOT",
 
757
  "AEREO",
758
  "TRENO",
759
  "CARAMELLA",
760
+ "COMETA",
761
+ "GLOBO",
762
  "PARCO",
763
  "SPIAGGIA",
764
  "GIOCATTOLO",
 
788
  "NIDO",
789
  "ROCCIA",
790
  "FOGLIA",
791
+ "PINNELLO",
792
  "DENTE",
793
  "MANO",
794
+ "PIEDE",
795
  "OCCHIO",
796
  "NASO",
797
  "ORECCHIO",
 
824
  "TELEVISIONE",
825
  "RADIO",
826
  "BATTERIA",
 
827
  "RECINTO",
828
  "MATTONE",
829
  "LANTERNA",
 
840
  "ASCIUGATRICE",
841
  "FORNO",
842
  "VENTILATORE",
843
+ "PINNELLO",
844
  "SECCHIO",
845
  "SPUGNA",
846
  "SAPONE",
 
857
  "MOFFOLA",
858
  "SCIARPA",
859
  "GUANTO",
860
+ "PANTALON",
861
  "CAMICIA",
862
  "GIACCA",
863
  "VESTITO",
864
  "GONNA",
865
  "CALZINO",
 
866
  "SANDALO",
867
+ "BERRETTO",
 
868
  "MASCHERA",
869
  "OROLOGIO",
870
  "COLLANA",
 
882
  "TENDA",
883
  "PICNIC",
884
  "PANCHINA",
 
885
  "CANCELLO",
886
  "SEGNALE",
887
  "SEMAFORO",
888
  "MARCIAPIEDE",
 
 
889
  "CARTOLINA",
890
  "FRANCOBOLLO",
891
  "LETTERA",
 
893
  "PARCHEGGIO",
894
  "STRADA",
895
  "AUTOSTRADA",
 
896
  "TUNNEL",
897
  "STATUA",
898
  "FONTANA",
 
906
  "TELESCOPIO",
907
  "MICROSCOPIO",
908
  "MAGNETE",
 
909
  "LAMPADINA",
910
  "PRESA",
911
  "SPINA",
 
1036
  "TELEVISIÓN",
1037
  "RADIO",
1038
  "BATERÍA",
 
1039
  "VALLA",
1040
  "BUZÓN",
1041
  "LADRILLO",
 
1053
  "SECADORA",
1054
  "HORNO",
1055
  "VENTILADOR",
 
1056
  "CUBO",
1057
  "ESPONJA",
1058
  "JABÓN",
 
1060
  "TELA",
1061
  "TIJERAS",
1062
  "CINTA",
 
1063
  "HILO",
1064
  "AGUJA",
1065
  "BOTÓN",
 
1069
  "MANOPLA",
1070
  "BUFANDA",
1071
  "GUANTE",
1072
+ "PANTALÓN",
1073
  "CAMISA",
1074
  "CHAQUETA",
1075
  "VESTIDO",
 
1077
  "CALCETÍN",
1078
  "BOTA",
1079
  "SANDALIA",
 
1080
  "GORRA",
1081
  "MÁSCARA",
1082
  "RELOJ",
 
1095
  "HOGUERA",
1096
  "PICNIC",
1097
  "BANCO",
 
 
1098
  "SEÑAL",
1099
  "SEMÁFORO",
1100
  "ACERA",
 
 
1101
  "POSTAL",
1102
  "SELLO",
1103
  "CARTA",
 
1105
  "ESTACIONAMIENTO",
1106
  "CALLE",
1107
  "AUTOPISTA",
 
1108
  "TÚNEL",
1109
  "ESTATUA",
1110
  "FUENTE",
 
1118
  "TELESCOPIO",
1119
  "MICROSCOPIO",
1120
  "IMÁN",
 
1121
  "BOMBILLA",
1122
  "ENCHUFE",
 
1123
  "CABLE",
1124
  "INTERRUPTOR",
1125
  "CIRCUITO",
 
1197
  "CAMA",
1198
  "XÍCARA",
1199
  "CHAVE",
1200
+ "PORTE",
1201
  "FRANGO",
1202
  "PATO",
1203
  "OVELHA",
 
1215
  "PINCEL",
1216
  "DENTE",
1217
  "MÃO",
1218
+ "",
1219
  "OLHO",
1220
  "NARIZ",
1221
  "ORELHA",
 
1248
  "TELEVISÃO",
1249
  "RÁDIO",
1250
  "BATERIA",
 
1251
  "CERCA",
1252
  "CAIXA DE CORREIO",
1253
  "TIJOLO",
 
1260
  "BICICLETA",
1261
  "FOGÃO",
1262
  "GELADEIRA",
1263
+ "MICROONDAS",
1264
  "MÁQUINA DE LAVAR",
1265
  "SECADORA",
1266
  "FORNO",
1267
  "VENTILADOR",
 
1268
  "BALDE",
1269
  "ESPONJA",
1270
  "SABÃO",
 
1272
  "TECIDO",
1273
  "TESOURA",
1274
  "FITA",
 
1275
  "LINHA",
1276
  "AGULHA",
1277
  "BOTÃO",
 
1281
  "LUVAS SEM DEDOS",
1282
  "CACHECOL",
1283
  "LUVAS",
1284
+ "CALÇA",
1285
  "CAMISA",
1286
  "JAQUETA",
1287
  "VESTIDO",
 
1289
  "MEIA",
1290
  "BOTA",
1291
  "SANDÁLIA",
 
1292
  "BONÉ",
1293
  "MÁSCARA",
1294
+ "RELÓGIO",
1295
  "COLAR",
1296
  "PULSEIRA",
1297
  "ANEL",
 
1303
  "MAPA",
1304
  "BÚSSOLA",
1305
  "TOCHA",
 
1306
  "FOGUEIRA",
1307
  "PIQUENIQUE",
1308
  "BANCO",
 
1309
  "PORTÃO",
1310
  "PLACA",
1311
  "SEMAFÓRO",
1312
  "CALÇADA",
 
 
1313
  "CARTÃO POSTAL",
1314
  "SELO",
1315
  "CARTA",
 
1317
  "ESTACIONAMENTO",
1318
  "RUA",
1319
  "RODOVIA",
 
1320
  "TÚNEL",
1321
  "ESTÁTUA",
1322
  "FONTE",
 
1330
  "TELESCÓPIO",
1331
  "MICROSCÓPIO",
1332
  "ÍMÃ",
 
1333
  "LÂMPADA",
1334
  "TOMADA",
 
1335
  "CABO",
1336
  "INTERRUPTOR",
1337
  "CIRCUITO",
 
1342
  "TELA",
1343
  "IMPRESSORA",
1344
  "ALTO-FALANTE",
 
1345
  "TELEFONE",
1346
  "CÂMERA"
1347
  ];
src/services/{mistralService.ts → aiService.ts} RENAMED
@@ -1,13 +1,14 @@
 
1
  import { supabase } from "@/integrations/supabase/client";
2
 
3
  export const generateAIResponse = async (currentWord: string, currentSentence: string[], language: string = 'en'): Promise<string> => {
4
  console.log('Calling generate-word function with:', { currentWord, currentSentence, language });
5
-
6
  const { data, error } = await supabase.functions.invoke('generate-word', {
7
- body: {
8
- currentWord,
9
  currentSentence: currentSentence.join(' '),
10
- language
11
  }
12
  });
13
 
@@ -24,21 +25,21 @@ export const generateAIResponse = async (currentWord: string, currentSentence: s
24
  throw new Error('No word generated');
25
  }
26
 
27
- console.log('AI generated word:', data.word);
28
  return data.word;
29
  };
30
 
31
- export const guessWord = async (sentence: string, language: string): Promise<string> => {
32
  console.log('Processing guess for sentence:', sentence);
33
-
34
  const words = sentence.trim().split(/\s+/);
35
-
36
  console.log('Calling guess-word function with sentence:', sentence, 'language:', language);
37
-
38
  const { data, error } = await supabase.functions.invoke('guess-word', {
39
- body: {
40
  sentence,
41
- language
42
  }
43
  });
44
 
@@ -55,6 +56,6 @@ export const guessWord = async (sentence: string, language: string): Promise<str
55
  throw new Error('No guess generated');
56
  }
57
 
58
- console.log('AI guessed:', data.guess);
59
- return data.guess;
60
- };
 
1
+
2
  import { supabase } from "@/integrations/supabase/client";
3
 
4
  export const generateAIResponse = async (currentWord: string, currentSentence: string[], language: string = 'en'): Promise<string> => {
5
  console.log('Calling generate-word function with:', { currentWord, currentSentence, language });
6
+
7
  const { data, error } = await supabase.functions.invoke('generate-word', {
8
+ body: {
9
+ currentWord,
10
  currentSentence: currentSentence.join(' '),
11
+ language
12
  }
13
  });
14
 
 
25
  throw new Error('No word generated');
26
  }
27
 
28
+ console.log('AI generated word:', data.word, 'using model:', data.model);
29
  return data.word;
30
  };
31
 
32
+ export const guessWord = async (sentence: string, language: string): Promise<{ guess: string; model: string }> => {
33
  console.log('Processing guess for sentence:', sentence);
34
+
35
  const words = sentence.trim().split(/\s+/);
36
+
37
  console.log('Calling guess-word function with sentence:', sentence, 'language:', language);
38
+
39
  const { data, error } = await supabase.functions.invoke('guess-word', {
40
+ body: {
41
  sentence,
42
+ language
43
  }
44
  });
45
 
 
56
  throw new Error('No guess generated');
57
  }
58
 
59
+ console.log('AI guessed:', data.guess, 'using model:', data.model);
60
+ return { guess: data.guess, model: data.model };
61
+ };
supabase/functions/create-session/index.ts CHANGED
@@ -1,5 +1,18 @@
1
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
2
  import { createClient } from 'https://esm.sh/@supabase/[email protected]';
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  const corsHeaders = {
5
  'Access-Control-Allow-Origin': '*',
@@ -56,6 +69,7 @@ serve(async (req) => {
56
  );
57
 
58
  } catch (error) {
 
59
  console.error('Error in create-session:', error);
60
  return new Response(
61
  JSON.stringify({ error: error.message }),
@@ -65,4 +79,4 @@ serve(async (req) => {
65
  }
66
  );
67
  }
68
- });
 
1
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
2
  import { createClient } from 'https://esm.sh/@supabase/[email protected]';
3
+ import * as Sentry from "https://deno.land/x/sentry/index.mjs";
4
+
5
+ Sentry.init({
6
+ dsn: "https://ca41c3f96489cc1b3e69c9a44704f7ee@o4508722276007936.ingest.de.sentry.io/4508772265558096",
7
+ defaultIntegrations: false,
8
+ // Performance Monitoring
9
+ tracesSampleRate: 1.0,
10
+ // Set sampling rate for profiling - this is relative to tracesSampleRate
11
+ profilesSampleRate: 1.0,
12
+ });
13
+
14
+ Sentry.setTag('region', Deno.env.get('SB_REGION'));
15
+ Sentry.setTag('execution_id', Deno.env.get('SB_EXECUTION_ID'));
16
 
17
  const corsHeaders = {
18
  'Access-Control-Allow-Origin': '*',
 
69
  );
70
 
71
  } catch (error) {
72
+ Sentry.captureException(error)
73
  console.error('Error in create-session:', error);
74
  return new Response(
75
  JSON.stringify({ error: error.message }),
 
79
  }
80
  );
81
  }
82
+ });
supabase/functions/generate-daily-challenge/index.ts CHANGED
@@ -1,12 +1,26 @@
1
  import "https://deno.land/x/[email protected]/mod.ts";
2
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
3
  import { createClient } from 'https://esm.sh/@supabase/[email protected]';
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  const corsHeaders = {
6
  'Access-Control-Allow-Origin': '*',
7
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
8
  };
9
 
 
10
  const wordTranslations: Record<string, Record<string, string>> = {
11
  "CAT": { de: "KATZE", fr: "CHAT", it: "GATTO", es: "GATO", pt: "GATO" },
12
  "DOG": { de: "HUND", fr: "CHIEN", it: "CANE", es: "PERRO", pt: "CÃO" },
@@ -88,7 +102,7 @@ const wordTranslations: Record<string, Record<string, string>> = {
88
  "BRUSH": { de: "PINSEL", fr: "BROSSE", it: "PENNELLO", es: "Pincel", pt: "Pincel" },
89
  "TOOTH": { de: "ZAHN", fr: "DENT", it: "DENTE", es: "DIENTE", pt: "DENTE" },
90
  "HAND": { de: "HAND", fr: "MAIN", it: "MANO", es: "MANO", pt: "MÃO" },
91
- "FEET": { de: "FÜSSE", fr: "PIEDS", it: "PIEDI", es: "PIES", pt: "PÉS" },
92
  "EYE": { de: "AUGE", fr: "ŒIL", it: "OCCHIO", es: "OJO", pt: "OLHO" },
93
  "NOSE": { de: "NASE", fr: "NEZ", it: "NASO", es: "NARIZ", pt: "NARIZ" },
94
  "EAR": { de: "OHR", fr: "OREILLE", it: "ORECCHIO", es: "OREJA", pt: "ORELHA" },
@@ -123,7 +137,7 @@ const wordTranslations: Record<string, Record<string, string>> = {
123
  "BATTERY": { de: "BATTERIE", fr: "PILE", it: "BATTERIA", es: "BATERÍA", pt: "BATERIA" },
124
  "FENCE": { de: "ZAUN", fr: "CLÔTURE", it: "RECINTO", es: "VALLA", pt: "CERCA" },
125
  "MAILBOX": { de: "BRIEFKASTEN", fr: "BOÎTE AUX LETTRES", it: "CASSETTA POSTALE", es: "BUZÓN", pt: "CAIXA DE CORREIO" },
126
- "BRICK": { de: "BACKSTEIN", fr: "BRIQUE", it: "MATTONE", es: "LADRILLO", pt: "Tijolo" },
127
  "LANTERN": { de: "LATERNE", fr: "LANTERNE", it: "LANTERNA", es: "FAROL", pt: "LANTERNA" },
128
  "WHEEL": { de: "RAD", fr: "ROUE", it: "RUOTA", es: "RUEDA", pt: "RODA" },
129
  "BELL": { de: "GLOCKE", fr: "CLoche", it: "CAMPANA", es: "CAMPANA", pt: "SINO" },
@@ -144,7 +158,7 @@ const wordTranslations: Record<string, Record<string, string>> = {
144
  "SOAP": { de: "SEIFE", fr: "SAVON", it: "SAPONE", es: "JABÓN", pt: "SABÃO" },
145
  "TOWEL": { de: "HANDTUCH", fr: "SERVIETTE", it: "ASCIUGAMANO", es: "TOALLA", pt: "TOALHA" },
146
  "CLOTH": { de: "STOFF", fr: "TISSU", it: "STOFFA", es: "TELA", pt: "TECIDO" },
147
- "SCISSORS": { de: "SCHERE", fr: "CISEAUX", it: "FORBICI", es: "TIJERAS", pt: "TESOURA" },
148
  "RIBBON": { de: "BAND", fr: "RUBAN", it: "NASTRO", es: "CINTA", pt: "FITA" },
149
  "THREAD": { de: "FADEN", fr: "FIL", it: "FILO", es: "HILO", pt: "LINHA" },
150
  "NEEDLE": { de: "NADEL", fr: "AIGUILLE", it: "AGO", es: "AGUJA", pt: "AGULHA" },
@@ -154,7 +168,7 @@ const wordTranslations: Record<string, Record<string, string>> = {
154
  "MITTEN": { de: "FAUSTHANDSCHUH", fr: "MOUFLE", it: "GUANTO", es: "MANOPLA", pt: "LUVA" },
155
  "SCARF": { de: "SCHAL", fr: "ÉCHARPE", it: "SCIARPA", es: "BUFANDA", pt: "CACHECOL" },
156
  "GLOVE": { de: "HANDSCHUH", fr: "GANT", it: "GUANTO", es: "GUANTE", pt: "LUVA" },
157
- "PANTS": { de: "HOSE", fr: "PANTALON", it: "PANTALONI", es: "PANTALONES", pt: "CALÇAS" },
158
  "SHIRT": { de: "HEMD", fr: "CHEMISE", it: "CAMICIA", es: "CAMISA", pt: "CAMISA" },
159
  "JACKET": { de: "JACKE", fr: "VESTE", it: "GIACCA", es: "CHAQUETA", pt: "JAQUETA" },
160
  "DRESS": { de: "KLEID", fr: "ROBE", it: "VESTITO", es: "VESTIDO", pt: "VESTIDO" },
@@ -350,6 +364,7 @@ serve(async (req) => {
350
  );
351
 
352
  } catch (error) {
 
353
  console.error('Error in generate-daily-challenge:', error);
354
  return new Response(
355
  JSON.stringify({ error: error.message }),
@@ -359,4 +374,4 @@ serve(async (req) => {
359
  }
360
  );
361
  }
362
- });
 
1
  import "https://deno.land/x/[email protected]/mod.ts";
2
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
3
  import { createClient } from 'https://esm.sh/@supabase/[email protected]';
4
+ import * as Sentry from "https://deno.land/x/sentry/index.mjs";
5
+
6
+ Sentry.init({
7
+ dsn: "https://ca41c3f96489cc1b3e69c9a44704f7ee@o4508722276007936.ingest.de.sentry.io/4508772265558096",
8
+ defaultIntegrations: false,
9
+ // Performance Monitoring
10
+ tracesSampleRate: 1.0,
11
+ // Set sampling rate for profiling - this is relative to tracesSampleRate
12
+ profilesSampleRate: 1.0,
13
+ });
14
+
15
+ Sentry.setTag('region', Deno.env.get('SB_REGION'));
16
+ Sentry.setTag('execution_id', Deno.env.get('SB_EXECUTION_ID'));
17
 
18
  const corsHeaders = {
19
  'Access-Control-Allow-Origin': '*',
20
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
21
  };
22
 
23
+ // Ensure that all words are singular nouns by updating the keys for words that were originally plural.
24
  const wordTranslations: Record<string, Record<string, string>> = {
25
  "CAT": { de: "KATZE", fr: "CHAT", it: "GATTO", es: "GATO", pt: "GATO" },
26
  "DOG": { de: "HUND", fr: "CHIEN", it: "CANE", es: "PERRO", pt: "CÃO" },
 
102
  "BRUSH": { de: "PINSEL", fr: "BROSSE", it: "PENNELLO", es: "Pincel", pt: "Pincel" },
103
  "TOOTH": { de: "ZAHN", fr: "DENT", it: "DENTE", es: "DIENTE", pt: "DENTE" },
104
  "HAND": { de: "HAND", fr: "MAIN", it: "MANO", es: "MANO", pt: "MÃO" },
105
+ "FOOT": { de: "FUß", fr: "PIED", it: "PIEDE", es: "PIE", pt: "" },
106
  "EYE": { de: "AUGE", fr: "ŒIL", it: "OCCHIO", es: "OJO", pt: "OLHO" },
107
  "NOSE": { de: "NASE", fr: "NEZ", it: "NASO", es: "NARIZ", pt: "NARIZ" },
108
  "EAR": { de: "OHR", fr: "OREILLE", it: "ORECCHIO", es: "OREJA", pt: "ORELHA" },
 
137
  "BATTERY": { de: "BATTERIE", fr: "PILE", it: "BATTERIA", es: "BATERÍA", pt: "BATERIA" },
138
  "FENCE": { de: "ZAUN", fr: "CLÔTURE", it: "RECINTO", es: "VALLA", pt: "CERCA" },
139
  "MAILBOX": { de: "BRIEFKASTEN", fr: "BOÎTE AUX LETTRES", it: "CASSETTA POSTALE", es: "BUZÓN", pt: "CAIXA DE CORREIO" },
140
+ "BRICK": { de: "BACKSTEIN", fr: "BRIQUE", it: "MATTONE", es: "LADRILLO", pt: "TIJOLO" },
141
  "LANTERN": { de: "LATERNE", fr: "LANTERNE", it: "LANTERNA", es: "FAROL", pt: "LANTERNA" },
142
  "WHEEL": { de: "RAD", fr: "ROUE", it: "RUOTA", es: "RUEDA", pt: "RODA" },
143
  "BELL": { de: "GLOCKE", fr: "CLoche", it: "CAMPANA", es: "CAMPANA", pt: "SINO" },
 
158
  "SOAP": { de: "SEIFE", fr: "SAVON", it: "SAPONE", es: "JABÓN", pt: "SABÃO" },
159
  "TOWEL": { de: "HANDTUCH", fr: "SERVIETTE", it: "ASCIUGAMANO", es: "TOALLA", pt: "TOALHA" },
160
  "CLOTH": { de: "STOFF", fr: "TISSU", it: "STOFFA", es: "TELA", pt: "TECIDO" },
161
+ "SCISSOR": { de: "SCHERE", fr: "CISEAU", it: "FORBICI", es: "TIJERA", pt: "TESOURA" },
162
  "RIBBON": { de: "BAND", fr: "RUBAN", it: "NASTRO", es: "CINTA", pt: "FITA" },
163
  "THREAD": { de: "FADEN", fr: "FIL", it: "FILO", es: "HILO", pt: "LINHA" },
164
  "NEEDLE": { de: "NADEL", fr: "AIGUILLE", it: "AGO", es: "AGUJA", pt: "AGULHA" },
 
168
  "MITTEN": { de: "FAUSTHANDSCHUH", fr: "MOUFLE", it: "GUANTO", es: "MANOPLA", pt: "LUVA" },
169
  "SCARF": { de: "SCHAL", fr: "ÉCHARPE", it: "SCIARPA", es: "BUFANDA", pt: "CACHECOL" },
170
  "GLOVE": { de: "HANDSCHUH", fr: "GANT", it: "GUANTO", es: "GUANTE", pt: "LUVA" },
171
+ "TROUSER": { de: "HOSE", fr: "PANTALON", it: "PANTALONE", es: "PANTALÓN", pt: "CALÇA" },
172
  "SHIRT": { de: "HEMD", fr: "CHEMISE", it: "CAMICIA", es: "CAMISA", pt: "CAMISA" },
173
  "JACKET": { de: "JACKE", fr: "VESTE", it: "GIACCA", es: "CHAQUETA", pt: "JAQUETA" },
174
  "DRESS": { de: "KLEID", fr: "ROBE", it: "VESTITO", es: "VESTIDO", pt: "VESTIDO" },
 
364
  );
365
 
366
  } catch (error) {
367
+ Sentry.captureException(error)
368
  console.error('Error in generate-daily-challenge:', error);
369
  return new Response(
370
  JSON.stringify({ error: error.message }),
 
374
  }
375
  );
376
  }
377
+ });
supabase/functions/generate-game/index.ts CHANGED
@@ -1,6 +1,19 @@
1
  import "https://deno.land/x/[email protected]/mod.ts";
2
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
3
  import { createClient } from 'https://esm.sh/@supabase/[email protected]';
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  const corsHeaders = {
6
  'Access-Control-Allow-Origin': '*',
@@ -46,6 +59,7 @@ serve(async (req) => {
46
  usedWords.push(data.word);
47
  }
48
  } catch (error) {
 
49
  console.error('Error generating word:', error);
50
  throw error;
51
  }
@@ -82,4 +96,4 @@ serve(async (req) => {
82
  }
83
  );
84
  }
85
- });
 
1
  import "https://deno.land/x/[email protected]/mod.ts";
2
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
3
  import { createClient } from 'https://esm.sh/@supabase/[email protected]';
4
+ import * as Sentry from "https://deno.land/x/sentry/index.mjs";
5
+
6
+ Sentry.init({
7
+ dsn: "https://ca41c3f96489cc1b3e69c9a44704f7ee@o4508722276007936.ingest.de.sentry.io/4508772265558096",
8
+ defaultIntegrations: false,
9
+ // Performance Monitoring
10
+ tracesSampleRate: 1.0,
11
+ // Set sampling rate for profiling - this is relative to tracesSampleRate
12
+ profilesSampleRate: 1.0,
13
+ });
14
+
15
+ Sentry.setTag('region', Deno.env.get('SB_REGION'));
16
+ Sentry.setTag('execution_id', Deno.env.get('SB_EXECUTION_ID'));
17
 
18
  const corsHeaders = {
19
  'Access-Control-Allow-Origin': '*',
 
59
  usedWords.push(data.word);
60
  }
61
  } catch (error) {
62
+ Sentry.captureException(error)
63
  console.error('Error generating word:', error);
64
  throw error;
65
  }
 
96
  }
97
  );
98
  }
99
+ });
supabase/functions/generate-themed-word/index.ts CHANGED
@@ -1,6 +1,18 @@
1
  import "https://deno.land/x/[email protected]/mod.ts";
2
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
3
- import { Mistral } from 'npm:@mistralai/mistralai';
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  const corsHeaders = {
6
  'Access-Control-Allow-Origin': '*',
@@ -10,69 +22,36 @@ const corsHeaders = {
10
  const languagePrompts = {
11
  en: {
12
  systemPrompt: "You are helping generate words for a word-guessing game. Generate a single word in English related to the theme",
13
- requirements: "The word should be:\n- A single word (no spaces or hyphens)\n- Common enough that people would know it\n- Specific enough to be interesting\n- Related to the theme\n- Between 4 and 12 letters\n- A noun\n- NOT be any of these previously used words:"
14
  },
15
  fr: {
16
  systemPrompt: "Vous aidez à générer des mots pour un jeu de devinettes. Générez un seul mot en français lié au thème",
17
- requirements: "Le mot doit être :\n- Un seul mot (pas d'espaces ni de traits d'union)\n- Assez courant pour que les gens le connaissent\n- Suffisamment spécifique pour être intéressant\n- En rapport avec le thème\n- Entre 4 et 12 lettres\n- Un nom\n- NE PAS être l'un de ces mots déjà utilisés :"
18
  },
19
  de: {
20
  systemPrompt: "Sie helfen bei der Generierung von Wörtern für ein Worträtselspiel. Generieren Sie ein einzelnes Wort auf Deutsch zum Thema",
21
- requirements: "Das Wort sollte:\n- Ein einzelnes Wort sein (keine Leerzeichen oder Bindestriche)\n- Häufig genug, dass Menschen es kennen\n- Spezifisch genug, um interessant zu sein\n- Zum Thema passen\n- Zwischen 4 und 12 Buchstaben lang sein\n- Ein Substantiv sein\n- NICHT eines dieser bereits verwendeten Wörter sein:"
22
  },
23
  it: {
24
  systemPrompt: "Stai aiutando a generare parole per un gioco di indovinelli. Genera una singola parola in italiano legata al tema",
25
- requirements: "La parola deve essere:\n- Una singola parola (senza spazi o trattini)\n- Abbastanza comune da essere conosciuta\n- Sufficientemente specifica da essere interessante\n- Correlata al tema\n- Tra 4 e 12 lettere\n- Un sostantivo\n- NON essere una di queste parole già utilizzate:"
26
  },
27
  es: {
28
  systemPrompt: "Estás ayudando a generar palabras para un juego de adivinanzas. Genera una sola palabra en español relacionada con el tema",
29
- requirements: "La palabra debe ser:\n- Una sola palabra (sin espacios ni guiones)\n- Lo suficientemente común para que la gente la conozca\n- Lo suficientemente específica para ser interesante\n- Relacionada con el tema\n- Entre 4 y 12 letras\n- Un sustantivo\n- NO ser ninguna de estas palabras ya utilizadas:"
30
  },
31
  pt: {
32
  systemPrompt: "Estás ajudando a gerar palavras para um jogo de adivinhação. Gere uma única palavra em português relacionada ao tema",
33
- requirements: "A palavra deve ser:\n- Uma única palavra (sem espaços ou hífens)\n- Comum o suficiente para que as pessoas a conheçam\n- Específica o suficiente para ser interessante\n- Relacionada ao tema\n- Entre 4 e 12 letras\n- Um substantivo\n- NÃO ser nenhuma destas palavras já utilizadas:"
34
  }
35
  };
36
 
37
  const openRouterModels = [
38
- 'sophosympatheia/rogue-rose-103b-v0.2:free',
39
  'google/gemini-2.0-flash-exp:free',
40
- 'meta-llama/llama-3.1-70b-instruct:free',
41
- 'microsoft/phi-3-medium-128k-instruct:free'
42
  ];
43
 
44
- async function tryMistral(theme: string, usedWords: string[], language: string) {
45
- const mistralKey = Deno.env.get('MISTRAL_API_KEY');
46
- if (!mistralKey) {
47
- throw new Error('Mistral API key not configured');
48
- }
49
-
50
- const client = new Mistral({
51
- apiKey: mistralKey,
52
- });
53
-
54
- const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;
55
-
56
- const response = await client.chat.complete({
57
- model: "mistral-large-latest",
58
- messages: [
59
- {
60
- role: "system",
61
- content: `${prompts.systemPrompt} "${theme}".\n${prompts.requirements} ${usedWords.join(', ')}\n\nRespond with just the word in UPPERCASE, nothing else.`
62
- }
63
- ],
64
- maxTokens: 50,
65
- temperature: 0.99
66
- });
67
-
68
- if (!response?.choices?.[0]?.message?.content) {
69
- throw new Error('Invalid response from Mistral API');
70
- }
71
-
72
- return response.choices[0].message.content.trim();
73
- }
74
-
75
- async function tryOpenRouter(theme: string, usedWords: string[], language: string) {
76
  const openRouterKey = Deno.env.get('OPENROUTER_API_KEY');
77
  if (!openRouterKey) {
78
  throw new Error('OpenRouter API key not configured');
@@ -81,7 +60,7 @@ async function tryOpenRouter(theme: string, usedWords: string[], language: strin
81
  const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;
82
  const randomModel = openRouterModels[Math.floor(Math.random() * openRouterModels.length)];
83
 
84
- console.log('Trying OpenRouter with model:', randomModel);
85
 
86
  const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
87
  method: "POST",
@@ -125,30 +104,21 @@ serve(async (req) => {
125
  const { theme, usedWords = [], language = 'en' } = await req.json();
126
  console.log('Generating word for theme:', theme, 'language:', language, 'excluding:', usedWords);
127
 
128
- let word;
129
- let error;
130
-
131
  try {
132
- console.log('Attempting with Mistral...');
133
- word = await tryMistral(theme, usedWords, language);
134
- console.log('Successfully generated word with Mistral:', word);
135
- } catch (mistralError) {
136
- console.error('Mistral error:', mistralError);
137
- console.log('Falling back to OpenRouter...');
138
-
139
- try {
140
- word = await tryOpenRouter(theme, usedWords, language);
141
- console.log('Successfully generated word with OpenRouter:', word);
142
- } catch (openRouterError) {
143
- console.error('OpenRouter error:', openRouterError);
144
- error = openRouterError;
145
- }
146
- }
147
 
148
- if (!word) {
149
  return new Response(
150
  JSON.stringify({
151
- error: 'Failed to generate word with both Mistral and OpenRouter',
152
  details: error?.message || 'Unknown error'
153
  }),
154
  {
@@ -157,16 +127,13 @@ serve(async (req) => {
157
  }
158
  );
159
  }
160
-
161
- return new Response(
162
- JSON.stringify({ word }),
163
- { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
164
- );
165
  } catch (error) {
166
- console.error('Error generating themed word:', error);
 
 
167
  return new Response(
168
  JSON.stringify({
169
- error: 'Error generating themed word',
170
  details: error.message
171
  }),
172
  {
@@ -175,4 +142,4 @@ serve(async (req) => {
175
  }
176
  );
177
  }
178
- });
 
1
  import "https://deno.land/x/[email protected]/mod.ts";
2
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
3
+ import * as Sentry from "https://deno.land/x/sentry/index.mjs";
4
+
5
+ Sentry.init({
6
+ dsn: "https://ca41c3f96489cc1b3e69c9a44704f7ee@o4508722276007936.ingest.de.sentry.io/4508772265558096",
7
+ defaultIntegrations: false,
8
+ // Performance Monitoring
9
+ tracesSampleRate: 1.0,
10
+ // Set sampling rate for profiling - this is relative to tracesSampleRate
11
+ profilesSampleRate: 1.0,
12
+ });
13
+
14
+ Sentry.setTag('region', Deno.env.get('SB_REGION'));
15
+ Sentry.setTag('execution_id', Deno.env.get('SB_EXECUTION_ID'));
16
 
17
  const corsHeaders = {
18
  'Access-Control-Allow-Origin': '*',
 
22
  const languagePrompts = {
23
  en: {
24
  systemPrompt: "You are helping generate words for a word-guessing game. Generate a single word in English related to the theme",
25
+ requirements: "The word should be:\n- A single word (no spaces or hyphens)\n- Common enough that people would know it\n- Specific enough to be interesting\n- Related to the theme\n- Between 4 and 12 letters\n- A singular noun (not plural)\n- NOT be any of these previously used words:"
26
  },
27
  fr: {
28
  systemPrompt: "Vous aidez à générer des mots pour un jeu de devinettes. Générez un seul mot en français lié au thème",
29
+ requirements: "Le mot doit être :\n- Un seul mot (pas d'espaces ni de traits d'union)\n- Assez courant pour que les gens le connaissent\n- Suffisamment spécifique pour être intéressant\n- En rapport avec le thème\n- Entre 4 et 12 lettres\n- Un nom commun au singulier\n- NE PAS être l'un de ces mots déjà utilisés :"
30
  },
31
  de: {
32
  systemPrompt: "Sie helfen bei der Generierung von Wörtern für ein Worträtselspiel. Generieren Sie ein einzelnes Wort auf Deutsch zum Thema",
33
+ requirements: "Das Wort sollte:\n- Ein einzelnes Wort sein (keine Leerzeichen oder Bindestriche)\n- Häufig genug, dass Menschen es kennen\n- Spezifisch genug, um interessant zu sein\n- Zum Thema passen\n- Zwischen 4 und 12 Buchstaben lang sein\n- Ein Substantiv im Singular sein\n- NICHT eines dieser bereits verwendeten Wörter sein:"
34
  },
35
  it: {
36
  systemPrompt: "Stai aiutando a generare parole per un gioco di indovinelli. Genera una singola parola in italiano legata al tema",
37
+ requirements: "La parola deve essere:\n- Una singola parola (senza spazi o trattini)\n- Abbastanza comune da essere conosciuta\n- Sufficientemente specifica da essere interessante\n- Correlata al tema\n- Tra 4 e 12 lettere\n- Un sostantivo singolare\n- NON essere una di queste parole già utilizzate:"
38
  },
39
  es: {
40
  systemPrompt: "Estás ayudando a generar palabras para un juego de adivinanzas. Genera una sola palabra en español relacionada con el tema",
41
+ requirements: "La palabra debe ser:\n- Una sola palabra (sin espacios ni guiones)\n- Lo suficientemente común para que la gente la conozca\n- Lo suficientemente específica para ser interesante\n- Relacionada con el tema\n- Entre 4 y 12 lettere\n- Un sustantivo en singular\n- NO ser ninguna de estas palabras ya utilizadas:"
42
  },
43
  pt: {
44
  systemPrompt: "Estás ajudando a gerar palavras para um jogo de adivinhação. Gere uma única palavra em português relacionada ao tema",
45
+ requirements: "A palavra deve ser:\n- Uma única palavra (sem espaços ou hífens)\n- Comum o suficiente para que as pessoas a conheçam\n- Específica o suficiente para ser interessante\n- Relacionada ao tema\n- Entre 4 e 12 letras\n- Um substantivo no singular\n- NÃO ser nenhuma destas palavras já utilizadas:"
46
  }
47
  };
48
 
49
  const openRouterModels = [
 
50
  'google/gemini-2.0-flash-exp:free',
51
+ 'mistralai/mistral-nemo'
 
52
  ];
53
 
54
+ async function generateWord(theme: string, usedWords: string[], language: string) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  const openRouterKey = Deno.env.get('OPENROUTER_API_KEY');
56
  if (!openRouterKey) {
57
  throw new Error('OpenRouter API key not configured');
 
60
  const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;
61
  const randomModel = openRouterModels[Math.floor(Math.random() * openRouterModels.length)];
62
 
63
+ console.log('Using OpenRouter with model:', randomModel);
64
 
65
  const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
66
  method: "POST",
 
104
  const { theme, usedWords = [], language = 'en' } = await req.json();
105
  console.log('Generating word for theme:', theme, 'language:', language, 'excluding:', usedWords);
106
 
 
 
 
107
  try {
108
+ const word = await generateWord(theme, usedWords, language);
109
+ console.log('Successfully generated word:', word);
110
+
111
+ return new Response(
112
+ JSON.stringify({ word }),
113
+ { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
114
+ );
115
+ } catch (error) {
116
+ Sentry.captureException(error);
117
+ console.error('Error generating word:', error);
 
 
 
 
 
118
 
 
119
  return new Response(
120
  JSON.stringify({
121
+ error: 'Failed to generate word',
122
  details: error?.message || 'Unknown error'
123
  }),
124
  {
 
127
  }
128
  );
129
  }
 
 
 
 
 
130
  } catch (error) {
131
+ Sentry.captureException(error);
132
+ console.error('Error processing request:', error);
133
+
134
  return new Response(
135
  JSON.stringify({
136
+ error: 'Error processing request',
137
  details: error.message
138
  }),
139
  {
 
142
  }
143
  );
144
  }
145
+ });
supabase/functions/generate-word/index.ts CHANGED
@@ -1,5 +1,17 @@
1
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
2
- import { Mistral } from "npm:@mistralai/mistralai";
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  const corsHeaders = {
5
  'Access-Control-Allow-Origin': '*',
@@ -46,51 +58,25 @@ const languagePrompts = {
46
  };
47
 
48
  const openRouterModels = [
49
- 'sophosympatheia/rogue-rose-103b-v0.2:free',
50
  'google/gemini-2.0-flash-exp:free',
51
- 'meta-llama/llama-3.1-70b-instruct:free',
52
- 'microsoft/phi-3-medium-128k-instruct:free'
53
  ];
54
 
55
- async function tryMistral(currentWord: string, existingSentence: string, language: string) {
56
- const client = new Mistral({
57
- apiKey: Deno.env.get('MISTRAL_API_KEY'),
58
- });
59
-
60
- const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;
61
-
62
- const response = await client.chat.complete({
63
- model: "mistral-large-latest",
64
- messages: [
65
- {
66
- role: "system",
67
- content: `${prompts.systemPrompt} "${currentWord}". ${prompts.task} ${prompts.instruction} "${existingSentence}". ${prompts.noQuotes}`
68
- }
69
- ],
70
- maxTokens: 50,
71
- temperature: 0.5
72
- });
73
-
74
- const aiResponse = response.choices[0].message.content.trim();
75
- console.log('Mistral full response:', aiResponse);
76
-
77
- return aiResponse
78
- .slice(existingSentence.length)
79
- .trim()
80
- .split(' ')[0]
81
- .replace(/[.,!?]$/, '');
82
- }
83
 
84
- async function tryOpenRouter(currentWord: string, existingSentence: string, language: string) {
85
  const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;
86
  const randomModel = openRouterModels[Math.floor(Math.random() * openRouterModels.length)];
87
 
88
- console.log('Trying OpenRouter with model:', randomModel);
89
 
90
  const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
91
  method: "POST",
92
  headers: {
93
- "Authorization": `Bearer ${Deno.env.get('OPENROUTER_API_KEY')}`,
94
  "HTTP-Referer": "https://think-in-sync.com",
95
  "X-Title": "Think in Sync",
96
  "Content-Type": "application/json"
@@ -107,18 +93,33 @@ async function tryOpenRouter(currentWord: string, existingSentence: string, lang
107
  });
108
 
109
  if (!response.ok) {
110
- throw new Error(`OpenRouter API error: ${response.status}`);
 
 
 
 
 
 
111
  }
112
 
113
  const data = await response.json();
 
 
 
 
 
 
 
114
  const aiResponse = data.choices[0].message.content.trim();
115
- console.log('OpenRouter full response:', aiResponse);
116
 
117
- return aiResponse
118
  .slice(existingSentence.length)
119
  .trim()
120
  .split(' ')[0]
121
  .replace(/[.,!?]$/, '');
 
 
122
  }
123
 
124
  serve(async (req) => {
@@ -133,28 +134,44 @@ serve(async (req) => {
133
  const existingSentence = currentSentence || '';
134
 
135
  try {
136
- console.log('Attempting with Mistral...');
137
- const word = await tryMistral(currentWord, existingSentence, language);
138
- console.log('Successfully generated word with Mistral:', word);
139
  return new Response(
140
- JSON.stringify({ word }),
141
  { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
142
  );
143
- } catch (mistralError) {
144
- console.error('Mistral error:', mistralError);
145
- console.log('Falling back to OpenRouter...');
 
 
 
 
146
 
147
- const word = await tryOpenRouter(currentWord, existingSentence, language);
148
- console.log('Successfully generated word with OpenRouter:', word);
149
  return new Response(
150
- JSON.stringify({ word }),
151
- { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
 
 
 
 
 
 
152
  );
153
  }
154
  } catch (error) {
155
- console.error('Error generating word:', error);
 
 
 
 
 
 
156
  return new Response(
157
- JSON.stringify({ error: error.message }),
 
 
 
158
  {
159
  status: 500,
160
  headers: { ...corsHeaders, 'Content-Type': 'application/json' }
 
1
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
2
+ import * as Sentry from "https://deno.land/x/sentry/index.mjs";
3
+
4
+ Sentry.init({
5
+ dsn: "https://ca41c3f96489cc1b3e69c9a44704f7ee@o4508722276007936.ingest.de.sentry.io/4508772265558096",
6
+ defaultIntegrations: false,
7
+ // Performance Monitoring
8
+ tracesSampleRate: 1.0,
9
+ // Set sampling rate for profiling - this is relative to tracesSampleRate
10
+ profilesSampleRate: 1.0,
11
+ });
12
+
13
+ Sentry.setTag('region', Deno.env.get('SB_REGION'));
14
+ Sentry.setTag('execution_id', Deno.env.get('SB_EXECUTION_ID'));
15
 
16
  const corsHeaders = {
17
  'Access-Control-Allow-Origin': '*',
 
58
  };
59
 
60
  const openRouterModels = [
 
61
  'google/gemini-2.0-flash-exp:free',
62
+ 'mistralai/mistral-nemo'
 
63
  ];
64
 
65
+ async function generateWord(currentWord: string, existingSentence: string, language: string) {
66
+ const openRouterKey = Deno.env.get('OPENROUTER_API_KEY');
67
+ if (!openRouterKey) {
68
+ throw new Error('OpenRouter API key not configured');
69
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
 
71
  const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;
72
  const randomModel = openRouterModels[Math.floor(Math.random() * openRouterModels.length)];
73
 
74
+ console.log('Using OpenRouter with model:', randomModel);
75
 
76
  const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
77
  method: "POST",
78
  headers: {
79
+ "Authorization": `Bearer ${openRouterKey}`,
80
  "HTTP-Referer": "https://think-in-sync.com",
81
  "X-Title": "Think in Sync",
82
  "Content-Type": "application/json"
 
93
  });
94
 
95
  if (!response.ok) {
96
+ const errorText = await response.text();
97
+ console.error('OpenRouter API error response:', {
98
+ status: response.status,
99
+ statusText: response.statusText,
100
+ body: errorText
101
+ });
102
+ throw new Error(`OpenRouter API error (${response.status}): ${errorText}`);
103
  }
104
 
105
  const data = await response.json();
106
+ console.log('OpenRouter raw response:', data);
107
+
108
+ if (!data?.choices?.[0]?.message?.content) {
109
+ console.error('Invalid OpenRouter API response structure:', data);
110
+ throw new Error('Received invalid response structure from OpenRouter API');
111
+ }
112
+
113
  const aiResponse = data.choices[0].message.content.trim();
114
+ console.log('OpenRouter processed response:', aiResponse);
115
 
116
+ const word = aiResponse
117
  .slice(existingSentence.length)
118
  .trim()
119
  .split(' ')[0]
120
  .replace(/[.,!?]$/, '');
121
+
122
+ return { word, model: randomModel };
123
  }
124
 
125
  serve(async (req) => {
 
134
  const existingSentence = currentSentence || '';
135
 
136
  try {
137
+ const { word, model } = await generateWord(currentWord, existingSentence, language);
138
+ console.log('Successfully generated word:', word, 'using model:', model);
 
139
  return new Response(
140
+ JSON.stringify({ word, model }),
141
  { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
142
  );
143
+ } catch (error) {
144
+ console.error('OpenRouter API error:', {
145
+ error: error,
146
+ message: error.message,
147
+ stack: error.stack
148
+ });
149
+ Sentry.captureException(error);
150
 
 
 
151
  return new Response(
152
+ JSON.stringify({
153
+ error: 'Failed to generate word',
154
+ details: error.message
155
+ }),
156
+ {
157
+ status: 500,
158
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' }
159
+ }
160
  );
161
  }
162
  } catch (error) {
163
+ console.error('Fatal error in generate-word function:', {
164
+ error: error,
165
+ message: error.message,
166
+ stack: error.stack
167
+ });
168
+ Sentry.captureException(error);
169
+
170
  return new Response(
171
+ JSON.stringify({
172
+ error: error.message,
173
+ details: process.env.NODE_ENV === 'development' ? error.stack : undefined
174
+ }),
175
  {
176
  status: 500,
177
  headers: { ...corsHeaders, 'Content-Type': 'application/json' }
supabase/functions/guess-word/index.ts CHANGED
@@ -1,5 +1,15 @@
1
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
2
- import { Mistral } from "npm:@mistralai/mistralai";
 
 
 
 
 
 
 
 
 
 
3
 
4
  const corsHeaders = {
5
  'Access-Control-Allow-Origin': '*',
@@ -8,105 +18,100 @@ const corsHeaders = {
8
 
9
  const languagePrompts = {
10
  en: {
11
- systemPrompt: "You are helping in a word guessing game. Given a description, guess what single word is being described. The described word itself was not allowed in the description, so do not expect it to appear.",
12
  instruction: "Based on this description",
13
- responseInstruction: "Respond with ONLY the word you think is being described, in uppercase letters. Do not add any explanation or punctuation."
14
  },
15
  fr: {
16
- systemPrompt: "Vous aidez dans un jeu de devinettes. À partir d'une description, devinez le mot unique qui est décrit. Le mot décrit n'était pas autorisé dans la description, ne vous attendez donc pas à le voir apparaître.",
17
  instruction: "D'après cette description",
18
- responseInstruction: "Répondez uniquement par le mot que vous pensez être décrit, en lettres majuscules. N'ajoutez aucune explication ni ponctuation."
19
  },
20
  de: {
21
- systemPrompt: "Sie helfen bei einem Worträtsel. Erraten Sie anhand einer Beschreibung, welches einzelne Wort beschrieben wird. Das beschriebene Wort durfte nicht in der Beschreibung verwendet werden, also erwarten Sie es nicht.",
22
  instruction: "Basierend auf dieser Beschreibung",
23
- responseInstruction: "Antworten Sie nur mit dem Wort, das Sie für beschrieben halten, in Großbuchstaben. Fügen Sie keine Erklärungen oder Satzzeichen hinzu."
24
  },
25
  it: {
26
- systemPrompt: "Stai aiutando in un gioco di indovinelli. Data una descrizione, indovina quale singola parola viene descritta. La parola descritta non era permessa nella descrizione, quindi non aspettarti di trovarla.",
27
  instruction: "Basandoti su questa descrizione",
28
- responseInstruction: "Rispondi solo con la parola che pensi venga descritta, in lettere maiuscole. Non aggiungere spiegazioni o punteggiatura."
29
  },
30
  es: {
31
- systemPrompt: "Estás ayudando en un juego de adivinanzas. Dada una descripción, adivina qué palabra única se está describiendo. La palabra descrita no estaba permitida en la descripción, así que no esperes verla.",
32
  instruction: "Basándote en esta descripción",
33
- responseInstruction: "Responde únicamente con la palabra que crees que se está describiendo, en letras mayúsculas. No añadas ninguna explicación ni puntuación."
34
  },
35
  pt: {
36
- systemPromp: "Estás ajudando em um jogo de adivinhação. Dada uma descrição, adivinha qual palavra única está sendo descrita. A palavra descrita não foi permitida na descrição, então não espere vê-la.",
37
  instruction: "Com base nesta descrição",
38
- responseInstruction: "Responda apenas com a palavra que você acredita estar sendo descrita, em letras maiúsculas. Não adicione nenhuma explicação nem pontuação."
39
  }
40
  };
41
 
42
  const openRouterModels = [
43
- 'sophosympatheia/rogue-rose-103b-v0.2:free',
44
  'google/gemini-2.0-flash-exp:free',
45
- 'meta-llama/llama-3.1-70b-instruct:free',
46
- 'microsoft/phi-3-medium-128k-instruct:free'
47
  ];
48
 
49
- async function tryMistral(sentence: string, language: string) {
50
- const client = new Mistral({
51
- apiKey: Deno.env.get('MISTRAL_API_KEY'),
52
- });
53
-
54
  const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;
 
55
 
56
- const response = await client.chat.complete({
57
- model: "mistral-large-latest",
58
- messages: [
59
- {
60
- role: "system",
61
- content: `${prompts.systemPrompt} ${prompts.responseInstruction}`
 
 
 
 
62
  },
63
- {
64
- role: "user",
65
- content: `${prompts.instruction} "${sentence}"`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
- ],
68
- maxTokens: 50,
69
- temperature: 0.1
70
- });
71
-
72
- return response.choices[0].message.content.trim().toUpperCase();
73
- }
74
 
75
- async function tryOpenRouter(sentence: string, language: string) {
76
- const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;
77
- const randomModel = openRouterModels[Math.floor(Math.random() * openRouterModels.length)];
78
 
79
- console.log('Trying OpenRouter with model:', randomModel);
80
-
81
- const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
82
- method: "POST",
83
- headers: {
84
- "Authorization": `Bearer ${Deno.env.get('OPENROUTER_API_KEY')}`,
85
- "HTTP-Referer": "https://think-in-sync.com",
86
- "X-Title": "Think in Sync",
87
- "Content-Type": "application/json"
88
- },
89
- body: JSON.stringify({
90
- model: randomModel,
91
- messages: [
92
- {
93
- role: "system",
94
- content: `${prompts.systemPrompt} ${prompts.responseInstruction}`
95
- },
96
- {
97
- role: "user",
98
- content: `${prompts.instruction} "${sentence}"`
99
- }
100
- ]
101
- })
102
- });
103
-
104
- if (!response.ok) {
105
- throw new Error(`OpenRouter API error: ${response.status}`);
106
  }
107
-
108
- const data = await response.json();
109
- return data.choices[0].message.content.trim().toUpperCase();
110
  }
111
 
112
  serve(async (req) => {
@@ -118,31 +123,23 @@ serve(async (req) => {
118
  const { sentence, language = 'en' } = await req.json();
119
  console.log('Trying to guess word from sentence:', sentence, 'language:', language);
120
 
121
- try {
122
- console.log('Attempting with Mistral...');
123
- const guess = await tryMistral(sentence, language);
124
- console.log('Successfully generated guess with Mistral:', guess);
125
- return new Response(
126
- JSON.stringify({ guess }),
127
- { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
128
- );
129
- } catch (mistralError) {
130
- console.error('Mistral error:', mistralError);
131
- console.log('Falling back to OpenRouter...');
132
-
133
- const guess = await tryOpenRouter(sentence, language);
134
- console.log('Successfully generated guess with OpenRouter:', guess);
135
- return new Response(
136
- JSON.stringify({ guess }),
137
- { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
138
- );
139
- }
140
  } catch (error) {
 
141
  console.error('Error generating guess:', error);
 
142
  return new Response(
143
- JSON.stringify({ error: error.message }),
 
 
144
  {
145
- status: 500,
146
  headers: { ...corsHeaders, 'Content-Type': 'application/json' }
147
  }
148
  );
 
1
  import { serve } from "https://deno.land/[email protected]/http/server.ts";
2
+ import * as Sentry from "https://deno.land/x/sentry/index.mjs";
3
+
4
+ Sentry.init({
5
+ dsn: "https://ca41c3f96489cc1b3e69c9a44704f7ee@o4508722276007936.ingest.de.sentry.io/4508772265558096",
6
+ defaultIntegrations: false,
7
+ tracesSampleRate: 1.0,
8
+ profilesSampleRate: 1.0,
9
+ });
10
+
11
+ Sentry.setTag('region', Deno.env.get('SB_REGION'));
12
+ Sentry.setTag('execution_id', Deno.env.get('SB_EXECUTION_ID'));
13
 
14
  const corsHeaders = {
15
  'Access-Control-Allow-Origin': '*',
 
18
 
19
  const languagePrompts = {
20
  en: {
21
+ systemPrompt: "You are helping in a word guessing game. Given a description, guess what single word is being described. The word must be a singular noun. The described word itself was not allowed in the description, so do not expect it to appear.",
22
  instruction: "Based on this description",
23
+ responseInstruction: "Respond with ONLY the word you think is being described, in uppercase letters. Do not add any explanation or punctuation. ONLY respond with ONE word, nothing else."
24
  },
25
  fr: {
26
+ systemPrompt: "Vous aidez dans un jeu de devinettes. À partir d'une description, devinez le mot unique qui est décrit. Le mot doit être un nom commun au singulier. Le mot décrit n'était pas autorisé dans la description, ne vous attendez donc pas à le voir apparaître.",
27
  instruction: "D'après cette description",
28
+ responseInstruction: "Répondez uniquement par le mot que vous pensez être décrit, en lettres majuscules. N'ajoutez aucune explication ni ponctuation. Répondez uniquement com um palavra, nada mais."
29
  },
30
  de: {
31
+ systemPrompt: "Sie helfen bei einem Worträtsel. Erraten Sie anhand einer Beschreibung, welches einzelne Wort beschrieben wird. Das Wort muss ein Substantiv im Singular sein. Das beschriebene Wort durfte nicht in der Beschreibung verwendet werden, also erwarten Sie es nicht.",
32
  instruction: "Basierend auf dieser Beschreibung",
33
+ responseInstruction: "Antworten Sie nur mit dem Wort, das Sie für beschrieben halten, in Großbuchstaben. Fügen Sie keine Erklärungen oder Satzzeichen hinzu. Antworten Sie nur mit einem Wort, nichts anderes."
34
  },
35
  it: {
36
+ systemPrompt: "Stai aiutando in un gioco di indovinelli. Data una descrizione, indovina quale singola parola viene descritta. La parola deve essere un sostantivo singolare. La parola descritta non era permessa nella descrizione, quindi non aspettarti di trovarla.",
37
  instruction: "Basandoti su questa descrizione",
38
+ responseInstruction: "Rispondi solo con la parola che pensi venga descritta, in lettere maiuscole. Non aggiungere spiegazioni o punteggiatura. Rispondi solo con una parola, nient'altro."
39
  },
40
  es: {
41
+ systemPrompt: "Estás ayudando en un juego de adivinanzas. Dada una descripción, adivina qué palabra única se está describiendo. La palabra debe ser un sustantivo singular. La palabra descrita no estaba permitida en la descripción, así que no esperes verla.",
42
  instruction: "Basándote en esta descripción",
43
+ responseInstruction: "Responde únicamente con la palabra que crees que se está describiendo, en letras mayúsculas. No añadas ninguna explicación ni puntuación. Responde únicamente con una palabra, nada más."
44
  },
45
  pt: {
46
+ systemPrompt: "Estás ajudando em um jogo de adivinhação. Dada uma descrição, adivinha qual palavra única está sendo descrita. A palavra deve ser um substantivo singular. A palavra descrita não foi permitida na descrição, então não espere vê-la.",
47
  instruction: "Com base nesta descrição",
48
+ responseInstruction: "Responda apenas com a palavra que você acredita estar sendo descrita, em letras maiúsculas. Não adicione nenhuma explicação nem pontuação. Responda apenas com uma palavra, nada mais."
49
  }
50
  };
51
 
52
  const openRouterModels = [
 
53
  'google/gemini-2.0-flash-exp:free',
54
+ 'mistralai/mistral-nemo'
 
55
  ];
56
 
57
+ async function generateGuess(sentence: string, language: string) {
 
 
 
 
58
  const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;
59
+ const randomModel = openRouterModels[Math.floor(Math.random() * openRouterModels.length)];
60
 
61
+ console.log('Using OpenRouter with model:', randomModel);
62
+
63
+ try {
64
+ const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
65
+ method: "POST",
66
+ headers: {
67
+ "Authorization": `Bearer ${Deno.env.get('OPENROUTER_API_KEY')}`,
68
+ "HTTP-Referer": "https://think-in-sync.com",
69
+ "X-Title": "Think in Sync",
70
+ "Content-Type": "application/json"
71
  },
72
+ body: JSON.stringify({
73
+ model: randomModel,
74
+ messages: [
75
+ {
76
+ role: "system",
77
+ content: `${prompts.systemPrompt} ${prompts.responseInstruction}`
78
+ },
79
+ {
80
+ role: "user",
81
+ content: `${prompts.instruction} "${sentence}"`
82
+ }
83
+ ]
84
+ })
85
+ });
86
+
87
+ if (!response.ok) {
88
+ const errorText = await response.text();
89
+ console.error('OpenRouter API error:', {
90
+ status: response.status,
91
+ statusText: response.statusText,
92
+ body: errorText
93
+ });
94
+
95
+ if (response.status === 402) {
96
+ throw new Error('The AI service has reached its rate limit. Please try again in a few moments.');
97
  }
 
 
 
 
 
 
 
98
 
99
+ throw new Error(`OpenRouter API error (${response.status}): ${errorText}`);
100
+ }
 
101
 
102
+ const data = await response.json();
103
+ return {
104
+ guess: data.choices[0].message.content.trim().toUpperCase(),
105
+ model: randomModel
106
+ };
107
+ } catch (error) {
108
+ console.error('Error in generateGuess:', error);
109
+ // Re-throw with more user-friendly message if it's not already a custom error
110
+ if (!error.message.includes('rate limit')) {
111
+ throw new Error('Failed to generate guess. Please try again.');
112
+ }
113
+ throw error;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
 
 
 
115
  }
116
 
117
  serve(async (req) => {
 
123
  const { sentence, language = 'en' } = await req.json();
124
  console.log('Trying to guess word from sentence:', sentence, 'language:', language);
125
 
126
+ const { guess, model } = await generateGuess(sentence, language);
127
+ console.log('Successfully generated guess:', guess, 'using model:', model);
128
+
129
+ return new Response(
130
+ JSON.stringify({ guess, model }),
131
+ { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
132
+ );
 
 
 
 
 
 
 
 
 
 
 
 
133
  } catch (error) {
134
+ Sentry.captureException(error);
135
  console.error('Error generating guess:', error);
136
+
137
  return new Response(
138
+ JSON.stringify({
139
+ error: error.message || 'An unexpected error occurred',
140
+ }),
141
  {
142
+ status: error.message.includes('rate limit') ? 429 : 500,
143
  headers: { ...corsHeaders, 'Content-Type': 'application/json' }
144
  }
145
  );
supabase/functions/submit-high-score/index.ts CHANGED
@@ -1,4 +1,17 @@
1
- import { createClient } from 'https://esm.sh/@supabase/[email protected]'
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  const corsHeaders = {
4
  'Access-Control-Allow-Origin': '*',
@@ -55,9 +68,8 @@ Deno.serve(async (req) => {
55
  })
56
 
57
  // Verify that claimed score matches actual successful rounds
58
- // TODO FIX ME AGAIN
59
- // if (score !== successfulRounds) {
60
- if (0 === 1) {
61
  return new Response(
62
  JSON.stringify({
63
  error: 'Score verification failed',
@@ -96,6 +108,7 @@ Deno.serve(async (req) => {
96
  },
97
  )
98
  } catch (error) {
 
99
  console.error('Error:', error.message)
100
  return new Response(
101
  JSON.stringify({ error: error.message }),
@@ -105,4 +118,4 @@ Deno.serve(async (req) => {
105
  },
106
  )
107
  }
108
- })
 
1
+ import { createClient } from 'https://esm.sh/@supabase/[email protected]';
2
+ import * as Sentry from "https://deno.land/x/sentry/index.mjs";
3
+
4
+ Sentry.init({
5
+ dsn: "https://ca41c3f96489cc1b3e69c9a44704f7ee@o4508722276007936.ingest.de.sentry.io/4508772265558096",
6
+ defaultIntegrations: false,
7
+ // Performance Monitoring
8
+ tracesSampleRate: 1.0,
9
+ // Set sampling rate for profiling - this is relative to tracesSampleRate
10
+ profilesSampleRate: 1.0,
11
+ });
12
+
13
+ Sentry.setTag('region', Deno.env.get('SB_REGION'));
14
+ Sentry.setTag('execution_id', Deno.env.get('SB_EXECUTION_ID'));
15
 
16
  const corsHeaders = {
17
  'Access-Control-Allow-Origin': '*',
 
68
  })
69
 
70
  // Verify that claimed score matches actual successful rounds
71
+ if (score !== successfulRounds) {
72
+ Sentry.captureException('Score verification failed')
 
73
  return new Response(
74
  JSON.stringify({
75
  error: 'Score verification failed',
 
108
  },
109
  )
110
  } catch (error) {
111
+ Sentry.captureException(error)
112
  console.error('Error:', error.message)
113
  return new Response(
114
  JSON.stringify({ error: error.message }),
 
118
  },
119
  )
120
  }
121
+ })