diff --git a/.vercel/README.txt b/.vercel/README.txt
new file mode 100644
index 0000000..525d8ce
--- /dev/null
+++ b/.vercel/README.txt
@@ -0,0 +1,11 @@
+> Why do I have a folder named ".vercel" in my project?
+The ".vercel" folder is created when you link a directory to a Vercel project.
+
+> What does the "project.json" file contain?
+The "project.json" file contains:
+- The ID of the Vercel project that you linked ("projectId")
+- The ID of the user or team your Vercel project is owned by ("orgId")
+
+> Should I commit the ".vercel" folder?
+No, you should not share the ".vercel" folder with anyone.
+Upon creation, it will be automatically added to your ".gitignore" file.
diff --git a/.vercel/project.json b/.vercel/project.json
new file mode 100644
index 0000000..2940633
--- /dev/null
+++ b/.vercel/project.json
@@ -0,0 +1 @@
+{"projectId":"prj_mviE4QuVIY1jqwDW43dnewthkKBg","orgId":"team_qnuIc1YJcQtnGmdXyWj97YF2"}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 1849579..d4581e8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
"name": "subjugator",
"version": "0.0.0",
"dependencies": {
+ "heic2any": "^0.0.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0",
@@ -24,7 +25,7 @@
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.18",
"globals": "^15.14.0",
- "vite": "^6.1.0"
+ "vite": "^6.3.5"
}
},
"node_modules/@ampproject/remapping": {
@@ -324,14 +325,13 @@
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
- "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
+ "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
"cpu": [
"ppc64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"aix"
@@ -341,14 +341,13 @@
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz",
- "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
+ "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
"cpu": [
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
@@ -358,14 +357,13 @@
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz",
- "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
+ "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
@@ -375,14 +373,13 @@
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz",
- "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
+ "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
@@ -392,14 +389,13 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz",
- "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
+ "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -409,14 +405,13 @@
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz",
- "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
+ "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -426,14 +421,13 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz",
- "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
+ "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"freebsd"
@@ -443,14 +437,13 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz",
- "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
+ "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"freebsd"
@@ -460,14 +453,13 @@
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz",
- "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
+ "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
"cpu": [
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -477,14 +469,13 @@
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz",
- "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
+ "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -494,14 +485,13 @@
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz",
- "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
+ "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
"cpu": [
"ia32"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -511,14 +501,13 @@
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz",
- "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
+ "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
"cpu": [
"loong64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -528,14 +517,13 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz",
- "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
+ "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
"cpu": [
"mips64el"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -545,14 +533,13 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz",
- "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
+ "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
"cpu": [
"ppc64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -562,14 +549,13 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz",
- "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
+ "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
"cpu": [
"riscv64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -579,14 +565,13 @@
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz",
- "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
+ "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
"cpu": [
"s390x"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -596,14 +581,13 @@
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz",
- "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
+ "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -613,14 +597,13 @@
}
},
"node_modules/@esbuild/netbsd-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz",
- "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
+ "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"netbsd"
@@ -630,14 +613,13 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz",
- "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
+ "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"netbsd"
@@ -647,14 +629,13 @@
}
},
"node_modules/@esbuild/openbsd-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz",
- "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
+ "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"openbsd"
@@ -664,14 +645,13 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz",
- "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
+ "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"openbsd"
@@ -681,14 +661,13 @@
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz",
- "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
+ "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"sunos"
@@ -698,14 +677,13 @@
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz",
- "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
+ "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -715,14 +693,13 @@
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz",
- "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
+ "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
"cpu": [
"ia32"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -732,14 +709,13 @@
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz",
- "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
+ "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -1009,266 +985,260 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz",
- "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.0.tgz",
+ "integrity": "sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==",
"cpu": [
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz",
- "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.0.tgz",
+ "integrity": "sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz",
- "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.0.tgz",
+ "integrity": "sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz",
- "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.0.tgz",
+ "integrity": "sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz",
- "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.0.tgz",
+ "integrity": "sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz",
- "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.0.tgz",
+ "integrity": "sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz",
- "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.0.tgz",
+ "integrity": "sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==",
"cpu": [
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz",
- "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.0.tgz",
+ "integrity": "sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==",
"cpu": [
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz",
- "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.0.tgz",
+ "integrity": "sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz",
- "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.0.tgz",
+ "integrity": "sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz",
- "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.0.tgz",
+ "integrity": "sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==",
"cpu": [
"loong64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz",
- "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.0.tgz",
+ "integrity": "sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==",
"cpu": [
"ppc64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz",
- "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.0.tgz",
+ "integrity": "sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.0.tgz",
+ "integrity": "sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==",
"cpu": [
"riscv64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz",
- "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.0.tgz",
+ "integrity": "sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==",
"cpu": [
"s390x"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz",
- "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.0.tgz",
+ "integrity": "sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz",
- "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.0.tgz",
+ "integrity": "sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz",
- "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.0.tgz",
+ "integrity": "sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==",
"cpu": [
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz",
- "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.0.tgz",
+ "integrity": "sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA==",
"cpu": [
"ia32"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz",
- "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.0.tgz",
+ "integrity": "sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ==",
"cpu": [
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -1326,11 +1296,10 @@
"license": "MIT"
},
"node_modules/@types/estree": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
- "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
- "dev": true,
- "license": "MIT"
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
@@ -2143,12 +2112,11 @@
}
},
"node_modules/esbuild": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
- "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
+ "version": "0.25.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz",
+ "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==",
"dev": true,
"hasInstallScript": true,
- "license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
@@ -2156,31 +2124,31 @@
"node": ">=18"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.24.2",
- "@esbuild/android-arm": "0.24.2",
- "@esbuild/android-arm64": "0.24.2",
- "@esbuild/android-x64": "0.24.2",
- "@esbuild/darwin-arm64": "0.24.2",
- "@esbuild/darwin-x64": "0.24.2",
- "@esbuild/freebsd-arm64": "0.24.2",
- "@esbuild/freebsd-x64": "0.24.2",
- "@esbuild/linux-arm": "0.24.2",
- "@esbuild/linux-arm64": "0.24.2",
- "@esbuild/linux-ia32": "0.24.2",
- "@esbuild/linux-loong64": "0.24.2",
- "@esbuild/linux-mips64el": "0.24.2",
- "@esbuild/linux-ppc64": "0.24.2",
- "@esbuild/linux-riscv64": "0.24.2",
- "@esbuild/linux-s390x": "0.24.2",
- "@esbuild/linux-x64": "0.24.2",
- "@esbuild/netbsd-arm64": "0.24.2",
- "@esbuild/netbsd-x64": "0.24.2",
- "@esbuild/openbsd-arm64": "0.24.2",
- "@esbuild/openbsd-x64": "0.24.2",
- "@esbuild/sunos-x64": "0.24.2",
- "@esbuild/win32-arm64": "0.24.2",
- "@esbuild/win32-ia32": "0.24.2",
- "@esbuild/win32-x64": "0.24.2"
+ "@esbuild/aix-ppc64": "0.25.5",
+ "@esbuild/android-arm": "0.25.5",
+ "@esbuild/android-arm64": "0.25.5",
+ "@esbuild/android-x64": "0.25.5",
+ "@esbuild/darwin-arm64": "0.25.5",
+ "@esbuild/darwin-x64": "0.25.5",
+ "@esbuild/freebsd-arm64": "0.25.5",
+ "@esbuild/freebsd-x64": "0.25.5",
+ "@esbuild/linux-arm": "0.25.5",
+ "@esbuild/linux-arm64": "0.25.5",
+ "@esbuild/linux-ia32": "0.25.5",
+ "@esbuild/linux-loong64": "0.25.5",
+ "@esbuild/linux-mips64el": "0.25.5",
+ "@esbuild/linux-ppc64": "0.25.5",
+ "@esbuild/linux-riscv64": "0.25.5",
+ "@esbuild/linux-s390x": "0.25.5",
+ "@esbuild/linux-x64": "0.25.5",
+ "@esbuild/netbsd-arm64": "0.25.5",
+ "@esbuild/netbsd-x64": "0.25.5",
+ "@esbuild/openbsd-arm64": "0.25.5",
+ "@esbuild/openbsd-x64": "0.25.5",
+ "@esbuild/sunos-x64": "0.25.5",
+ "@esbuild/win32-arm64": "0.25.5",
+ "@esbuild/win32-ia32": "0.25.5",
+ "@esbuild/win32-x64": "0.25.5"
}
},
"node_modules/escalade": {
@@ -2437,6 +2405,20 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fdir": {
+ "version": "6.4.6",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
+ "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
+ "dev": true,
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -2510,7 +2492,6 @@
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -2777,6 +2758,11 @@
"node": ">= 0.4"
}
},
+ "node_modules/heic2any": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/heic2any/-/heic2any-0.0.4.tgz",
+ "integrity": "sha512-3lLnZiDELfabVH87htnRolZ2iehX9zwpRyGNz22GKXIu0fznlblf0/ftppXKNqS26dqFSeqfIBhAmAj/uSp0cA=="
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -3667,6 +3653,18 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/possible-typed-array-names": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
@@ -3898,13 +3896,12 @@
}
},
"node_modules/rollup": {
- "version": "4.34.8",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz",
- "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==",
+ "version": "4.44.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.0.tgz",
+ "integrity": "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "@types/estree": "1.0.6"
+ "@types/estree": "1.0.8"
},
"bin": {
"rollup": "dist/bin/rollup"
@@ -3914,25 +3911,26 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.34.8",
- "@rollup/rollup-android-arm64": "4.34.8",
- "@rollup/rollup-darwin-arm64": "4.34.8",
- "@rollup/rollup-darwin-x64": "4.34.8",
- "@rollup/rollup-freebsd-arm64": "4.34.8",
- "@rollup/rollup-freebsd-x64": "4.34.8",
- "@rollup/rollup-linux-arm-gnueabihf": "4.34.8",
- "@rollup/rollup-linux-arm-musleabihf": "4.34.8",
- "@rollup/rollup-linux-arm64-gnu": "4.34.8",
- "@rollup/rollup-linux-arm64-musl": "4.34.8",
- "@rollup/rollup-linux-loongarch64-gnu": "4.34.8",
- "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8",
- "@rollup/rollup-linux-riscv64-gnu": "4.34.8",
- "@rollup/rollup-linux-s390x-gnu": "4.34.8",
- "@rollup/rollup-linux-x64-gnu": "4.34.8",
- "@rollup/rollup-linux-x64-musl": "4.34.8",
- "@rollup/rollup-win32-arm64-msvc": "4.34.8",
- "@rollup/rollup-win32-ia32-msvc": "4.34.8",
- "@rollup/rollup-win32-x64-msvc": "4.34.8",
+ "@rollup/rollup-android-arm-eabi": "4.44.0",
+ "@rollup/rollup-android-arm64": "4.44.0",
+ "@rollup/rollup-darwin-arm64": "4.44.0",
+ "@rollup/rollup-darwin-x64": "4.44.0",
+ "@rollup/rollup-freebsd-arm64": "4.44.0",
+ "@rollup/rollup-freebsd-x64": "4.44.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.44.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.44.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.44.0",
+ "@rollup/rollup-linux-arm64-musl": "4.44.0",
+ "@rollup/rollup-linux-loongarch64-gnu": "4.44.0",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.44.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.44.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.44.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.44.0",
+ "@rollup/rollup-linux-x64-gnu": "4.44.0",
+ "@rollup/rollup-linux-x64-musl": "4.44.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.44.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.44.0",
+ "@rollup/rollup-win32-x64-msvc": "4.44.0",
"fsevents": "~2.3.2"
}
},
@@ -4314,6 +4312,22 @@
"integrity": "sha512-nNE3pnTHxXN/Phw768u0Grr7W4+rumGg/H6PgeseNJojkJtmeHJfZWi41Gp2mpXl1pg1pf1zjwR4McM1jTqkpg==",
"license": "MIT"
},
+ "node_modules/tinyglobby": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
+ "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
+ "dev": true,
+ "dependencies": {
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
"node_modules/turbo-stream": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
@@ -4472,15 +4486,17 @@
}
},
"node_modules/vite": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.1.tgz",
- "integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==",
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
+ "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "esbuild": "^0.24.2",
- "postcss": "^8.5.2",
- "rollup": "^4.30.1"
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2",
+ "postcss": "^8.5.3",
+ "rollup": "^4.34.9",
+ "tinyglobby": "^0.2.13"
},
"bin": {
"vite": "bin/vite.js"
diff --git a/package.json b/package.json
index 06a8501..d8d8b79 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "heic2any": "^0.0.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0",
@@ -26,6 +27,6 @@
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.18",
"globals": "^15.14.0",
- "vite": "^6.1.0"
+ "vite": "^6.3.5"
}
}
diff --git a/public/assets/advanced-autonomy.png b/public/assets/advanced-autonomy.png
new file mode 100644
index 0000000..4fe69fe
Binary files /dev/null and b/public/assets/advanced-autonomy.png differ
diff --git a/public/assets/logo.png b/public/assets/logo.png
new file mode 100644
index 0000000..0822acc
Binary files /dev/null and b/public/assets/logo.png differ
diff --git a/public/assets/people/adam_hamdan.png b/public/assets/people/adam_hamdan.png
new file mode 100644
index 0000000..4a0c9af
Binary files /dev/null and b/public/assets/people/adam_hamdan.png differ
diff --git a/public/assets/people/adam_mcaleer.png b/public/assets/people/adam_mcaleer.png
new file mode 100644
index 0000000..76cf73e
Binary files /dev/null and b/public/assets/people/adam_mcaleer.png differ
diff --git a/public/assets/people/adrian_fernandez.png b/public/assets/people/adrian_fernandez.png
new file mode 100644
index 0000000..e6cfe3b
Binary files /dev/null and b/public/assets/people/adrian_fernandez.png differ
diff --git a/public/assets/people/alex_johnson.png b/public/assets/people/alex_johnson.png
new file mode 100644
index 0000000..f8e945b
Binary files /dev/null and b/public/assets/people/alex_johnson.png differ
diff --git a/public/assets/people/cameron_brown.jpeg b/public/assets/people/cameron_brown.jpeg
new file mode 100644
index 0000000..3965348
Binary files /dev/null and b/public/assets/people/cameron_brown.jpeg differ
diff --git a/public/assets/people/carlos_chavez.png b/public/assets/people/carlos_chavez.png
new file mode 100644
index 0000000..7e69bd8
Binary files /dev/null and b/public/assets/people/carlos_chavez.png differ
diff --git a/public/assets/people/daniel_parra.png b/public/assets/people/daniel_parra.png
new file mode 100644
index 0000000..73a933b
Binary files /dev/null and b/public/assets/people/daniel_parra.png differ
diff --git a/public/assets/people/ethan_mitchell.png b/public/assets/people/ethan_mitchell.png
new file mode 100644
index 0000000..303187d
Binary files /dev/null and b/public/assets/people/ethan_mitchell.png differ
diff --git a/public/assets/people/joseph_goodman.png b/public/assets/people/joseph_goodman.png
new file mode 100644
index 0000000..96f2416
Binary files /dev/null and b/public/assets/people/joseph_goodman.png differ
diff --git a/public/assets/people/keith_khadar.jpg b/public/assets/people/keith_khadar.jpg
new file mode 100644
index 0000000..b7b2c04
Binary files /dev/null and b/public/assets/people/keith_khadar.jpg differ
diff --git a/public/assets/people/lester_bonilla.jpg b/public/assets/people/lester_bonilla.jpg
new file mode 100644
index 0000000..0f8ec97
Binary files /dev/null and b/public/assets/people/lester_bonilla.jpg differ
diff --git a/public/assets/people/lorant_domokos.png b/public/assets/people/lorant_domokos.png
new file mode 100644
index 0000000..91425a6
Binary files /dev/null and b/public/assets/people/lorant_domokos.png differ
diff --git a/public/assets/people/ryan_hoburg.png b/public/assets/people/ryan_hoburg.png
new file mode 100644
index 0000000..afd4552
Binary files /dev/null and b/public/assets/people/ryan_hoburg.png differ
diff --git a/public/assets/robosub_logo.png b/public/assets/robosub_logo.png
new file mode 100644
index 0000000..5fd49c0
Binary files /dev/null and b/public/assets/robosub_logo.png differ
diff --git a/public/assets/robosub_preparation.png b/public/assets/robosub_preparation.png
new file mode 100644
index 0000000..1f94864
Binary files /dev/null and b/public/assets/robosub_preparation.png differ
diff --git a/public/assets/simulation_enviornment.png b/public/assets/simulation_enviornment.png
new file mode 100644
index 0000000..128a5f1
Binary files /dev/null and b/public/assets/simulation_enviornment.png differ
diff --git a/public/assets/sponsors/JD-squared-transparent.png b/public/assets/sponsors/JD-squared-transparent.png
new file mode 100644
index 0000000..40cb0d1
Binary files /dev/null and b/public/assets/sponsors/JD-squared-transparent.png differ
diff --git a/public/assets/sponsors/MAE_logo.png b/public/assets/sponsors/MAE_logo.png
new file mode 100644
index 0000000..13443fd
Binary files /dev/null and b/public/assets/sponsors/MAE_logo.png differ
diff --git a/public/assets/sponsors/Sylphase.png b/public/assets/sponsors/Sylphase.png
new file mode 100644
index 0000000..3b53cf7
Binary files /dev/null and b/public/assets/sponsors/Sylphase.png differ
diff --git a/public/assets/sponsorship_packet.pdf b/public/assets/sponsorship_packet.pdf
new file mode 100644
index 0000000..d06cc9a
Binary files /dev/null and b/public/assets/sponsorship_packet.pdf differ
diff --git a/public/assets/subjugator8-hero.png b/public/assets/subjugator8-hero.png
new file mode 100644
index 0000000..655200b
Binary files /dev/null and b/public/assets/subjugator8-hero.png differ
diff --git a/public/assets/submarine-blueprint.png b/public/assets/submarine-blueprint.png
new file mode 100644
index 0000000..2373874
Binary files /dev/null and b/public/assets/submarine-blueprint.png differ
diff --git a/public/assets/submarines/sub9_1.jpeg b/public/assets/submarines/sub9_1.jpeg
new file mode 100644
index 0000000..810df6b
Binary files /dev/null and b/public/assets/submarines/sub9_1.jpeg differ
diff --git a/public/assets/submarines/sub9_cherry_1.png b/public/assets/submarines/sub9_cherry_1.png
new file mode 100644
index 0000000..53b5b68
Binary files /dev/null and b/public/assets/submarines/sub9_cherry_1.png differ
diff --git a/public/assets/submarines/sub9_development.jpg b/public/assets/submarines/sub9_development.jpg
new file mode 100644
index 0000000..a9a89fb
Binary files /dev/null and b/public/assets/submarines/sub9_development.jpg differ
diff --git a/public/assets/submarines/sub9_frame.png b/public/assets/submarines/sub9_frame.png
new file mode 100644
index 0000000..810d8c9
Binary files /dev/null and b/public/assets/submarines/sub9_frame.png differ
diff --git a/public/assets/submarines/subjugator_1.png b/public/assets/submarines/subjugator_1.png
new file mode 100644
index 0000000..bf0c4eb
Binary files /dev/null and b/public/assets/submarines/subjugator_1.png differ
diff --git a/public/assets/submarines/subjugator_3.png b/public/assets/submarines/subjugator_3.png
new file mode 100644
index 0000000..66f3969
Binary files /dev/null and b/public/assets/submarines/subjugator_3.png differ
diff --git a/public/assets/submarines/subjugator_6.png b/public/assets/submarines/subjugator_6.png
new file mode 100644
index 0000000..ae5a0aa
Binary files /dev/null and b/public/assets/submarines/subjugator_6.png differ
diff --git a/public/assets/submarines/subjugator_8.png b/public/assets/submarines/subjugator_8.png
new file mode 100644
index 0000000..24ae1e3
Binary files /dev/null and b/public/assets/submarines/subjugator_8.png differ
diff --git a/public/assets/submarines/subjugator_9.1.png b/public/assets/submarines/subjugator_9.1.png
new file mode 100644
index 0000000..4189d8c
Binary files /dev/null and b/public/assets/submarines/subjugator_9.1.png differ
diff --git a/public/assets/submarines/subjugator_9.png b/public/assets/submarines/subjugator_9.png
new file mode 100644
index 0000000..a50f54a
Binary files /dev/null and b/public/assets/submarines/subjugator_9.png differ
diff --git a/public/assets/team-photo.jpg b/public/assets/team-photo.jpg
new file mode 100644
index 0000000..107766e
Binary files /dev/null and b/public/assets/team-photo.jpg differ
diff --git a/src/App.css b/src/App.css
index b9d355d..2f3fce3 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,3 +1,7 @@
+:root {
+ --navbar-height: 80px;
+}
+
#root {
max-width: 1280px;
margin: 0 auto;
@@ -40,3 +44,7 @@
.read-the-docs {
color: #888;
}
+
+.main-content {
+ padding-top: var(--navbar-height);
+}
diff --git a/src/App.jsx b/src/App.jsx
index fee585b..8c86e47 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,7 +1,7 @@
-// App.jsx
import React from "react";
-import { Routes, Route } from "react-router-dom";
+import { Routes, Route, useLocation } from "react-router-dom";
import Navbar from "./Components/Navbar";
+import ScrollToTop from "./Pages/ScrollToTop";
import Home from "./Pages/Home";
import AboutUs from "./Pages/AboutUs";
import Contact from "./Pages/Contact";
@@ -12,10 +12,14 @@ import OurTeam from "./Pages/OurTeam";
import "./App.css";
function App() {
+ const location = useLocation();
+ const isHome = location.pathname === "/";
+
return (
-
+
+
} />
} />
@@ -26,9 +30,8 @@ function App() {
} />
- {/* We'll add a footer component later */}
);
}
-export default App;
\ No newline at end of file
+export default App;
diff --git a/src/Components/Navbar.css b/src/Components/Navbar.css
index 504a04a..1fcd05e 100644
--- a/src/Components/Navbar.css
+++ b/src/Components/Navbar.css
@@ -24,12 +24,16 @@
padding: 0 var(--space-lg);
}
+
.nav-logo {
- height: 45px;
- width: auto;
+ --logo-h: clamp(135px, 6vw, 130px);
+ height: var(--logo-h);
+ width: calc(var(--logo-h) * 3.1);
+ background: url("/src/assets/subjugator_logo.png") center/contain no-repeat;
transition: opacity var(--transition-fast);
}
+
.nav-logo:hover {
opacity: 0.8;
}
diff --git a/src/Components/Navbar.jsx b/src/Components/Navbar.jsx
index 2f72180..2ce67b7 100644
--- a/src/Components/Navbar.jsx
+++ b/src/Components/Navbar.jsx
@@ -46,12 +46,7 @@ function Navbar() {
{/* Logo */}
-
-
+
{/* Navigation */}
diff --git a/src/Pages/AUVTechnology.jsx b/src/Pages/AUVTechnology.jsx
index 000a38d..7adb1eb 100644
--- a/src/Pages/AUVTechnology.jsx
+++ b/src/Pages/AUVTechnology.jsx
@@ -1,54 +1,78 @@
import React, { useEffect, useRef, useState } from "react";
-import { Link } from "react-router-dom";
+import { useLocation, Link } from "react-router-dom";
import {
FaCogs,
FaBolt,
FaLaptopCode,
FaInfoCircle,
- FaArrowsAlt,
FaExpand,
} from "react-icons/fa";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import "../styles/AUVTechnology.css";
-
-// Helper component for hotspots that appear on the 3D model
-const Hotspot = ({ id, title, isActive, onClick }) => {
- return (
-
-
-
-
-
{title}
+import techReport from "../assets/Design_and_Development_of_SubjuGator_9.pdf";
+
+// Hotspot button on the model
+const Hotspot = ({ id, title, isActive, onClick }) => (
+
+);
+
+// Specification card below the 3D canvas
+const SpecCard = ({ icon, title, description, list }) => (
+
+
{icon}
+
{title}
+
{description}
+ {list && (
+
+ {list.map((item, i) => (
+ {item}
+ ))}
+
+ )}
+
+);
+
+export default function AUVTechnology() {
+ const location = useLocation();
+
+ // 1) Keep --vh up to date for mobile address-bar hiding
+ useEffect(() => {
+ const setVh = () =>
+ document.documentElement.style.setProperty(
+ "--vh",
+ `${window.innerHeight * 0.01}px`
+ );
+ setVh();
+ window.addEventListener("resize", setVh);
+ window.addEventListener("orientationchange", setVh);
+ return () => {
+ window.removeEventListener("resize", setVh);
+ window.removeEventListener("orientationchange", setVh);
+ };
+ }, []);
-// Helper component for technical specifications
-const SpecCard = ({ icon, title, description, list }) => {
- return (
-
-
{icon}
-
{title}
-
{description}
- {list && (
-
- {list.map((item, index) => (
- {item}
- ))}
-
- )}
-
- );
-};
+ // 2) Smooth-scroll to anchors
+ useEffect(() => {
+ if (location.hash) {
+ setTimeout(() => {
+ const el = document.querySelector(location.hash);
+ if (el) el.scrollIntoView({ behavior: "smooth" });
+ }, 100);
+ }
+ }, [location.hash]);
-function AUVTechnology() {
- // Refs for DOM elements and Three.js objects
+ // Three.js refs
const canvasContainerRef = useRef(null);
const canvasRef = useRef(null);
const sceneRef = useRef(null);
@@ -56,101 +80,25 @@ function AUVTechnology() {
const rendererRef = useRef(null);
const controlsRef = useRef(null);
const modelRef = useRef(null);
- const animationFrameRef = useRef(null);
+ const frameRef = useRef(null);
- // State for UI and interactions
- const [activeSection, setActiveSection] = useState("overview");
+ // UI state
const [activeHotspot, setActiveHotspot] = useState(null);
const [isLoading, setIsLoading] = useState(true);
- const [viewMode, setViewMode] = useState("complete"); // complete or exploded
- const [infoVisible, setInfoVisible] = useState(true);
const [isModelLoaded, setIsModelLoaded] = useState(false);
+ const [viewMode, setViewMode] = useState("complete");
+ const [infoVisible, setInfoVisible] = useState(true);
- // Define hotspots to display on the model
+ // Hotspot definitions
const hotspots = [
- {
- id: "thrusters",
- title: "Thrusters",
- position: { x: 0.3, y: 0.1, z: 0.2 },
- },
- {
- id: "camera",
- title: "Vision System",
- position: { x: -0.2, y: 0.15, z: 0.3 },
- },
- { id: "mainHull", title: "Main Hull", position: { x: 0, y: 0, z: 0 } },
- {
- id: "torpedos",
- title: "Torpedo System",
- position: { x: 0.4, y: 0, z: -0.2 },
- },
- {
- id: "gripper",
- title: "Gripper",
- position: { x: -0.35, y: -0.1, z: 0.15 },
- },
+ { id: "thrusters", title: "Thrusters" },
+ { id: "camera", title: "Vision System" },
+ { id: "mainHull", title: "Main Hull" },
+ { id: "torpedos", title: "Torpedo System" },
+ { id: "gripper", title: "Gripper" },
];
- // Function to update hotspot positions - now inside the component
- const updateHotspotPositions = () => {
- if (
- !modelRef.current ||
- !cameraRef.current ||
- !sceneRef.current ||
- !canvasRef.current
- )
- return;
-
- // Get the canvas dimensions for calculations
- const canvas = canvasRef.current;
- const rect = canvas.getBoundingClientRect();
-
- // - Thrusters are now positioned at the rear (underside)
- // - Camera (vision system) is raised on the front
- // - Main Hull remains centered
- // - Torpedo system is placed on the front right
- // - Gripper is placed on the front left
- const attachmentPoints = {
- thrusters: new THREE.Vector3(0, -0.1, -0.3),
- camera: new THREE.Vector3(0, 0.05, 0.2),
- mainHull: new THREE.Vector3(0, 0, 0),
- torpedos: new THREE.Vector3(0.1, -0.01, 0.15),
- gripper: new THREE.Vector3(-0.5, 0.1, -0.35),
- };
-
- hotspots.forEach((hotspot) => {
- if (!attachmentPoints[hotspot.id]) return;
- const point = attachmentPoints[hotspot.id].clone();
-
- // Convert model space to world space
- if (modelRef.current) {
- const worldMatrix = modelRef.current.matrixWorld.clone();
- point.applyMatrix4(worldMatrix);
- }
-
- // Project 3D point to 2D screen coordinates
- point.project(cameraRef.current);
-
- // Convert to CSS coordinates
- const x = (point.x * 0.5 + 0.5) * rect.width;
- const y = (-point.y * 0.5 + 0.5) * rect.height;
-
- // Check if point is in front of the camera (z between -1 and 1 after projection)
- const visible = point.z > -1 && point.z < 1;
-
- // Update hotspot DOM element position
- const hotspotElement = document.querySelector(
- `.model-hotspot[data-id="${hotspot.id}"]`
- );
- if (hotspotElement) {
- hotspotElement.style.left = `${x}px`;
- hotspotElement.style.top = `${y}px`;
- hotspotElement.style.visibility = visible ? "visible" : "hidden";
- }
- });
- };
-
- // Technical specifications for each system
+ // Technical specifications data
const technicalSpecs = {
mechanical: {
icon:
,
@@ -158,10 +106,10 @@ function AUVTechnology() {
description:
"SubjuGator features precision-engineered mechanical systems, including servo-actuated mechanisms and a carbon fiber frame.",
list: [
- "Servo-actuated gripper with serrated aluminum jaws",
+ "Servo-actuated gripper with serrated jaws",
"Dual torpedo launchers with rack and pinion actuators",
- "Marker dropper with rotational mechanism",
- "Eight-thruster configuration for redundant motion control",
+ "Ball dropper with rotational mechanism",
+ "Eight-thruster configuration for robust motion control",
"Carbon fiber and aluminum space-frame chassis",
],
},
@@ -172,7 +120,6 @@ function AUVTechnology() {
"Custom-designed electrical infrastructure provides reliable power, communications, and sensor integration.",
list: [
"Battery monitoring system with voltage and current tracking",
- "CAN bus for internal communications",
"Water-cooling system for optimal thermal management",
"Custom thruster/kill board for safety and control",
"Multi-level power regulation for various subsystems",
@@ -184,7 +131,7 @@ function AUVTechnology() {
description:
"Built on ROS (Robot Operating System), SubjuGator's software enables advanced autonomy and perception.",
list: [
- "Custom state estimation using unscented Kalman filter",
+ "Custom state estimation using Extended Kalman filter",
"Trajectory generation and control system",
"Computer vision with deep neural networks (YOLO)",
"Asynchronous mission planning infrastructure",
@@ -193,42 +140,28 @@ function AUVTechnology() {
},
};
- // Initialize Three.js scene
+ // Initialize Three.js scene, lights, camera, controls, loader, animate
useEffect(() => {
if (!canvasRef.current) return;
- // Create scene, camera, renderer
+ // Scene
const scene = new THREE.Scene();
- sceneRef.current = scene;
scene.background = new THREE.Color(0x050505);
+ sceneRef.current = scene;
- // Adjusted lighting setup for better visibility without making the model pure white
- const ambientLight = new THREE.AmbientLight(0xffffff, 1.2); // Reduced from 2.5
- scene.add(ambientLight);
-
- // Make the directional light a bit more subtle
- const mainLight = new THREE.DirectionalLight(0xffffff, 1.8); // Reduced from 3
- mainLight.position.set(2, 5, 5);
- scene.add(mainLight);
-
- // Add a spotlight to highlight the front of the model
- const spotlight = new THREE.SpotLight(0xffffff, 1.5); // Reduced from 3
- spotlight.position.set(0, 0, 10);
- spotlight.angle = Math.PI / 6;
- spotlight.penumbra = 0.5;
- spotlight.distance = 20;
- spotlight.decay = 0.5;
- scene.add(spotlight);
-
- // Make the colored accent lights more subtle
- const blueLight = new THREE.PointLight(0x4a9fff, 1.8, 15); // Reduced from 3
- blueLight.position.set(-3, 2, 3);
- scene.add(blueLight);
-
- const orangeLight = new THREE.PointLight(0xfa4616, 1.8, 15); // Reduced from 3
- orangeLight.position.set(3, -2, -3);
- scene.add(orangeLight);
- // Create and position camera
+ // Lights
+ scene.add(new THREE.AmbientLight(0xffffff, 1.2));
+ const dir = new THREE.DirectionalLight(0xffffff, 1.8);
+ dir.position.set(2, 5, 5);
+ scene.add(dir);
+ const spot = new THREE.SpotLight(0xffffff, 1.5);
+ spot.position.set(0, 0, 10);
+ spot.angle = Math.PI / 6;
+ scene.add(spot);
+ scene.add(new THREE.PointLight(0x4a9fff, 1.8, 15));
+ scene.add(new THREE.PointLight(0xfa4616, 1.8, 15));
+
+ // Camera
const container = canvasContainerRef.current;
const camera = new THREE.PerspectiveCamera(
45,
@@ -236,689 +169,274 @@ function AUVTechnology() {
0.1,
1000
);
- cameraRef.current = camera;
camera.position.set(0, 0, 2);
+ cameraRef.current = camera;
- // Create WebGL renderer
+ // Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvasRef.current,
antialias: true,
alpha: true,
});
- rendererRef.current = renderer;
- renderer.setSize(container.clientWidth, container.clientHeight);
renderer.setPixelRatio(window.devicePixelRatio);
+ renderer.setSize(container.clientWidth, container.clientHeight);
+ rendererRef.current = renderer;
- // Add orbit controls for user interaction
+ // Controls
const controls = new OrbitControls(camera, renderer.domElement);
- controlsRef.current = controls;
controls.enableDamping = true;
controls.dampingFactor = 0.05;
- controls.enableZoom = true;
- controls.enablePan = true;
controls.autoRotate = true;
controls.autoRotateSpeed = 0.5;
+ controlsRef.current = controls;
- // Animation loop
- const animate = () => {
- animationFrameRef.current = requestAnimationFrame(animate);
-
- if (controlsRef.current) {
- controlsRef.current.update();
- }
-
- if (rendererRef.current && sceneRef.current && cameraRef.current) {
- rendererRef.current.render(sceneRef.current, cameraRef.current);
- updateHotspotPositions(); // Now properly defined within component scope
- }
- };
-
- // Start animation loop
- animate();
-
- // Handle window resize
- const handleResize = () => {
- if (!cameraRef.current || !rendererRef.current || !container) return;
-
- const width = container.clientWidth;
- const height = container.clientHeight;
-
- cameraRef.current.aspect = width / height;
- cameraRef.current.updateProjectionMatrix();
-
- rendererRef.current.setSize(width, height);
- };
-
- window.addEventListener("resize", handleResize);
-
- // Load 3D model using GLTFLoader
+ // Load model
const loader = new GLTFLoader();
-
- // Try loading the actual GLTF model
loader.load(
- "/models/subjugator.glb", // Path to model in public folder
+ "/models/subjugator.glb",
(gltf) => {
const model = gltf.scene;
- modelRef.current = model;
scene.add(model);
+ modelRef.current = model;
- // Center the model
+ // center & scale
const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3());
- model.position.x = -center.x;
- model.position.y = -center.y;
- model.position.z = -center.z;
-
- // Scale the model if needed
- const size = box.getSize(new THREE.Vector3());
- const maxDim = Math.max(size.x, size.y, size.z);
- if (maxDim > 5) {
- const scale = 5 / maxDim;
- model.scale.set(scale, scale, scale);
- }
-
- // Store original positions for exploded view
- model.traverse((child) => {
- if (child.isMesh) {
- if (child.material) {
- child.material.needsUpdate = true;
- child.material.emissive = new THREE.Color(0x111111);
- child.material.emissiveIntensity = 0.1;
- child.material.metalness = 0.4;
- child.material.roughness = 0.2;
- }
- child.userData.originalPosition = child.position.clone();
+ model.position.sub(center);
+ const size = box.getSize(new THREE.Vector3()).length();
+ if (size > 5) model.scale.setScalar(5 / size);
+
+ model.traverse((c) => {
+ if (c.isMesh) {
+ c.userData.originalPosition = c.position.clone();
+ c.material.emissive = new THREE.Color(0x111111);
+ c.material.emissiveIntensity = 0.1;
+ c.material.metalness = 0.4;
+ c.material.roughness = 0.2;
}
});
setIsModelLoaded(true);
setIsLoading(false);
},
- // Progress callback
- (xhr) => {
- console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
- },
- // Error callback - fallback to temporary model if loading fails
- (error) => {
- console.error("Error loading model:", error);
- // Create a temporary model as fallback
- const model = createTemporaryModel();
- modelRef.current = model;
- scene.add(model);
-
- // Simulate loading time
- setTimeout(() => {
- setIsLoading(false);
- setIsModelLoaded(true);
- }, 1000);
+ undefined,
+ (err) => {
+ console.error("Model load error:", err);
+ setIsLoading(false);
+ setIsModelLoaded(true);
}
);
- // Fallback model creation function
- const createTemporaryModel = () => {
- // Create a temporary submarine-like shape
- const group = new THREE.Group();
-
- // Main hull - cylinder
- const hullGeometry = new THREE.CylinderGeometry(0.5, 0.5, 2, 32);
- const hullMaterial = new THREE.MeshStandardMaterial({
- color: 0x888888,
- metalness: 0.6,
- roughness: 0.4,
- emissive: 0x111111,
- emissiveIntensity: 0.1,
- });
- const hull = new THREE.Mesh(hullGeometry, hullMaterial);
- hull.rotation.x = Math.PI / 2;
- hull.userData.originalPosition = hull.position.clone();
- hull.userData.id = "mainHull";
- group.add(hull);
-
- // Nose cone
- const noseGeometry = new THREE.ConeGeometry(0.5, 0.8, 32);
- const noseMaterial = new THREE.MeshStandardMaterial({
- color: 0x333333,
- metalness: 0.8,
- roughness: 0.2,
- });
- const nose = new THREE.Mesh(noseGeometry, noseMaterial);
- nose.rotation.x = -Math.PI / 2;
- nose.position.z = 1.4;
- nose.userData.originalPosition = nose.position.clone();
- group.add(nose);
-
- // Thrusters
- const thrusterGeometry = new THREE.CylinderGeometry(0.15, 0.15, 0.3, 16);
- const thrusterMaterial = new THREE.MeshStandardMaterial({
- color: 0x222222,
- metalness: 0.9,
- roughness: 0.1,
- });
-
- // Create 8 thrusters positioned around the hull
- const thrusterPositions = [
- { x: 0.6, y: 0.6, z: -0.5 },
- { x: -0.6, y: 0.6, z: -0.5 },
- { x: 0.6, y: -0.6, z: -0.5 },
- { x: -0.6, y: -0.6, z: -0.5 },
- { x: 0.6, y: 0.6, z: 0.5 },
- { x: -0.6, y: 0.6, z: 0.5 },
- { x: 0.6, y: -0.6, z: 0.5 },
- { x: -0.6, y: -0.6, z: 0.5 },
- ];
-
- thrusterPositions.forEach((pos, index) => {
- const thruster = new THREE.Mesh(thrusterGeometry, thrusterMaterial);
- thruster.position.set(pos.x, pos.y, pos.z);
- thruster.rotation.x = Math.PI / 2;
- thruster.userData.originalPosition = thruster.position.clone();
- thruster.userData.id = "thrusters";
- group.add(thruster);
- });
-
- // Camera dome
- const cameraGeometry = new THREE.SphereGeometry(
- 0.2,
- 32,
- 32,
- 0,
- Math.PI * 2,
- 0,
- Math.PI / 2
- );
- const cameraMaterial = new THREE.MeshStandardMaterial({
- color: 0x3366ff,
- transparent: true,
- opacity: 0.7,
- });
- const camera = new THREE.Mesh(cameraGeometry, cameraMaterial);
- camera.position.set(0, -0.5, 1);
- camera.rotation.x = Math.PI;
- camera.userData.originalPosition = camera.position.clone();
- camera.userData.id = "camera";
- group.add(camera);
-
- // Add orange accent
- const accentGeometry = new THREE.BoxGeometry(0.1, 0.1, 2.5);
- const accentMaterial = new THREE.MeshStandardMaterial({
- color: 0xfa4616,
- });
- const accent = new THREE.Mesh(accentGeometry, accentMaterial);
- accent.position.set(0, 0.53, 0);
- accent.userData.originalPosition = accent.position.clone();
- group.add(accent);
-
- return group;
+ // Animation loop
+ const animate = () => {
+ frameRef.current = requestAnimationFrame(animate);
+ controls.update();
+ renderer.render(scene, camera);
+ // updateHotspots();
};
+ animate();
- // Clean up on component unmount
+ // Resize handler
+ const onResize = () => {
+ const w = container.clientWidth;
+ const h = container.clientHeight;
+ camera.aspect = w / h;
+ camera.updateProjectionMatrix();
+ renderer.setSize(w, h);
+ };
+ window.addEventListener("resize", onResize);
return () => {
- window.removeEventListener("resize", handleResize);
-
- if (animationFrameRef.current) {
- cancelAnimationFrame(animationFrameRef.current);
- }
-
- if (rendererRef.current) {
- rendererRef.current.dispose();
- }
-
- if (sceneRef.current) {
- // Clean up Three.js objects
- while (sceneRef.current.children.length > 0) {
- const object = sceneRef.current.children[0];
- sceneRef.current.remove(object);
- }
- }
+ window.removeEventListener("resize", onResize);
+ cancelAnimationFrame(frameRef.current);
+ renderer.dispose();
};
}, []);
- // Handle exploded view toggle
+ // Exploded / complete toggle
useEffect(() => {
if (!modelRef.current) return;
-
- if (viewMode === "exploded") {
- // Move parts apart to create an exploded view
- modelRef.current.traverse((child) => {
- if (child.isMesh && child.userData.originalPosition) {
- // Calculate direction from center
- const direction = new THREE.Vector3();
- direction
- .subVectors(child.position, new THREE.Vector3(0, 0, 0))
- .normalize();
-
- // Store current position before exploding
- child.userData.preExplodedPosition = child.position.clone();
-
- // Move outward
- const explosionDistance = 1.5;
- child.position.add(direction.multiplyScalar(explosionDistance));
- }
- });
- } else {
- // Reset to original positions
- modelRef.current.traverse((child) => {
- if (child.isMesh) {
- if (child.userData.preExplodedPosition) {
- child.position.copy(child.userData.preExplodedPosition);
- } else if (child.userData.originalPosition) {
- child.position.copy(child.userData.originalPosition);
- }
- }
- });
- }
- }, [viewMode]);
-
- // Handle scroll effect to show different sections
- useEffect(() => {
- const handleScroll = () => {
- const scrollY = window.scrollY;
- const windowHeight = window.innerHeight;
-
- // Determine active section based on scroll position
- const sections = document.querySelectorAll(".section");
- sections.forEach((section) => {
- const rect = section.getBoundingClientRect();
- const sectionId = section.id;
-
- if (rect.top < windowHeight / 2 && rect.bottom > windowHeight / 2) {
- setActiveSection(sectionId);
- }
- });
-
- // Parallax effect for certain elements
- const parallaxElements = document.querySelectorAll(".parallax");
- parallaxElements.forEach((element) => {
- if (element.dataset && element.dataset.speed) {
- const speed = parseFloat(element.dataset.speed) || 0.2;
- element.style.transform = `translateY(${scrollY * speed}px)`;
- }
- });
-
- // Optional: Adjust camera or model position based on scroll
- if (modelRef.current && controlsRef.current) {
- // Example: Rotate model slightly based on scroll
- modelRef.current.rotation.y = scrollY * 0.001;
+ modelRef.current.traverse((c) => {
+ if (!c.isMesh || !c.userData.originalPosition) return;
+ if (viewMode === "exploded") {
+ const dir = c.position.clone().normalize().multiplyScalar(1.5);
+ c.position.copy(c.userData.originalPosition).add(dir);
+ } else {
+ c.position.copy(c.userData.originalPosition);
}
- };
-
- window.addEventListener("scroll", handleScroll);
- return () => window.removeEventListener("scroll", handleScroll);
- }, []);
+ });
+ }, [viewMode]);
- // Control auto-rotation based on user interaction
+ // Interaction handlers
const handleModelInteraction = () => {
- if (controlsRef.current) {
- controlsRef.current.autoRotate = false;
-
- // Resume auto-rotation after a period of inactivity
- clearTimeout(controlsRef.current.userData.rotationTimeout);
- controlsRef.current.userData.rotationTimeout = setTimeout(() => {
- if (controlsRef.current) {
- controlsRef.current.autoRotate = true;
- }
- }, 5000);
- }
+ if (controlsRef.current) controlsRef.current.autoRotate = false;
};
- // Handle hotspot clicks
- const handleHotspotClick = (hotspotId) => {
- // Toggle logic - if clicking the already active hotspot, deselect it
- if (activeHotspot === hotspotId) {
- setActiveHotspot(null); // Deselect the hotspot
-
- // Optional: Reset camera to default rotation if you want
- if (controlsRef.current) {
- controlsRef.current.autoRotate = true; // Resume auto-rotation
- }
-
- return; // Exit the function early
- }
-
- // If it's a different hotspot, select it (existing functionality)
- setActiveHotspot(hotspotId);
-
- // Move camera to focus on the selected component
- if (modelRef.current && cameraRef.current && controlsRef.current) {
- // Find the component in the model
- const targetComponent = modelRef.current.children.find(
- (child) => child.userData.id === hotspotId
- );
-
- if (targetComponent) {
- // Disable auto-rotation when focusing on a component
- controlsRef.current.autoRotate = false;
-
- // Set camera target directly
- controlsRef.current.target.copy(targetComponent.position);
+ const updateHotspotPositions = () => {
+ if (!modelRef.current || !cameraRef.current || !canvasRef.current) return;
+ const rect = canvasRef.current.getBoundingClientRect();
+ const attach = {
+ thrusters: new THREE.Vector3(0, -0.1, -0.3),
+ camera: new THREE.Vector3(0, 0.05, 0.2),
+ mainHull: new THREE.Vector3(0, 0, 0),
+ torpedos: new THREE.Vector3(0.1, -0.01, 0.15),
+ gripper: new THREE.Vector3(-0.5, 0.1, -0.35),
+ };
+ hotspots.forEach((h) => {
+ const pt = attach[h.id]?.clone();
+ if (!pt) return;
+ pt.applyMatrix4(modelRef.current.matrixWorld);
+ pt.project(cameraRef.current);
+ const x = (pt.x * 0.5 + 0.5) * rect.width;
+ const y = (-pt.y * 0.5 + 0.5) * rect.height;
+ const vis = pt.z > -1 && pt.z < 1;
+ const el = document.querySelector(`.model-hotspot[data-id="${h.id}"]`);
+ if (el) {
+ el.style.left = `${x}px`;
+ el.style.top = `${y}px`;
+ el.style.visibility = vis ? "visible" : "hidden";
}
- }
- };
-
- // Toggle between complete and exploded views
- const toggleViewMode = () => {
- setViewMode((prevMode) =>
- prevMode === "complete" ? "exploded" : "complete"
- );
+ });
};
- // Toggle information overlay visibility
- const toggleInfoVisibility = () => {
- setInfoVisible((prev) => !prev);
- };
+ useEffect(() => {
+ // on each frame draw, also update hotspots
+ const id = setInterval(() => {
+ if (isModelLoaded) updateHotspotPositions();
+ }, 100);
+ return () => clearInterval(id);
+ }, [isModelLoaded]);
return (
- {/* Hero Section with 3D Model */}
+ {/* ===== Hero ===== */}
-
-
-
-
- AUV Technology
-
-
- Exploring the innovation behind SubjuGator
-
-
- {/* 3D Model Canvas Container */}
-
- {isLoading && (
-
-
-
Loading 3D Model...
-
- )}
-
-
-
- {isModelLoaded && (
- <>
- {/* Interactive Hotspots */}
-
- {hotspots.map((hotspot) => (
- handleHotspotClick(hotspot.id)}
- />
- ))}
-
-
- {/* Model Controls */}
-
-
+
+
+ AUV Technology
+
+
+ Exploring the innovation behind SubjuGator
+
+
+ {isLoading && (
+
+ )}
+
+ {isModelLoaded && (
+ <>
+
+ {hotspots.map((hs) => (
+
+ setActiveHotspot((p) => (p === hs.id ? null : hs.id))
}
- >
-
-
- {viewMode === "complete"
- ? "Exploded View"
- : "Complete View"}
-
-
-
-
-
- {infoVisible ? "Hide Info" : "Show Info"}
-
-
- >
- )}
-
- {/* Component Information Panel */}
- {activeHotspot && infoVisible && (
-
-
{hotspots.find((h) => h.id === activeHotspot)?.title}
-
- {activeHotspot === "thrusters" &&
- "Eight-thruster configuration provides redundant six degrees of freedom control, maintaining full functionality even if one thruster fails."}
- {activeHotspot === "camera" &&
- "Computer vision system using advanced neural networks for object detection and classification underwater."}
- {activeHotspot === "mainHull" &&
- "Houses the main computer, power distribution, and electronic systems in a waterproof enclosure."}
- {activeHotspot === "torpedos" &&
- "Dual servo-actuated torpedo launchers with rack and pinion mechanisms for competition tasks."}
- {activeHotspot === "gripper" &&
- "Servo-actuated gripper with serrated aluminum jaws for manipulating underwater objects."}
-
+ />
+ ))}
- )}
-
-
-
-
- Click and drag to rotate • Scroll to zoom • Click on hotspots to
- explore
-
-
+
+
+ setViewMode((v) =>
+ v === "complete" ? "exploded" : "complete"
+ )
+ }
+ >
+ {" "}
+
+ {viewMode === "complete"
+ ? "Exploded View"
+ : "Complete View"}
+
+
+ setInfoVisible((v) => !v)}>
+ {" "}
+ {infoVisible ? "Hide Info" : "Show Info"}
+
+
+ {activeHotspot && infoVisible && (
+
+
+ {hotspots.find((h) => h.id === activeHotspot)?.title}
+
+
+ {/* Add your active-hotspot description here */}
+
+
+ )}
+ >
+ )}
- {/* Technical Specifications Section */}
+ {/* ===== Technical Specifications ===== */}
-
+
Technical Specifications
-
+
Cutting-edge systems powering autonomous underwater exploration
-
-
-
-
-
-
-
-
-
-
- {/* Feature Highlight Section */}
-
-
-
-
Key Innovations
-
-
- Pioneering advancements that set SubjuGator apart
-
-
-
-
-
- {/* Background image will be set in CSS */}
-
-
-
- Adaptive{" "}
- Control System
-
-
- Our state-of-the-art control system uses an unscented Kalman
- filter operating on manifolds to efficiently handle attitude
- singularities. The trajectory generator produces 3rd-order
- continuous trajectories while accounting for vehicle
- constraints.
-
-
- Read Research Paper
-
-
+
+
+
-
-
-
- {/* Background image will be set in CSS */}
-
-
-
- Deep Learning {" "}
- Vision
-
-
- SubjuGator combines traditional computer vision techniques with
- advanced deep neural networks (YOLO architecture) to identify
- competition elements and navigate dynamic underwater
- environments.
-
-
- Explore Vision System
-
-
-
-
-
-
- {/* Background image will be set in CSS */}
-
-
-
- Advanced{" "}
- Electro-Mechanical {" "}
- Design
-
-
- Our innovative electro-mechanical systems include custom PCB
- designs, CAN bus communications, servo-actuated mechanisms, and
- aluminum components manufactured using precision CNC and
- water-jet cutting techniques.
-
-
- See Design Details
-
-
-
-
-
-
- {/* Next Generation Section */}
-
-
-
-
SubjuGator 9
-
-
- The next generation of autonomous underwater excellence
-
-
-
-
-
- {/* This will be a background image set in CSS */}
-
-
-
Evolution of Innovation
-
- Currently in development, SubjuGator 9 represents the
- culmination of years of research and competition experience.
- With a completely redesigned aluminum chassis and electronics
- hull, this next-generation AUV will push the boundaries of
- what's possible in autonomous underwater robotics.
-
-
-
-
Enhanced Chassis
-
- Fully CNC-machined from 6061-T6 aluminum for optimal
- strength and weight
-
-
-
-
Advanced Electronics
-
- Redesigned electronics hull with improved thermal management
- and expanded sensor capacity
-
-
-
-
Next-Gen Software
-
- Enhanced autonomy algorithms and improved mission planning
- capabilities
-
-
-
-
+
- {/* Resources Section */}
+ {/* ===== Resources ===== */}
-
+
Technical Resources
-
+
In-depth documentation and research materials
-
Technical Paper
-
- Comprehensive overview of SubjuGator's design and implementation
-
+
Comprehensive overview of SubjuGator's design and implementation
- {/* Call to Action */}
+ {/* ===== Call to Action ===== */}
Experience Innovation
-
- Want to learn more about SubjuGator or get involved with our team?
-
+
Want to learn more about SubjuGator or get involved with our team?
-
+
RoboSub Competition
-
+
Meet The Team
@@ -957,5 +471,3 @@ function AUVTechnology() {
);
}
-
-export default AUVTechnology;
diff --git a/src/Pages/AboutUs.jsx b/src/Pages/AboutUs.jsx
index 07e2e53..163813e 100644
--- a/src/Pages/AboutUs.jsx
+++ b/src/Pages/AboutUs.jsx
@@ -198,7 +198,7 @@ function AboutUs() {
collaboration within the global AUV community.
- 7x AUVSI RoboSub champions
+ 5x AUVSI RoboSub champions
Consistent innovation award recipients
International recognition for technical merit
@@ -229,10 +229,7 @@ function AboutUs() {
Team Formation
@@ -255,10 +252,7 @@ function AboutUs() {
First Competition Win
@@ -281,10 +275,7 @@ function AboutUs() {
Technology Evolution
@@ -307,10 +298,8 @@ function AboutUs() {
Advanced Autonomy
@@ -333,10 +322,7 @@ function AboutUs() {
SubjuGator 9
@@ -424,7 +410,7 @@ function AboutUs() {
-
+
Meet Our Team Members
@@ -456,7 +442,7 @@ function AboutUs() {
Dr. Eric M. Schwartz
- Director, Machine Intelligence Laboratory
+ Director, SubjuGator AUV Project & Machine Intelligence Laboratory
Areas of Expertise:
@@ -467,8 +453,8 @@ function AboutUs() {
- Provides overall guidance for the SubjuGator team and
- coordinates resources across the university.
+ Provides overall guidance, invaluable insight and
+ coordinates resources across the university for the SubjuGator team.
@@ -513,7 +499,7 @@ function AboutUs() {
-
7x RoboSub Champions
+
5x RoboSub Champions
First place wins at the international AUVSI RoboSub Competition
@@ -548,7 +534,7 @@ function AboutUs() {
underwater robotics!
-
+
Contact Us
diff --git a/src/Pages/Contact.jsx b/src/Pages/Contact.jsx
index 050c984..a9ed51b 100644
--- a/src/Pages/Contact.jsx
+++ b/src/Pages/Contact.jsx
@@ -2,6 +2,8 @@ import React, { useState, useEffect, useRef } from "react";
import { Link } from "react-router-dom";
import { FaMapMarkerAlt, FaEnvelope, FaPhone, FaUsers } from "react-icons/fa";
import "../styles/Contact.css";
+import { useLocation } from "react-router-dom";
+
function Contact() {
const [formStatus, setFormStatus] = useState("");
@@ -11,6 +13,19 @@ function Contact() {
const subtitleRef = useRef(null);
const contactInfoRef = useRef(null);
const formRef = useRef(null);
+
+ useEffect(() => {
+ const hash = location.hash;
+ if (hash) {
+ // Delay to ensure the target element is rendered
+ setTimeout(() => {
+ const element = document.querySelector(hash);
+ if (element) {
+ element.scrollIntoView({ behavior: "smooth" });
+ }
+ }, 100);
+ }
+ }, [location]);
// Initialize form data
const [formData, setFormData] = useState({
@@ -120,7 +135,7 @@ function Contact() {
return (
-
8
+
9
Generations of AUVs
@@ -163,7 +205,7 @@ function Home() {
-
+
Explore Full Capabilities
@@ -178,60 +220,41 @@ function Home() {
+ {/* — 1 — */}
-
- {/* Update image will be background in CSS */}
-
+
{/* add bg via CSS */}
-
February 28, 2025
+
SubjuGator 9 Development
- Progress on our next-generation AUV including aluminum chassis
+ Progress on our new AUV including aluminum chassis
completion and electronics hull integration.
-
- Read More
-
+
Read More
-
-
- {/* Update image will be background in CSS */}
-
+ {/* — 2 — */}
+
+
+ {/* — 3 — */}
+
+
-
January 15, 2025
+
RoboSub 2025 Preparation
- Team training and technology refinement for the upcoming
+ Team testing and technology refinement for the upcoming
competition season.
-
- Read More
-
-
-
-
-
-
- {/* Update image will be background in CSS */}
-
-
-
December 10, 2024
-
End-of-Year Achievements
-
- Celebrating our accomplishments and recognizing team
- contributions.
-
-
- Read More
-
+
Read More
-
+
+
{/* Call to Action */}
@@ -242,10 +265,19 @@ function Home() {
technology. Connect with our team or support our mission.
-
+
Meet Our Team
-
+ {
+ const el = document.querySelector("#top-sponsor");
+ if (el) {
+ el.scrollIntoView({ behavior: "smooth" });
+ }
+ }}
+ >
Become a Sponsor
diff --git a/src/Pages/OurTeam.jsx b/src/Pages/OurTeam.jsx
index 200276d..adeabb1 100644
--- a/src/Pages/OurTeam.jsx
+++ b/src/Pages/OurTeam.jsx
@@ -1,12 +1,141 @@
-import React from "react";
+import React, { useEffect } from "react";
+import { useLocation } from "react-router-dom";
+import { Link } from "react-router-dom";
+import "../styles/OurTeam.css";
+/* ---------- auto-import headshots from /assets/people ---------- */
+const peopleModules = import.meta.glob(
+ "../assets/people/*.{png,jpg,jpeg,webp,gif}",
+ { eager: true }
+);
+const memberImages = Object.fromEntries(
+ Object.entries(peopleModules).map(([path, mod]) => [
+ path.split("/").pop(),
+ mod.default,
+ ])
+);
+
+const toSlug = (name) =>
+ name.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+/g, "_");
+
+const resolveImage = (slug) => {
+ for (const ext of ["png", "jpg", "jpeg", "webp", "gif"]) {
+ const key = `${slug}.${ext}`;
+ if (memberImages[key]) return memberImages[key];
+ }
+ return undefined; // fallback – no head‑shot found
+};
+
+/* ---------- card component ---------- */
+const TeamMemberCard = ({ member }) => {
+ const hasImage = Boolean(member.img);
+
+ return (
+
+ {hasImage && (
+
+
+
+ )}
+
+ {member.name}
+ {member.role}
+
+ );
+};
+
+/* ---------- page component ---------- */
function OurTeam() {
+ const rawMembers = [
+ { name: "Adam McAleer", role: "Mechanical Lead" },
+ { name: "Joseph Goodman", role: "Electrical Lead" },
+ { name: "Cameron Brown", role: "Software Lead" },
+ { name: "Adrian Fernandez", role: "Electrical Lead" },
+ { name: "Lester Bonilla", role: "Electrical Lead" },
+ { name: "Adam Hamdan", role: "Mechanical Lead" },
+ { name: "Ryan Hoburg", role: "Mechanical Lead" },
+ { name: "Alex Johnson", role: "Software Lead" },
+ { name: "Carlos Chavez", role: "Software Lead" },
+ { name: "Eric(Jack) Rainville", role: "Electrical Lead" },
+ { name: "Ethan Mitchell", role: "Electrical Member" },
+ { name: "Keith Khadar", role: "Software Lead" },
+ { name: "Daniel Parra", role: "Software Lead" },
+ { name: "Lorant Domokos", role: "Mechanical Lead" },
+
+
+ ];
+
+ /* attach images */
+ const teamMembers = rawMembers.map((m) => ({
+ ...m,
+ img: resolveImage(toSlug(m.name)),
+ }));
+
+ const location = useLocation();
+
+ useEffect(() => {
+ const hash = location.hash;
+ if (hash) {
+ // Delay to ensure the target element is rendered
+ setTimeout(() => {
+ const element = document.querySelector(hash);
+ if (element) {
+ element.scrollIntoView({ behavior: "smooth" });
+ }
+ }, 100);
+ }
+ }, [location]);
+
+
+ /* devtools verification – run once */
+ useEffect(() => {
+ console.table(teamMembers.map((m) => ({ name: m.name, imgFound: !!m.img })));
+ }, []);
return (
-
-
Our Team
-
This is a placeholder for now.
-
+
+
+
+ 2025 Team
+ Members
+
+
+
+ {/* ----- grid section ----- */}
+
+
+
+ Meet the engineers shaping SubjuGator
+
+
+
+ {teamMembers.map((member) => (
+
+ ))}
+
+
+
+
+
+
+
Passionate about underwater robotics?
+
+
+ Contact Us
+
+
+
+
+
+
);
}
-export default OurTeam;
+export default OurTeam;
\ No newline at end of file
diff --git a/src/Pages/RoboSub.jsx b/src/Pages/RoboSub.jsx
index f1eef37..0084942 100644
--- a/src/Pages/RoboSub.jsx
+++ b/src/Pages/RoboSub.jsx
@@ -1,4 +1,5 @@
import React, { useState, useEffect, useRef } from "react";
+import { useLocation } from "react-router-dom";
import { Link } from "react-router-dom";
import {
FaRobot,
@@ -69,6 +70,21 @@ function RoboSub() {
const titleRef = useRef(null);
const subtitleRef = useRef(null);
+ const location = useLocation();
+
+ useEffect(() => {
+ const hash = location.hash;
+ if (hash) {
+ // Delay to ensure the target element is rendered
+ setTimeout(() => {
+ const element = document.querySelector(hash);
+ if (element) {
+ element.scrollIntoView({ behavior: "smooth" });
+ }
+ }, 100);
+ }
+ }, [location]);
+
useEffect(() => {
// Force immediate display of elements instead of relying on animations
const heroBackground = heroBackgroundRef.current;
@@ -90,7 +106,7 @@ function RoboSub() {
return (
-
+
{/* Background image now set with inline style as fallback */}
@@ -106,9 +122,8 @@ function RoboSub() {
@@ -166,21 +181,25 @@ function RoboSub() {
Competition Vehicle
- Meet SubjuGator 8, our flagship autonomous underwater vehicle
+ Meet SubjuGator 9, our flagship autonomous underwater vehicle
-
-
SubjuGator 8 - University of Florida's AUV
+
+
Subjugator 9 - First Swim
-
SubjuGator 8
+
SubjuGator 9
- SubjuGator 8 has served as the flagship autonomous submarine for the Machine Intelligence Laboratory (MIL) at the University of Florida for the past five years. It features a modular design that allows for rapid iteration and improvement of individual components.
+ SubjuGator 9 represents the
+ culmination of years of research and competition experience.
+ With a completely redesigned aluminum chassis and electronics
+ hull, this next-generation AUV pushes the boundaries of
+ what's possible in autonomous underwater robotics.
@@ -189,24 +208,22 @@ function RoboSub() {
Computing
- Intel i9-9900k + Nvidia RTX 2080
+ Nvidia Jetson Orion NX
Power
- 22.2V LiPo Batteries
+ 14.8V LiPo Batteries
Framework
- ROS Noetic
+ ROS 2 Jazzy
-
- Technical Design Report
-
+
@@ -224,12 +241,20 @@ function RoboSub() {
Innovative Design
-
- The mechanical design of SubjuGator 8 incorporates four independently operated electronic servo mechanisms: a gripper, two torpedo launchers, and a marker dropper. These mechanisms are used to complete mission-specific tasks, and they are controlled through the servo controller board housed in a separate, compact pressure vessel.
-
+
+
+
+
Mechanisms
+
+ Three independently
+ operated electronic servo mechanisms: a gripper,
+ torpedo launcher, and a ball dropper.
+
+
+
-
Space-Frame Chassis
+
Durable Frame
Carbon fiber tubes and aluminum sheet sections provide protection for delicate components while enabling modularity.
@@ -237,17 +262,16 @@ function RoboSub() {
CNC milled and abrasive water-jetted aluminum components replaced many previously 3D printed parts for improved durability.
-
Redundant Thruster Configuration
+
Thruster Configuration
Eight thrusters provide full six degrees of freedom control with built-in redundancy for mission reliability.
-
+
-
Servo Actuators
-
Waterproof servo system ensures reliable actuation for all manipulation tasks
+
SubjuGator 9 Frame
@@ -268,18 +292,17 @@ function RoboSub() {
-
+
Student-Designed PCBs
-
Custom boards for thruster control, power management, and sensor integration
Robust Electrical Systems
- SubjuGator 8 consists of a robust set of embedded industry standards and student-designed electronic devices. Peripheral to the main computer is a suite of devices to aid in navigation, safety, power delivery, and communication.
+ SubjuGator 9 consists of a robust set of embedded industry standards and student-designed electronic devices. Peripheral to the main computer is a suite of devices to aid in navigation, safety, power delivery, and communication.
@@ -291,8 +314,8 @@ function RoboSub() {
Hall-effect-based manual shut-off feature allows immediate power cutoff to thrusters for safety during testing and competitions.
-
Water Cooling System
-
Closed-loop water cooling ensures optimal thermal efficiency for the main computer and GPGPU.
+
Open Architecture
+
Subjuss computers and sesnors are connected via a gigabit Ethernet switch. Adding and removing systems is as simple as connecting or disconnecting network devices.
@@ -315,12 +338,12 @@ function RoboSub() {
Advanced Autonomy
- SubjuGator 8's software stack is built on the Noetic version of the Robot Operating System (ROS). Our stack has grown to over 60+ ROS packages, all of which are open-source, allowing other teams to share the benefits of our work.
+ SubjuGator 9's software stack is built on the Jazzy version of the Robot Operating System 2 (ROS2). Our stack has grown to over 60+ ROS packages, all of which are open-source, allowing other teams to share the benefits of our work.
State Estimation
-
An unscented Kalman filter operating on manifolds provides efficient handling of attitude singularities, fusing data from IMU, DVL, and other sensors.
+
An Extended Kalman filter operating on manifolds provides efficient handling of attitude singularities, fusing data from IMU, DVL, and other sensors.
Computer Vision
@@ -333,7 +356,7 @@ function RoboSub() {
-
+
Simulation Environment
@@ -358,7 +381,7 @@ function RoboSub() {
-
+
diff --git a/src/Pages/ScrollToTop.jsx b/src/Pages/ScrollToTop.jsx
new file mode 100644
index 0000000..d965e32
--- /dev/null
+++ b/src/Pages/ScrollToTop.jsx
@@ -0,0 +1,10 @@
+import { useEffect } from "react";
+import { useLocation } from "react-router-dom";
+
+export default function ScrollToTop() {
+ const { pathname } = useLocation();
+ useEffect(() => {
+ window.scrollTo(0, 0);
+ }, [pathname]);
+ return null;
+}
diff --git a/src/Pages/Sponsors.jsx b/src/Pages/Sponsors.jsx
index 3b1aced..3c1697d 100644
--- a/src/Pages/Sponsors.jsx
+++ b/src/Pages/Sponsors.jsx
@@ -1,12 +1,144 @@
-import React from "react";
+// src/Pages/Sponsors.jsx
+import React, { useEffect } from "react";
+import { useLocation } from "react-router-dom";
+import "../styles/Sponsors.css";
-function Sponsors() {
- return (
-
-
Sponsors
-
This is a placeholder for now.
+// local logo & pdf imports
+import sylphaseLogo from "../assets/sponsors/Sylphase.png";
+import sponsorPacket from "../assets/sponsorship_packet.pdf";
+
+/* ---------- Tier component ---------- */
+const SponsorSection = ({ title, sponsors }) => (
+
+ {title}
+
+
+ {sponsors.map((s, i) => {
+ const isPerson = !s.url; // people / alumni have no URL
+ return (
+
+ {s.imgSrc && (
+ isPerson ? (
+
+ ) : (
+
+
+
+ )
+ )}
+ {isPerson &&
{s.name} }
+
+ );
+ })}
+
+);
+
+/* ---------- Main page ---------- */
+const Sponsors = () => {
+ const diamondSponsors = [
+ {
+ name: "Sylphase",
+ url: "https://sylphase.com",
+ imgSrc: sylphaseLogo,
+ imgAlt: "Sylphase Logo",
+ },
+ {
+ name: "L3Harris Technologies",
+ url: "https://l3harris.com",
+ imgSrc:
+ "https://upload.wikimedia.org/wikipedia/en/thumb/2/23/L3Harris_Technologies_logo.svg/1280px-L3Harris_Technologies_logo.svg.png",
+ imgAlt: "L3Harris Logo",
+ },
+ {
+ name: "Erik de la Inglesia",
+ imgSrc: "https://mil.ufl.edu/sponsors/Erik.png",
+ imgAlt: "Erik de la Iglesia",
+ },
+ ];
+
+ const platinumSponsors = [
+ {
+ name: "JD Squared",
+ url: "https://jd2.com",
+ imgSrc: "http://mil.ufl.edu/sponsors/JD-squared-transparent.png",
+ imgAlt: "JD Squared Logo",
+ },
+ {
+ name: "Texas Instruments",
+ url: "https://ti.com",
+ imgSrc: "https://1000logos.net/wp-content/uploads/2020/04/Logo-Texas-Instruments.jpg",
+ imgAlt: "Texas Instruments Logo",
+ },
+ ];
+
+ const goldSponsors = [
+ { name: "Kevin Allen (MIL alumnus)", imgSrc: "http://mil.ufl.edu/sponsors/kevin.jpeg", imgAlt: "Kevin Allen" },
+ { name: "Anonymous (MIL alumnus)" },
+ ];
+
+ const silverSponsors = [
+ { name: "Matthew Langford (MIL alumnus)" },
+ { name: "IEEE", url: "https://www.ieee.org", imgSrc: "https://upload.wikimedia.org/wikipedia/commons/2/21/IEEE_logo.svg", imgAlt: "IEEE Logo" },
+ { name: "Anonymous (MIL alumnus)" },
+ { name: "Electrical and Computer Engineering, UF", url: "https://ece.ufl.edu", imgSrc: "https://www.ece.ufl.edu/wp-content/uploads/2024/10/ElectricalComputerEngineering-VECTOR-RGB.svg", imgAlt: "ECE Logo" },
+ { name: "Mechanical and Aerospace Engineering, UF", url: "https://mae.ufl.edu", imgSrc: "https://mil.ufl.edu/sponsors/MAE_logo.png", imgAlt: "MAE Logo" },
+ ];
+
+ const bronzeSponsors = [
+ { name: "Dr. Andrew Gray (MIL alumnus)" },
+ { name: "DigiKey", url: "https://www.digikey.com", imgSrc: "https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/DigiKey_logo.svg/1280px-DigiKey_logo.svg.png", imgAlt: "DigiKey Logo" },
+ ];
+
+ const location = useLocation();
+
+ useEffect(() => {
+ const hash = location.hash;
+ if (hash) {
+ // Delay to ensure the target element is rendered
+ setTimeout(() => {
+ const element = document.querySelector(hash);
+ if (element) {
+ element.scrollIntoView({ behavior: "smooth" });
+ }
+ }, 100);
+ }
+ }, [location]);
+
+ return (
+
+ {/* ----- hero ----- */}
+
+
+ {/* ----- sponsor tiers ----- */}
+
+
+
+
+
+
+
+
+ {/* ----- footer with call‑to‑action button ----- */}
+
+
);
-}
+};
export default Sponsors;
diff --git a/src/assets/Design_and_Development_of_SubjuGator_9.pdf b/src/assets/Design_and_Development_of_SubjuGator_9.pdf
new file mode 100644
index 0000000..d88cb7d
Binary files /dev/null and b/src/assets/Design_and_Development_of_SubjuGator_9.pdf differ
diff --git a/src/assets/PCB.png b/src/assets/PCB.png
new file mode 100644
index 0000000..2173dde
Binary files /dev/null and b/src/assets/PCB.png differ
diff --git a/src/assets/advanced-autonomy.png b/src/assets/advanced-autonomy.png
new file mode 100644
index 0000000..4fe69fe
Binary files /dev/null and b/src/assets/advanced-autonomy.png differ
diff --git a/src/assets/people/adam_hamdan.png b/src/assets/people/adam_hamdan.png
new file mode 100644
index 0000000..4a0c9af
Binary files /dev/null and b/src/assets/people/adam_hamdan.png differ
diff --git a/src/assets/people/adam_mcaleer.png b/src/assets/people/adam_mcaleer.png
new file mode 100644
index 0000000..76cf73e
Binary files /dev/null and b/src/assets/people/adam_mcaleer.png differ
diff --git a/src/assets/people/adrian_fernandez.png b/src/assets/people/adrian_fernandez.png
new file mode 100644
index 0000000..e6cfe3b
Binary files /dev/null and b/src/assets/people/adrian_fernandez.png differ
diff --git a/src/assets/people/alex_johnson.png b/src/assets/people/alex_johnson.png
new file mode 100644
index 0000000..f8e945b
Binary files /dev/null and b/src/assets/people/alex_johnson.png differ
diff --git a/src/assets/people/cameron_brown.jpeg b/src/assets/people/cameron_brown.jpeg
new file mode 100644
index 0000000..3965348
Binary files /dev/null and b/src/assets/people/cameron_brown.jpeg differ
diff --git a/src/assets/people/carlos_chavez.png b/src/assets/people/carlos_chavez.png
new file mode 100644
index 0000000..7e69bd8
Binary files /dev/null and b/src/assets/people/carlos_chavez.png differ
diff --git a/src/assets/people/daniel_parra.png b/src/assets/people/daniel_parra.png
new file mode 100644
index 0000000..73a933b
Binary files /dev/null and b/src/assets/people/daniel_parra.png differ
diff --git a/src/assets/people/ericjack_rainville.jpg b/src/assets/people/ericjack_rainville.jpg
new file mode 100644
index 0000000..fddcb2d
Binary files /dev/null and b/src/assets/people/ericjack_rainville.jpg differ
diff --git a/src/assets/people/ethan_mitchell.png b/src/assets/people/ethan_mitchell.png
new file mode 100644
index 0000000..303187d
Binary files /dev/null and b/src/assets/people/ethan_mitchell.png differ
diff --git a/src/assets/people/joseph_goodman.png b/src/assets/people/joseph_goodman.png
new file mode 100644
index 0000000..96f2416
Binary files /dev/null and b/src/assets/people/joseph_goodman.png differ
diff --git a/src/assets/people/keith_khadar.jpg b/src/assets/people/keith_khadar.jpg
new file mode 100644
index 0000000..b7b2c04
Binary files /dev/null and b/src/assets/people/keith_khadar.jpg differ
diff --git a/src/assets/people/lester_bonilla.jpg b/src/assets/people/lester_bonilla.jpg
new file mode 100644
index 0000000..0f8ec97
Binary files /dev/null and b/src/assets/people/lester_bonilla.jpg differ
diff --git a/src/assets/people/lorant_domokos.png b/src/assets/people/lorant_domokos.png
new file mode 100644
index 0000000..91425a6
Binary files /dev/null and b/src/assets/people/lorant_domokos.png differ
diff --git a/src/assets/people/ryan_hoburg.png b/src/assets/people/ryan_hoburg.png
new file mode 100644
index 0000000..afd4552
Binary files /dev/null and b/src/assets/people/ryan_hoburg.png differ
diff --git a/src/assets/robosub_logo.png b/src/assets/robosub_logo.png
new file mode 100644
index 0000000..5fd49c0
Binary files /dev/null and b/src/assets/robosub_logo.png differ
diff --git a/src/assets/robosub_preparation.png b/src/assets/robosub_preparation.png
new file mode 100644
index 0000000..1f94864
Binary files /dev/null and b/src/assets/robosub_preparation.png differ
diff --git a/src/assets/simulation_enviornment.png b/src/assets/simulation_enviornment.png
new file mode 100644
index 0000000..128a5f1
Binary files /dev/null and b/src/assets/simulation_enviornment.png differ
diff --git a/src/assets/sponsors/JD-squared-transparent.png b/src/assets/sponsors/JD-squared-transparent.png
new file mode 100644
index 0000000..40cb0d1
Binary files /dev/null and b/src/assets/sponsors/JD-squared-transparent.png differ
diff --git a/src/assets/sponsors/MAE_logo.png b/src/assets/sponsors/MAE_logo.png
new file mode 100644
index 0000000..13443fd
Binary files /dev/null and b/src/assets/sponsors/MAE_logo.png differ
diff --git a/src/assets/sponsors/Sylphase.png b/src/assets/sponsors/Sylphase.png
new file mode 100644
index 0000000..3b53cf7
Binary files /dev/null and b/src/assets/sponsors/Sylphase.png differ
diff --git a/src/assets/sponsorship_packet.pdf b/src/assets/sponsorship_packet.pdf
new file mode 100644
index 0000000..d06cc9a
Binary files /dev/null and b/src/assets/sponsorship_packet.pdf differ
diff --git a/src/assets/subjugator_logo.png b/src/assets/subjugator_logo.png
new file mode 100644
index 0000000..b3a3eaf
Binary files /dev/null and b/src/assets/subjugator_logo.png differ
diff --git a/src/assets/submarines/sub9_1.jpeg b/src/assets/submarines/sub9_1.jpeg
new file mode 100644
index 0000000..810df6b
Binary files /dev/null and b/src/assets/submarines/sub9_1.jpeg differ
diff --git a/src/assets/submarines/sub9_cherry_1.png b/src/assets/submarines/sub9_cherry_1.png
new file mode 100644
index 0000000..53b5b68
Binary files /dev/null and b/src/assets/submarines/sub9_cherry_1.png differ
diff --git a/src/assets/submarines/sub9_development.jpg b/src/assets/submarines/sub9_development.jpg
new file mode 100644
index 0000000..a9a89fb
Binary files /dev/null and b/src/assets/submarines/sub9_development.jpg differ
diff --git a/src/assets/submarines/sub9_frame.png b/src/assets/submarines/sub9_frame.png
new file mode 100644
index 0000000..810d8c9
Binary files /dev/null and b/src/assets/submarines/sub9_frame.png differ
diff --git a/src/assets/submarines/subjugator_1.png b/src/assets/submarines/subjugator_1.png
new file mode 100644
index 0000000..bf0c4eb
Binary files /dev/null and b/src/assets/submarines/subjugator_1.png differ
diff --git a/src/assets/submarines/subjugator_3.png b/src/assets/submarines/subjugator_3.png
new file mode 100644
index 0000000..66f3969
Binary files /dev/null and b/src/assets/submarines/subjugator_3.png differ
diff --git a/src/assets/submarines/subjugator_6.png b/src/assets/submarines/subjugator_6.png
new file mode 100644
index 0000000..ae5a0aa
Binary files /dev/null and b/src/assets/submarines/subjugator_6.png differ
diff --git a/src/assets/submarines/subjugator_8.png b/src/assets/submarines/subjugator_8.png
new file mode 100644
index 0000000..24ae1e3
Binary files /dev/null and b/src/assets/submarines/subjugator_8.png differ
diff --git a/src/assets/submarines/subjugator_9.1.png b/src/assets/submarines/subjugator_9.1.png
new file mode 100644
index 0000000..4189d8c
Binary files /dev/null and b/src/assets/submarines/subjugator_9.1.png differ
diff --git a/src/assets/submarines/subjugator_9.png b/src/assets/submarines/subjugator_9.png
new file mode 100644
index 0000000..a50f54a
Binary files /dev/null and b/src/assets/submarines/subjugator_9.png differ
diff --git a/src/index.css b/src/index.css
index 6119ad9..b5b3f12 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,18 +1,21 @@
:root {
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
- line-height: 1.5;
- font-weight: 400;
+ --navbar-height: 80px;
+ --max-width: 1280px;
+ --space-sm: 0.5rem;
+ --space-md: 1rem;
+ --space-lg: 2rem;
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- background-color: #242424;
+ --color-text-primary: #ffffff;
+ --color-text-secondary: #d1d5db;
+ --color-primary: #fa4616;
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
+ --color-background: #000000;
+
+ --transition-fast: 0.2s ease;
+ --transition-medium: 0.4s ease;
}
+
a {
font-weight: 500;
color: #646cff;
@@ -28,6 +31,10 @@ body {
place-items: center;
min-width: 320px;
min-height: 100vh;
+ padding: 0;
+ color: white;
+ background-color: #000000;
+ overflow-x: hidden;
}
h1 {
diff --git a/src/main.jsx b/src/main.jsx
index 9191daf..d719969 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -2,11 +2,12 @@ import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
-import "./styles/GlobalStyles.css";
import "./index.css";
ReactDOM.createRoot(document.getElementById("root")).render(
-
-
-
-);
\ No newline at end of file
+
+
+
+
+
+);
diff --git a/src/styles/AUVTechnology.css b/src/styles/AUVTechnology.css
index 7e62c94..84bb0e4 100644
--- a/src/styles/AUVTechnology.css
+++ b/src/styles/AUVTechnology.css
@@ -2,17 +2,28 @@
.auv-technology-page {
background-color: var(--color-background);
color: #ffffff;
+ font-family: 'Montserrat', sans-serif;
+
+}
+
+
+.tech-specs-section .tech-button-container {
+ margin-top: 6rem;
+
}
/* ========== Hero Section with 3D Model ========== */
.hero-section {
- height: 100vh;
+ height: calc(var(--vh) * 100 - var(--navbar-height, 0px));
position: relative;
- display: flex;
align-items: center;
+ overflow: visible;
justify-content: center;
- overflow: hidden;
- background-color: #000000;
+ position: relative;
+ display: flex;
+ height: 100svh;
+ height: 100dvh;
+ height: 100vh;
}
.hero-background {
@@ -263,7 +274,6 @@
gap: 10px;
z-index: 5;
}
-
.control-button {
background-color: rgba(0, 0, 0, 0.7);
border: 1px solid rgba(255, 255, 255, 0.2);
diff --git a/src/styles/AboutUs.css b/src/styles/AboutUs.css
index ab77d21..3a33abc 100644
--- a/src/styles/AboutUs.css
+++ b/src/styles/AboutUs.css
@@ -1,4 +1,8 @@
/* Hero Section with Team Photo Background - Improved */
+html, body {
+ font-family: "Open Sans", Helvetica, Arial, sans-serif !important;
+}
+
.about-hero-section {
min-height: 70vh;
position: relative;
@@ -17,17 +21,27 @@
border-radius: 12px; /* Optional: rounded corners for container */
}
-
+.about-hero-section::before {
+ content: "";
+ position: absolute;
+ top: 0; left: 0;
+ width: 100%; height: 100%;
+ background: rgba(0, 0, 0, 0.5);
+ pointer-events: none;
+ z-index: 1;
+}
.about-hero-section .container {
- position: relative;
+ position: absolute;
+ top: 45%;
+ left: 50%;
+ transform: translate(-50%,-50%);
z-index: 1;
width: 100%;
max-width: var(--max-width);
padding: 0 20px;
margin-bottom: 20px;
}
-
.hero-title {
font-size: clamp(2rem, 5vw, 3.5rem);
margin-bottom: 10px;
@@ -360,6 +374,12 @@
gap: 8px;
}
+.image-sub1 { background-image: url("/src/assets/submarines/subjugator_1.png"); }
+.image-sub3 { background-image: url("/src/assets/submarines/subjugator_3.png"); }
+.image-sub6 { background-image: url("/src/assets/submarines/subjugator_6.png"); }
+.image-sub8 { background-image: url("/src/assets/submarines/subjugator_8.png"); }
+.image-sub9 { background-image: url("/src/assets/submarines/subjugator_9.png"); }
+
.tech-tag {
display: inline-block;
padding: 4px 10px;
diff --git a/src/styles/Contact.css b/src/styles/Contact.css
index ecd71ab..ba16a4b 100644
--- a/src/styles/Contact.css
+++ b/src/styles/Contact.css
@@ -63,6 +63,7 @@
.contact-hero-section .hero-content {
text-align: center;
max-width: 800px;
+ color: white;
}
.contact-hero-section .hero-title {
diff --git a/src/styles/Home.css b/src/styles/Home.css
index 0b76335..52fc9cb 100644
--- a/src/styles/Home.css
+++ b/src/styles/Home.css
@@ -16,7 +16,7 @@
width: 100%;
max-width: 1200px;
margin: 0 auto;
- padding: 0 20px;
+ padding: 0 0px;
z-index: 1;
}
@@ -26,7 +26,7 @@
left: 0;
width: 100%;
height: 100%;
- background-image: url("/src/assets/submarine-hero.jpg");
+ background-image: url("/src/assets/subjugator8-hero.png");
background-size: cover;
background-position: center;
z-index: -1;
@@ -75,16 +75,6 @@
color: #ffffff;
}
-.hero-subtitle {
- opacity: 0;
- font-size: clamp(1.5rem, 4vw, 2.5rem);
- font-weight: 300;
- color: #ffffff;
- margin-top: 0;
- margin-bottom: 2rem;
- text-align: center;
- width: 100%;
-}
.hero-cta {
display: flex;
@@ -184,10 +174,9 @@
}
.animate-fadeIn {
- opacity: 1 !important; /* Force opacity to 1 */
+ opacity: 1 !important;
}
-/* Add a new class for slide up animation */
.animate-slideUp {
animation: slideUp 1.5s ease forwards;
}
@@ -248,11 +237,13 @@
.subtitle {
font-size: 1.2rem;
- color: rgba(255, 255, 255, 0.85); /* Improved contrast */
+ color: rgba(255, 255, 255, 0.85);
max-width: 700px;
margin: 0 auto;
}
+
+
.stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
@@ -322,9 +313,8 @@
}
.highlight-content {
- width: 50%;
- margin-left: auto;
- padding: var(--space-xl) 0;
+ margin: 0 auto;
+ text-align: center;
}
.tech-features {
@@ -390,6 +380,12 @@
background-color: var(--color-background);
padding: 80px 0;
position: relative;
+ padding-bottom: 260px;
+}
+.updates-section::after {
+ content: ""; /* creates a real box */
+ display: block;
+ height: 12rem; /* tweak up/down to taste (≈ 96 px) */
}
.updates-section .section-header {
@@ -479,6 +475,55 @@
transform: translateX(4px);
}
+.countdown-card {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: #111;
+}
+
+.countdown-title {
+ text-align: center;
+ margin-bottom: var(--space-md);
+}
+
+.countdown-clock {
+ display: flex;
+ justify-content: center;
+ gap: 1rem;
+}
+.countdown-clock .time-box:nth-child(4) .time-value
+{
+ color: #fa4616;
+}
+
+.time-box {
+ background: #1a1a1a;
+ border: 1px solid #333;
+ padding: 0.6rem 0.8rem;
+ border-radius: 6px;
+ min-width: 60px;
+}
+
+.time-value {
+ font-size: 1.6rem;
+ font-weight: 600;
+ color: #4a9fff;
+ display: block;
+}
+
+.time-label {
+ font-size: 0.75rem;
+ color: #ccc;
+ text-transform: uppercase;
+ letter-spacing: 0.02em;
+}
+
+.image-sub9 { background-image: url("/src/assets/submarines/sub9_development.jpg"); }
+.image-robosub{ background-image: url("/src/assets/robosub_preparation.png"); }
+.update-image { background-size: cover; background-position: center; }
+
+
/* ========== CTA Section (Join the Journey) ========== */
.cta-section {
padding: 100px 0; /* Increase vertical padding */
@@ -488,6 +533,7 @@
background-position: center;
background-attachment: fixed;
text-align: center;
+
}
.cta-content {
@@ -582,73 +628,102 @@
}
}
-/* Responsive adjustments */
-@media screen and (max-width: 992px) {
- .tech-highlights-section .btn {
- margin-left: 0;
- margin-right: auto;
- align-self: flex-start;
+
+html, body { overflow-x: hidden; }
+
+
+@media (max-width: 680px) {
+ .stats-grid, .updates-grid {
+ grid-template-columns: 1fr;
+ padding-inline: 0.75rem;
+ gap: 20px;
}
+
+ .overview-section {
+ padding-bottom: 40px; /* down from 80px */
+ }
+
.highlight-image {
- width: 100%;
- height: 300px;
position: relative;
+ width: 100%;
+ height: 220px;
clip-path: none;
}
- .updates-grid {
- grid-template-columns: repeat(2, 1fr); /* 2 columns on medium screens */
+ .container{
+ width: 100%;
+ position: relative;
}
+ /* —— MOBILE FIX FOR TECH HIGHLIGHTS —— */
.tech-highlights-section {
- flex-direction: column;
+ display: flex; /* ensure it’s flex */
+ flex-direction: column; /* stack image + content */
+ align-items: center; /* center children horizontally */
}
- .highlight-content {
+ .tech-highlights-section .highlight-image {
+ position: relative; /* flow normally */
+ width: 100%; /* full-width banner */
+ height: 220px; /* adjust as needed */
+ clip-path: none; /* remove the desktop diagonal */
+ }
+
+ .tech-highlights-section .container {
+ display: block; /* override the flex container */
width: 100%;
- margin: 0;
- padding: var(--space-xl) var(--space-lg);
+ max-width: 1200px; /* keep your desktop cap if you like */
+ margin: 0 auto; /* center it */
+ padding: 0 20px;
+ box-sizing: border-box;
+ }
+
+ .highlight-content {
+ max-width: 700px; /* optional cap so it doesn’t stretch too far */
+ margin: 1rem auto; /* vertical spacing + horizontal centering */
+ text-align: center;
}
- .hero-cta {
+
+ .tech-features {
display: flex;
- gap: 20px;
- justify-content: center;
- margin-top: 2rem;
- width: 100%;
- opacity: 0;
+ flex-direction: column; /* stack the three feature blocks */
+ gap: 20px; /* space between them */
+ align-items: center; /* center each block */
}
- .hero-cta .btn {
- opacity: 0;
+
+ .feature {
width: 100%;
+ max-width: 320px;
}
- .cta-buttons {
- flex-direction: column;
- gap: var(--space-md);
+ .tech-highlights-section .btn {
+ display: block;
+ margin: 2rem auto 0;
+ width: 100%;
+ max-width: 320px;
+ padding-top: 10px;
+ min-height: auto;
+ text-align: center;
}
+
}
-@media screen and (max-width: 768px) {
- .stats-grid,
- .updates-grid {
- grid-template-columns: 1fr;
- }
- .hero-section {
- padding-top: var(--navbar-height);
- }
- .feature-text p {
- max-width: 100%;
- }
- .feature-icon {
- width: 50px;
- height: 50px;
- margin-right: var(--space-md);
+@media (max-width: 680px) {
+ .hero-cta .btn,
+ .cta-buttons .btn {
+ min-width: 0;
+ width: 100%;
}
+}
- .feature-text h3 {
- font-size: 1.5rem;
- }
+.hero-section,
+.tech-highlights-section,
+.updates-section,
+.overview-section {
+ overflow-x: hidden;
}
+
+
.overview-section .section-header,
.updates-section .section-header {
width: 100%;
diff --git a/src/styles/OurTeam.css b/src/styles/OurTeam.css
new file mode 100644
index 0000000..2adbec3
--- /dev/null
+++ b/src/styles/OurTeam.css
@@ -0,0 +1,113 @@
+:root {
+ --orange: #fa4616;
+ --page-bg: #000000;
+ --shade-bg: #141414;
+ --card-bg: #1f1f1f;
+ --text-primary: #ffffff;
+ --text-secondary: #cccccc;
+}
+
+@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap');
+
+/* ---------- page shell ---------- */
+.our-team-page {
+ min-height: 100px;
+ background: var(--page-bg);
+ color: var(--text-primary);
+ display: flex;
+ flex-direction: column;
+}
+
+/* ---------- containers ---------- */
+.container-fluid { width: 100%; padding-inline: 1rem; }
+.container-xl { width: 100%; max-width: 1440px; margin-inline: auto; padding-inline: 1rem; }
+
+.hero { padding-block: clamp(4rem, 10vw, 6rem) 0; }
+.hero-title { font-size: clamp(3rem, 8vw, 5.5rem); line-height: 1.1; margin: 0; opacity: 0; animation: slideUp 1.2s ease forwards; }
+.hero-title .highlight {
+ background: linear-gradient(90deg, #fa4616, #f7cbbe); /* ⬅️ your new gradient */
+ background-size: 200% auto;
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+}
+
+.team-section {
+ background: var(--shade-bg);
+ width: 100%;
+ margin-top: clamp(5rem, 10vw, 6rem);
+ padding-block: clamp(2rem, 5vw, 3rem) clamp(3rem, 6vw, 5rem);
+ padding-inline: clamp(0.5rem, 3vw, 2rem);
+ border-radius: 0.75rem 0.75rem 0 0;
+}
+
+/* increase vertical gap so the grid sits lower */
+.team-section__inner {
+ display: flex;
+ flex-direction: column;
+ gap: clamp(2rem, 4vw, 2.75rem); /* ⬅️ was 1rem */
+}
+
+.grid-subtitle {
+ font-size: clamp(1.25rem, 2.2vw, 1.75rem); /* responsive subtitle size */
+ color: var(--text-secondary);
+ text-align: center;
+ opacity: 0;
+ animation: slideUp 1.1s ease 0.15s forwards;
+}
+
+.team-grid {
+ display: grid;
+ grid-template-columns: repeat(3, minmax(120px, 240px));
+ row-gap: clamp(8rem, 0.1vw, 9rem);
+ column-gap: clamp(0.75rem, 3vw, 1.5rem);
+ margin-top: clamp(5rem, 3vw, 2rem); /* ⬅️ pushes grid down */
+ opacity: 0;
+ animation: slideUp 1.2s ease 0.3s forwards;
+}
+
+
+/* card */
+.team-card { position:relative; background-color:var(--card-bg); border:1px solid transparent; border-top:4px solid var(--orange); border-radius:0.75rem; padding: 1.25rem 0.7rem 0.9rem; /* compact padding */ /* compact padding */ text-align:center; display:flex; flex-direction:column; align-items:center; min-height:170px; transition:transform 0.25s ease,border-color 0.25s ease,box-shadow 0.25s ease; }
+@media(hover:hover){ .team-card:hover,.team-card:focus-visible{ transform:translate3d(0,-6px,0); border-color:var(--orange); box-shadow:0 4px 10px rgba(0,0,0,.35); } }
+.team-card:focus-visible{ outline:2px solid var(--orange); outline-offset:4px; }
+
+/* image */
+.team-card__image-wrapper {
+ position: absolute;
+ top: -80px;
+ left: 50%;
+ translate: -50% 0;
+ width: 120px;
+ height: 120px;
+ border-radius: 0.5rem;
+ overflow: hidden;
+ box-shadow: none;
+ z-index: 1;
+ border: 1px solid var(--orange);
+}
+.team-card__image {
+ width:100%;
+ height:100%;
+ object-fit:cover;
+}
+
+/* ---------- typography inside card ---------- */
+.team-card__name { font-family:'Poppins',sans-serif; font-size:1.25rem; font-weight:600; margin:0.3rem 0 0.2rem; }
+.team-card__role { font-family:'Poppins',sans-serif; font-size:1.05rem; color:var(--text-secondary); }
+
+.team-card.no-photo{ padding-top:0.75rem; }
+.team-card.has-photo{ padding-top:3.5rem; }
+
+/* ---------- CTA section ---------- */
+.cta-section{ background:linear-gradient(180deg,#111 0%,#000 80%); padding-block:clamp(4rem,10vw,6rem); margin-top:auto; }
+.cta-wrapper{ text-align:center; max-width:720px; margin-inline:auto; }
+.cta-heading{ font-size:clamp(2rem,5vw,3rem); font-weight:700; margin-bottom:1.5rem; }
+.cta-buttons{ display:flex; flex-wrap:wrap; gap:1rem; justify-content:center; }
+.btn{ padding:0.6rem 1.4rem; border-radius:9999px; font-weight:600; transition:background 0.2s ease; }
+.btn-primary{ background:var(--orange); color:var(--text-primary);} .btn-primary:hover,.btn-primary:focus-visible{ background:#ff651f; }
+.btn-secondary{ background:#ffffff10; color:var(--text-primary); border:1px solid #ffffff25;} .btn-secondary:hover,.btn-secondary:focus-visible{ background:#ffffff22; }
+
+/* ---------- animations ---------- */
+@keyframes slideUp{ from{ transform:translateY(30px); opacity:0;} to{ transform:translateY(0); opacity:1;} }
+@keyframes gradientShift{ 0%{ background-position:0% center;} 100%{ background-position:200% center;} }
\ No newline at end of file
diff --git a/src/styles/RoboSub.css b/src/styles/RoboSub.css
index 47a54d1..108a47f 100644
--- a/src/styles/RoboSub.css
+++ b/src/styles/RoboSub.css
@@ -3,18 +3,20 @@
/* Base styles for the page */
color: var(--color-text-primary);
background-color: var(--color-background);
- overflow-x: hidden;
+ height: calc(100vh - var(--navbar-height));
+ overflow-x: visible;
}
/* Hero Section with regular background (not underwater) */
.robosub-page .robosub-hero-section {
- height: 100vh;
- position: relative;
- display: flex;
- align-items: center;
- justify-content: center;
- overflow: hidden;
- background-color: #000000;
+ height: calc(100vh - var(--navbar-height));
+ position: relative;
+ align-items: center;
+ overflow: visible;
+ justify-content: center;
+ position: relative;
+ margin-top: 160px;
+ display: flex;
}
/* Background image styling similar to Home page */
@@ -80,7 +82,6 @@
.robosub-page .hero-title {
font-size: clamp(3.5rem, 10vw, 7rem);
- font-weight: 800;
color: #ffffff;
margin-bottom: 0;
text-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
@@ -875,4 +876,11 @@
opacity: 1;
transform: translateY(0);
}
-
\ No newline at end of file
+
+.hero-bg { background-image: url("/src/assets/submarine-hero.jpg"); }
+.hero-auv { content: url("/src/assets/submarines/subjugator_9.1.png"); }
+.image-sub9-swim { content: url("/src/assets/submarines/sub9_cherry_1.png"); }
+.image-sub9-frame { content: url("/src/assets/submarines/sub9_1.jpeg"); }
+.image-electrical { content: url("/src/assets/PCB.png"); }
+.image-sim-env { content: url("/src/assets/simulation_enviornment.png"); }
+.image-robosub-logo { content: url("/src/assets/robosub_logo.png"); }
diff --git a/src/styles/Sponsors.css b/src/styles/Sponsors.css
new file mode 100644
index 0000000..6bf4aa3
--- /dev/null
+++ b/src/styles/Sponsors.css
@@ -0,0 +1,223 @@
+/* ---------- root palette ---------- */
+:root {
+ --orange: #fa4616;
+ --text-primary: #ffffff;
+ --text-secondary: #cccccc;
+ --shade-bg: #141414;
+}
+
+/* ---------- page shell ---------- */
+.sponsors-page {
+ background-color: #000;
+ color: var(--text-primary);
+ min-height: 100vh;
+}
+
+/* ---------- hero ---------- */
+.hero {
+ padding-block: clamp(4rem, 8vw, 6rem) 2rem;
+}
+
+.hero-title {
+ color: var(--text-primary); /* ensures white text */
+ font-size: clamp(2.5rem, 7vw, 5rem);
+ font-weight: 700;
+ margin: 0;
+}
+
+.hero-title .highlight {
+ background: linear-gradient(90deg, #fa4616, #ff8c69);
+ background-clip: text;
+ -webkit-background-clip: text;
+ color: transparent; /* gradient text */
+}
+
+.hero-subtitle {
+ margin-top: 1rem;
+ font-size: 1.2rem;
+ color: var(--text-secondary);
+}
+
+/* ---------- sponsor tiers ---------- */
+.sponsor-section {
+ padding-block: 5rem;
+}
+
+.sponsor-section__title {
+ text-align: center;
+ font-size: 1.75rem;
+ font-weight: 600;
+ color: var(--orange);
+ margin-bottom: 2.5rem;
+ position: relative;
+ padding-bottom: 0.5rem;
+}
+
+.sponsor-section__title::after {
+ content: "";
+ position: absolute;
+ left: 50%;
+ bottom: 0;
+ transform: translateX(-50%);
+ width: 80px;
+ height: 3px;
+ background: var(--orange);
+ border-radius: 4px;
+}
+
+.sponsor-grid {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 2rem;
+ row-gap: 3rem;
+}
+
+/* ---------- sponsor card ---------- */
+.sponsor-card {
+ background: var(--shade-bg); /* dark card body */
+ border-radius: 0.5rem;
+ padding: 1.5rem;
+ text-align: center;
+ max-width: 280px;
+ width: 100%;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25);
+ transition: transform 0.2s ease;
+}
+
+.sponsor-card:hover {
+ transform: translateY(-4px);
+}
+
+/* ---------- logo image ---------- */
+.sponsor-card__logo {
+ max-width: 100%;
+ max-height: 120px; /* larger logos */
+ object-fit: contain;
+ margin-bottom: 1rem;
+}
+
+/* allow explicit up-sizing via .large helper */
+.sponsor-card__logo.large {
+ max-height: 120px; /* matches default – keep for clarity */
+}
+
+/* ---------- name & optional description ---------- */
+.sponsor-card__name {
+ font-weight: 600;
+ font-size: 1.1rem;
+ margin-bottom: 0.5rem;
+}
+
+.sponsor-card__description {
+ font-size: 0.95rem;
+ color: var(--text-secondary);
+}
+/* no background / box for each sponsor */
+.sponsor-card {
+ background: none;
+ box-shadow: none;
+ padding: 0;
+ transition: transform 0.2s ease;
+}
+
+/* enlarge logos a bit */
+.sponsor-card__logo {
+ max-height: 140px;
+ margin-bottom: 0.8rem;
+}
+
+/* remove underline & make company links white */
+.no-style-link {
+ text-decoration: none;
+ color: var(--text-primary);
+}
+
+/* company names (inside anchor) inherit white text */
+.company-name a { color: var(--text-primary); }
+
+/* people names stay blue */
+.person-name {
+ color: #3b82f6; /* tailwind blue-500 */
+}
+
+.hero-subtitle {
+ max-width: 720px;
+ margin: 1rem auto;
+ font-size: 1.05rem;
+ color: var(--text-secondary);
+ line-height: 1.45;
+}
+
+.sponsor-footer {
+ padding: 3rem 1rem 4rem;
+}
+
+.sponsor-pdf-link {
+ color: var(--orange);
+ font-weight: 600;
+ text-decoration: underline;
+}
+
+/* footer layout */
+.sponsor-footer {
+ padding: 4rem 1rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 1.5rem;
+}
+
+/* big white heading */
+.sponsor-call {
+ font-size: 4.5rem; /* larger */
+ color: var(--text-primary);
+ margin: 0;
+}
+
+/* blue gradient underline */
+.sponsor-underline {
+ display: block;
+ width: 140px;
+ height: 5px;
+ margin: 0.6rem auto 2rem;
+ border-radius: 9999px;
+ background: linear-gradient(90deg, #3b82f6 0%, #1e40af 100%);
+}
+
+/* orange pill-button */
+.sponsor-btn {
+ background: var(--orange); /* orange by default */
+ color: var(--text-primary);
+ padding: 1rem 2.4rem;
+ border-radius: 9999px;
+ font-weight: 600;
+ text-decoration: none;
+ transition: background 0.25s ease, transform 0.15s ease;
+}
+
+/* turn blue – subtle lift on hover / focus */
+.sponsor-btn:hover,
+.sponsor-btn:focus-visible {
+ background: #06369e; /* Tailwind blue-600 */
+ transform: translateY(-2px);
+}
+
+/* optional: shade darker while active / clicking */
+.sponsor-btn:active {
+ background: #1e40af; /* blue-800 */
+ transform: translateY(0);
+}
+
+/* keep button text white in every state */
+.sponsor-btn,
+.sponsor-btn:visited,
+.sponsor-btn:hover,
+.sponsor-btn:focus-visible,
+.sponsor-btn:active {
+ color: var(--text-primary) !important;
+}
+
+
+
+
diff --git a/vercel.json b/vercel.json
new file mode 100644
index 0000000..6a92648
--- /dev/null
+++ b/vercel.json
@@ -0,0 +1,5 @@
+{
+ "rewrites": [
+ { "source": "/(.*)", "destination": "/" }
+ ]
+}