diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..763301f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+dist/
+node_modules/
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..b558fb4
--- /dev/null
+++ b/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+ Portfolio Starter Kit
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..a816888
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,855 @@
+{
+ "name": "portfolio-starter-kit",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "portfolio-starter-kit",
+ "version": "1.0.0",
+ "dependencies": {
+ "@vitejs/plugin-react": "latest",
+ "react": "latest",
+ "react-dom": "latest",
+ "react-router-dom": "latest",
+ "vite": "latest"
+ },
+ "devDependencies": {}
+ },
+ "node_modules/@oxc-project/types": {
+ "version": "0.143.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz",
+ "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz",
+ "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz",
+ "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz",
+ "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz",
+ "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz",
+ "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz",
+ "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz",
+ "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz",
+ "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz",
+ "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz",
+ "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz",
+ "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz",
+ "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz",
+ "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz",
+ "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
+ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
+ "license": "MIT"
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.5.tgz",
+ "integrity": "sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA==",
+ "license": "MIT",
+ "dependencies": {
+ "@rolldown/pluginutils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0",
+ "babel-plugin-react-compiler": "^1.0.0",
+ "vite": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@rolldown/plugin-babel": {
+ "optional": true
+ },
+ "babel-plugin-react-compiler": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.33.0",
+ "lightningcss-darwin-arm64": "1.33.0",
+ "lightningcss-darwin-x64": "1.33.0",
+ "lightningcss-freebsd-x64": "1.33.0",
+ "lightningcss-linux-arm-gnueabihf": "1.33.0",
+ "lightningcss-linux-arm64-gnu": "1.33.0",
+ "lightningcss-linux-arm64-musl": "1.33.0",
+ "lightningcss-linux-x64-gnu": "1.33.0",
+ "lightningcss-linux-x64-musl": "1.33.0",
+ "lightningcss-win32-arm64-msvc": "1.33.0",
+ "lightningcss-win32-x64-msvc": "1.33.0"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.26",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
+ "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.17",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.2.8",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz",
+ "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.2.8",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz",
+ "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.8"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "7.18.2",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.2.tgz",
+ "integrity": "sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.18.2",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.2.tgz",
+ "integrity": "sha512-AIKJ/jgGlFb3EbfCXk5Gzshiwt+l3mqbCrNjmEWMMjqQxNJ3svBa6bgzFyCC2Sw3RA0VWF1kg3uQf2OFhxb8hw==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.18.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/rolldown": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz",
+ "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.143.0",
+ "@rolldown/pluginutils": "^1.0.0"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.2.3",
+ "@rolldown/binding-darwin-arm64": "1.2.3",
+ "@rolldown/binding-darwin-x64": "1.2.3",
+ "@rolldown/binding-freebsd-x64": "1.2.3",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.3",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.3",
+ "@rolldown/binding-linux-arm64-musl": "1.2.3",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.3",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.3",
+ "@rolldown/binding-linux-x64-gnu": "1.2.3",
+ "@rolldown/binding-linux-x64-musl": "1.2.3",
+ "@rolldown/binding-openharmony-arm64": "1.2.3",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.3",
+ "@rolldown/binding-win32-x64-msvc": "1.2.3"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
+ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
+ "license": "MIT"
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/vite": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz",
+ "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==",
+ "license": "MIT",
+ "dependencies": {
+ "lightningcss": "^1.33.0",
+ "picomatch": "^4.0.5",
+ "postcss": "^8.5.25",
+ "rolldown": "~1.2.1",
+ "tinyglobby": "^0.2.17"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "@vitejs/devtools": "^0.4.0",
+ "esbuild": "^0.27.0 || ^0.28.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..750ce8f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "portfolio-starter-kit",
+ "private": true,
+ "version": "1.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@vitejs/plugin-react": "latest",
+ "vite": "latest",
+ "react": "latest",
+ "react-dom": "latest",
+ "react-router-dom": "latest"
+ },
+ "devDependencies": {}
+}
diff --git a/public/favicon.svg b/public/favicon.svg
new file mode 100644
index 0000000..62ed092
--- /dev/null
+++ b/public/favicon.svg
@@ -0,0 +1 @@
+
diff --git a/src/App.jsx b/src/App.jsx
new file mode 100644
index 0000000..1ef548d
--- /dev/null
+++ b/src/App.jsx
@@ -0,0 +1,28 @@
+import { Routes, Route } from 'react-router-dom'
+import Header from './components/Header'
+import Footer from './components/Footer'
+import Home from './pages/Home'
+import About from './pages/About'
+import NotFound from './pages/NotFound'
+import Project01 from './pages/projects/Project01'
+import Project02 from './pages/projects/Project02'
+import Project03 from './pages/projects/Project03'
+
+export default function App() {
+ return (
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+
+ )
+}
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
new file mode 100644
index 0000000..fea6f8e
--- /dev/null
+++ b/src/components/Footer.jsx
@@ -0,0 +1,3 @@
+export default function Footer() {
+ return © 2025 Your Name Designed & built with curiosity.
+}
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
new file mode 100644
index 0000000..f92aac6
--- /dev/null
+++ b/src/components/Header.jsx
@@ -0,0 +1,14 @@
+import { NavLink } from 'react-router-dom'
+
+export default function Header() {
+ return (
+
+ YOUR NAME.
+
+ Home
+ About
+ Contact
+
+
+ )
+}
diff --git a/src/components/ImageGrid.jsx b/src/components/ImageGrid.jsx
new file mode 100644
index 0000000..a4c26fa
--- /dev/null
+++ b/src/components/ImageGrid.jsx
@@ -0,0 +1,3 @@
+export default function ImageGrid({ images }) {
+ return {images.map((image, index) =>
)}
+}
diff --git a/src/components/ProjectCard.jsx b/src/components/ProjectCard.jsx
new file mode 100644
index 0000000..c8a5048
--- /dev/null
+++ b/src/components/ProjectCard.jsx
@@ -0,0 +1,5 @@
+import { Link } from 'react-router-dom'
+
+export default function ProjectCard({ title, category, year, image, to, number }) {
+ return {number}
+}
diff --git a/src/components/ProjectGrid.jsx b/src/components/ProjectGrid.jsx
new file mode 100644
index 0000000..68b2cf0
--- /dev/null
+++ b/src/components/ProjectGrid.jsx
@@ -0,0 +1,11 @@
+import ProjectCard from './ProjectCard'
+
+export const projects = [
+ { number: '01', title: 'Project One', category: 'UX Case Study', year: '2025', image: 'https://images.unsplash.com/photo-1558655146-d09347e92766?auto=format&fit=crop&w=1400&q=80', to: '/works/project-01' },
+ { number: '02', title: 'Project Two', category: 'Editorial Interface', year: '2024', image: 'https://images.unsplash.com/photo-1559028012-481c04fa702d?auto=format&fit=crop&w=1400&q=80', to: '/works/project-02' },
+ { number: '03', title: 'Project Three', category: 'Visual Direction', year: '2024', image: 'https://images.unsplash.com/photo-1550745165-9bc0b252726f?auto=format&fit=crop&w=1400&q=80', to: '/works/project-03' },
+]
+
+export default function ProjectGrid() {
+ return {projects.map((project) =>
)}
+}
diff --git a/src/components/ProjectHero.jsx b/src/components/ProjectHero.jsx
new file mode 100644
index 0000000..3b1fbaa
--- /dev/null
+++ b/src/components/ProjectHero.jsx
@@ -0,0 +1,3 @@
+export default function ProjectHero({ number, category, title, description, image, className = '' }) {
+ return {number} / {category}
{title} {description &&
{description}
}
{image &&
}
+}
diff --git a/src/components/ProjectNavigation.jsx b/src/components/ProjectNavigation.jsx
new file mode 100644
index 0000000..0249bed
--- /dev/null
+++ b/src/components/ProjectNavigation.jsx
@@ -0,0 +1,8 @@
+import { Link } from 'react-router-dom'
+import { projects } from './ProjectGrid'
+
+export default function ProjectNavigation({ current }) {
+ const index = projects.findIndex((project) => project.number === current)
+ const next = projects[(index + 1) % projects.length]
+ return Next project
{next.number} {next.title} ↗
+}
diff --git a/src/components/Section.jsx b/src/components/Section.jsx
new file mode 100644
index 0000000..d6ac3e5
--- /dev/null
+++ b/src/components/Section.jsx
@@ -0,0 +1,3 @@
+export default function Section({ eyebrow, title, children, className = '' }) {
+ return {eyebrow &&
{eyebrow}
}
{title} {children}
+}
diff --git a/src/main.jsx b/src/main.jsx
new file mode 100644
index 0000000..952dbdf
--- /dev/null
+++ b/src/main.jsx
@@ -0,0 +1,17 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import { HashRouter } from 'react-router-dom'
+import App from './App'
+import './styles/reset.css'
+import './styles/variables.css'
+import './styles/global.css'
+import './styles/layout.css'
+import './styles/components.css'
+
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+
+
+
+ ,
+)
diff --git a/src/pages/About.jsx b/src/pages/About.jsx
new file mode 100644
index 0000000..64425e8
--- /dev/null
+++ b/src/pages/About.jsx
@@ -0,0 +1,5 @@
+import Section from '../components/Section'
+
+export default function About() {
+ return About
Curious by default.Intentional by design. Hello, I’m Your Name — a UX/UI designer interested in the space between people, technology, and culture.
I enjoy making complex things feel simple and building visual systems that have room to breathe. This is placeholder copy: make it yours.
Experience 2024 — Now · Independent Designer
2022 — 2024 · Design Studio
Skills Research · UX/UI · Prototyping Art Direction · Visual Design · Writing
+}
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
new file mode 100644
index 0000000..4c9fd25
--- /dev/null
+++ b/src/pages/Home.jsx
@@ -0,0 +1,11 @@
+import { Link } from 'react-router-dom'
+import Section from '../components/Section'
+import ProjectGrid from '../components/ProjectGrid'
+
+export default function Home() {
+ return <>
+ UX / UI Designer & Visual Thinker
Making space for better ideas. A starter portfolio for documenting thoughtful digital experiences, experiments, and everything in between.
More about me ↗
+ Use this space to introduce your point of view. Replace this placeholder with a short statement about what you care about, how you work, or what you are currently exploring.
Currently available for selected projects · Seoul, KR
+
+ >
+}
diff --git a/src/pages/NotFound.jsx b/src/pages/NotFound.jsx
new file mode 100644
index 0000000..1d0aa0f
--- /dev/null
+++ b/src/pages/NotFound.jsx
@@ -0,0 +1,2 @@
+import { Link } from 'react-router-dom'
+export default function NotFound() { return 404 / Not found
This page tooka different route. Back to home ↗ }
diff --git a/src/pages/projects/Project01.jsx b/src/pages/projects/Project01.jsx
new file mode 100644
index 0000000..2526e56
--- /dev/null
+++ b/src/pages/projects/Project01.jsx
@@ -0,0 +1,7 @@
+import Section from '../../components/Section'
+import ProjectHero from '../../components/ProjectHero'
+import ProjectNavigation from '../../components/ProjectNavigation'
+import ImageGrid from '../../components/ImageGrid'
+
+const image = 'https://images.unsplash.com/photo-1558655146-d09347e92766?auto=format&fit=crop&w=1800&q=80'
+export default function Project01() { return Replace this overview with the context, role, timeline, and collaborators for your project.
Role UX / UI Designer Timeline 8 weeks Team Product, Engineering Use this section to explain what you learned from users and the opportunity you found. A good case study makes the thinking visible.
“Good design gives people confidence to move forward.”
}
diff --git a/src/pages/projects/Project02.jsx b/src/pages/projects/Project02.jsx
new file mode 100644
index 0000000..248fda6
--- /dev/null
+++ b/src/pages/projects/Project02.jsx
@@ -0,0 +1,6 @@
+import Section from '../../components/Section'
+import ProjectHero from '../../components/ProjectHero'
+import ProjectNavigation from '../../components/ProjectNavigation'
+import ImageGrid from '../../components/ImageGrid'
+const images = ['https://images.unsplash.com/photo-1559028012-481c04fa702d?auto=format&fit=crop&w=1600&q=80','https://images.unsplash.com/photo-1561070791-2526d30994b5?auto=format&fit=crop&w=1200&q=80','https://images.unsplash.com/photo-1567016432779-094069958ea5?auto=format&fit=crop&w=1200&q=80']
+export default function Project02() { return
Use large type, generous margins, and changing image scales to give a project its own voice. This layout is intentionally different from Project One.
“The most interesting detail is often the one you almost missed.” }
diff --git a/src/pages/projects/Project03.jsx b/src/pages/projects/Project03.jsx
new file mode 100644
index 0000000..c704a0a
--- /dev/null
+++ b/src/pages/projects/Project03.jsx
@@ -0,0 +1,5 @@
+import Section from '../../components/Section'
+import ProjectHero from '../../components/ProjectHero'
+import ProjectNavigation from '../../components/ProjectNavigation'
+const image = 'https://images.unsplash.com/photo-1550745165-9bc0b252726f?auto=format&fit=crop&w=2200&q=85'
+export default function Project03() { return
A visual system in motion
Keep the words minimal when the work can carry the story. Add your own images to the public/images folder and update this page.
This template is a starting point. Change the visual language, layout, and interaction until it feels like you.
}
diff --git a/src/styles/components.css b/src/styles/components.css
new file mode 100644
index 0000000..8c898bc
--- /dev/null
+++ b/src/styles/components.css
@@ -0,0 +1 @@
+/* Component-specific styles can be added here as students customize the kit. */
diff --git a/src/styles/global.css b/src/styles/global.css
new file mode 100644
index 0000000..d25cbe1
--- /dev/null
+++ b/src/styles/global.css
@@ -0,0 +1,14 @@
+body { background: var(--color-background); color: var(--color-text); font-family: var(--font-sans); font-size: 16px; line-height: 1.5; }
+::selection { background: var(--color-text); color: var(--color-background); }
+:focus-visible { outline: 2px solid var(--color-text); outline-offset: 5px; }
+.eyebrow { color: var(--color-muted); font-size: .75rem; letter-spacing: .08em; text-transform: uppercase; }
+h1, h2, h3 { font-weight: 400; letter-spacing: -.05em; line-height: .95; }
+h1 { font-size: clamp(3.5rem, 9vw, 9rem); }
+h2 { font-size: clamp(2rem, 4vw, 4.5rem); }
+h3 { font-size: 1.35rem; }
+em { font-family: Georgia, serif; font-weight: 400; }
+.lede { color: var(--color-muted); font-size: clamp(1.1rem, 1.7vw, 1.5rem); max-width: 32rem; }
+.muted { color: var(--color-muted); }
+.text-link { border-bottom: 1px solid var(--color-text); display: inline-flex; gap: .75rem; padding-bottom: .25rem; transition: opacity .2s ease; }
+.text-link:hover { opacity: .55; }
+@media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; } }
diff --git a/src/styles/layout.css b/src/styles/layout.css
new file mode 100644
index 0000000..d670a8a
--- /dev/null
+++ b/src/styles/layout.css
@@ -0,0 +1,57 @@
+.container { margin-inline: auto; max-width: var(--container-width); padding-inline: clamp(1.25rem, 5vw, 5rem); width: 100%; }
+.site-shell { min-height: 100vh; }
+.site-header { align-items: center; display: flex; justify-content: space-between; padding-block: 1.5rem; }
+.brand { font-size: .9rem; font-weight: 700; letter-spacing: .08em; }
+.brand span { color: var(--color-muted); }
+.site-header nav { align-items: center; display: flex; gap: 1.5rem; }
+.site-header nav a { color: var(--color-muted); font-size: .9rem; }
+.site-header nav a:hover, .site-header nav a.active { color: var(--color-text); }
+.site-footer { border-top: 1px solid var(--color-line); color: var(--color-muted); display: flex; font-size: .8rem; justify-content: space-between; margin-top: var(--space-xl); padding-block: 1.5rem; }
+.home-hero { min-height: 75vh; padding-bottom: var(--space-xl); padding-top: 16vh; }
+.home-hero h1 { margin-block: 1.5rem 2rem; }
+.home-hero .text-link { margin-top: 3rem; }
+.section { padding-block: var(--space-xl); }
+.section-heading { display: grid; gap: var(--space-md); grid-template-columns: 1fr 2fr; margin-bottom: 4rem; }
+.intro-copy { display: grid; gap: var(--space-lg); grid-template-columns: 1fr 1fr; margin-left: 33.33%; max-width: 45rem; }
+.project-grid { display: grid; gap: var(--space-lg) var(--space-md); grid-template-columns: repeat(2, 1fr); }
+.project-card:first-child { grid-column: span 2; }
+.project-image { aspect-ratio: 4 / 3; background-position: center; background-size: cover; overflow: hidden; padding: 1rem; transition: transform .5s ease; }
+.project-card:hover .project-image { transform: scale(.98); }
+.project-image span { background: var(--color-background); border-radius: 50%; display: grid; font-size: .75rem; height: 2.5rem; place-items: center; width: 2.5rem; }
+.project-meta { display: flex; justify-content: space-between; padding-top: 1rem; }
+.project-meta p, .project-meta > span { color: var(--color-muted); font-size: .85rem; margin-top: .25rem; }
+.page-intro { padding-block: 12vh var(--space-xl); }
+.page-intro h1 { margin-top: 2rem; }
+.about-grid, .detail-grid { display: grid; gap: var(--space-lg); grid-template-columns: 1fr 1fr; margin-left: 33.33%; max-width: 50rem; }
+.about-lede { font-size: 1.5rem; line-height: 1.2; }
+.profile-list { display: grid; gap: var(--space-lg); grid-template-columns: repeat(3, 1fr); margin-left: 33.33%; }
+.profile-list h3 { font-size: 1rem; letter-spacing: 0; margin-bottom: 1rem; }
+.profile-list p { color: var(--color-muted); font-size: .9rem; margin-bottom: .35rem; }
+.not-found { padding-block: 18vh; }
+.not-found h1 { margin-block: 2rem 3rem; }
+.project-hero { padding-block: 10vh var(--space-xl); }
+.project-hero-copy { display: grid; gap: 2rem; grid-template-columns: 1fr 2fr; }
+.project-hero-copy h1 { grid-column: 2; }
+.project-hero-copy .lede { grid-column: 2; }
+.hero-image { background-position: center; background-size: cover; height: min(55vw, 42rem); margin-top: 5rem; }
+.detail-grid dl { display: grid; font-size: .9rem; grid-template-columns: 1fr 2fr; row-gap: .5rem; }
+.detail-grid dt { color: var(--color-muted); }
+.prose { margin-left: 33.33%; max-width: 50rem; }
+.prose > p { max-width: 30rem; }
+.image-grid { display: grid; gap: 1rem; grid-template-columns: repeat(2, 1fr); margin-top: 4rem; }
+.grid-image { aspect-ratio: 1; background-position: center; background-size: cover; }
+.highlight-box { background: var(--color-text); color: var(--color-background); margin-left: 33.33%; padding: 5rem; }
+.highlight-box p { font-family: Georgia, serif; font-size: clamp(2rem, 4vw, 4rem); line-height: 1; }
+.project-navigation { border-top: 1px solid var(--color-line); margin-top: var(--space-xl); padding-block: 2rem 5rem; }
+.project-navigation > a { align-items: center; display: flex; gap: 1rem; justify-content: space-between; padding-top: 1.5rem; }
+.project-navigation strong { font-size: clamp(2rem, 5vw, 5rem); font-weight: 400; letter-spacing: -.05em; }
+.editorial-feature { background-position: center; background-size: cover; height: 70vh; margin-inline: 5vw; }
+.editorial-intro { font-size: clamp(1.5rem, 3vw, 3rem); line-height: 1.1; margin-left: 33.33%; max-width: 40rem; }
+.editorial blockquote { font-family: Georgia, serif; font-size: clamp(3rem, 8vw, 8rem); line-height: .9; margin: var(--space-xl) auto; max-width: 1200px; padding-inline: clamp(1.25rem, 5vw, 5rem); }
+.visual-project .project-hero { padding-bottom: 4rem; }
+.visual-stack { display: grid; gap: 4rem; grid-template-columns: 1fr 1fr; }
+.visual-image { background-position: center; background-size: cover; grid-column: span 2; min-height: 70vh; }
+.visual-image.tall { min-height: 100vh; }
+.visual-caption { align-self: center; max-width: 20rem; }
+.narrow-copy { font-size: 1.5rem; margin-left: 33.33%; max-width: 30rem; }
+@media (max-width: 720px) { .site-header nav { gap: .8rem; } .site-header nav a { font-size: .8rem; } .home-hero { min-height: 70vh; padding-top: 12vh; } .section-heading, .intro-copy, .about-grid, .detail-grid, .profile-list, .project-hero-copy { display: block; margin-left: 0; } .section-heading > h2 { margin-top: 1.5rem; } .intro-copy > p + p { margin-top: 2rem; } .project-grid { display: block; } .project-card { display: block; margin-bottom: 3rem; } .project-card:first-child { grid-column: auto; } .project-hero-copy h1, .project-hero-copy .lede { margin-top: 1.5rem; } .hero-image { height: 65vw; margin-top: 3rem; } .profile-list > div + div { margin-top: 2.5rem; } .prose, .highlight-box, .editorial-intro, .narrow-copy { margin-left: 0; } .highlight-box { padding: 2rem; } .image-grid { grid-template-columns: 1fr; } .editorial-feature { height: 55vh; margin-inline: 1.25rem; } .visual-stack { display: block; } .visual-image { margin-bottom: 3rem; min-height: 60vh; } .visual-image.tall { min-height: 80vh; } .visual-caption { margin-bottom: 3rem; } .site-footer { display: block; } .site-footer span { display: block; } .site-footer span + span { margin-top: .5rem; } }
diff --git a/src/styles/reset.css b/src/styles/reset.css
new file mode 100644
index 0000000..9f84cc8
--- /dev/null
+++ b/src/styles/reset.css
@@ -0,0 +1,6 @@
+*, *::before, *::after { box-sizing: border-box; }
+html { scroll-behavior: smooth; }
+body, h1, h2, h3, p, dl, dd, blockquote { margin: 0; }
+img { display: block; max-width: 100%; }
+a { color: inherit; text-decoration: none; }
+button, input { font: inherit; }
diff --git a/src/styles/variables.css b/src/styles/variables.css
new file mode 100644
index 0000000..0c0a577
--- /dev/null
+++ b/src/styles/variables.css
@@ -0,0 +1,14 @@
+:root {
+ --color-background: #f5f5f2;
+ --color-surface: #e9e9e4;
+ --color-text: #171717;
+ --color-muted: #777773;
+ --color-line: #d1d1cc;
+ --font-sans: Arial, Helvetica, sans-serif;
+ --space-xs: .5rem;
+ --space-sm: 1rem;
+ --space-md: 2rem;
+ --space-lg: 4rem;
+ --space-xl: 8rem;
+ --container-width: 1440px;
+}
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..9ffcc67
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,6 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+export default defineConfig({
+ plugins: [react()],
+})