first upload

This commit is contained in:
2026-08-09 04:10:45 +09:00
parent 85e77b77fd
commit ef7a961af3
27 changed files with 1120 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
dist/
node_modules/

14
index.html Normal file
View File

@@ -0,0 +1,14 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="UX/UI Portfolio Starter Kit" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>Portfolio Starter Kit</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

855
package-lock.json generated Normal file
View File

@@ -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
}
}
}
}
}

19
package.json Normal file
View File

@@ -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": {}
}

1
public/favicon.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="12" fill="#111"/><path d="M17 17h30v7H25v8h18v7H25v8h22v7H17z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 176 B

28
src/App.jsx Normal file
View File

@@ -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 (
<div className="site-shell">
<Header />
<main>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/works/project-01" element={<Project01 />} />
<Route path="/works/project-02" element={<Project02 />} />
<Route path="/works/project-03" element={<Project03 />} />
<Route path="*" element={<NotFound />} />
</Routes>
</main>
<Footer />
</div>
)
}

View File

@@ -0,0 +1,3 @@
export default function Footer() {
return <footer className="site-footer container"><span>© 2025 Your Name</span><span>Designed & built with curiosity.</span></footer>
}

14
src/components/Header.jsx Normal file
View File

@@ -0,0 +1,14 @@
import { NavLink } from 'react-router-dom'
export default function Header() {
return (
<header className="site-header container">
<NavLink className="brand" to="/" aria-label="Portfolio home">YOUR NAME<span>.</span></NavLink>
<nav aria-label="Main navigation">
<NavLink to="/">Home</NavLink>
<NavLink to="/about">About</NavLink>
<a href="mailto:hello@example.com">Contact</a>
</nav>
</header>
)
}

View File

@@ -0,0 +1,3 @@
export default function ImageGrid({ images }) {
return <div className="image-grid">{images.map((image, index) => <div key={image} className={`grid-image grid-image-${index + 1}`} style={{ backgroundImage: `url(${image})` }} role="img" aria-label={`Project image ${index + 1}`} />)}</div>
}

View File

@@ -0,0 +1,5 @@
import { Link } from 'react-router-dom'
export default function ProjectCard({ title, category, year, image, to, number }) {
return <Link className="project-card" to={to}><div className="project-image" style={{ backgroundImage: `url(${image})` }}><span>{number}</span></div><div className="project-meta"><div><h3>{title}</h3><p>{category}</p></div><span>{year}</span></div></Link>
}

View File

@@ -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 <div className="project-grid">{projects.map((project) => <ProjectCard key={project.number} {...project} />)}</div>
}

View File

@@ -0,0 +1,3 @@
export default function ProjectHero({ number, category, title, description, image, className = '' }) {
return <section className={`project-hero container ${className}`}><div className="project-hero-copy"><p className="eyebrow">{number} / {category}</p><h1>{title}</h1>{description && <p className="lede">{description}</p>}</div>{image && <div className="hero-image" style={{ backgroundImage: `url(${image})` }} aria-label={`${title} project visual`} role="img" />}</section>
}

View File

@@ -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 <div className="project-navigation container"><p className="eyebrow">Next project</p><Link to={next.to}><span>{next.number}</span><strong>{next.title}</strong><span className="arrow"></span></Link></div>
}

View File

@@ -0,0 +1,3 @@
export default function Section({ eyebrow, title, children, className = '' }) {
return <section className={`section container ${className}`}><div className="section-heading">{eyebrow && <p className="eyebrow">{eyebrow}</p>}<h2>{title}</h2></div>{children}</section>
}

17
src/main.jsx Normal file
View File

@@ -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(
<React.StrictMode>
<HashRouter>
<App />
</HashRouter>
</React.StrictMode>,
)

5
src/pages/About.jsx Normal file
View File

@@ -0,0 +1,5 @@
import Section from '../components/Section'
export default function About() {
return <div className="about-page"><section className="page-intro container"><p className="eyebrow">About</p><h1>Curious by default.<br /><em>Intentional</em> by design.</h1></section><Section eyebrow="01 / Introduction" title="A little about me."><div className="about-grid"><p className="about-lede">Hello, Im Your Name a UX/UI designer interested in the space between people, technology, and culture.</p><p>I enjoy making complex things feel simple and building visual systems that have room to breathe. This is placeholder copy: make it yours.</p></div></Section><Section eyebrow="02 / Profile" title="Experience & skills."><div className="profile-list"><div><h3>Experience</h3><p>2024 Now · Independent Designer</p><p>2022 2024 · Design Studio</p></div><div><h3>Skills</h3><p>Research · UX/UI · Prototyping<br />Art Direction · Visual Design · Writing</p></div><div><h3>Contact</h3><a className="text-link" href="mailto:hello@example.com">hello@example.com </a></div></div></Section></div>
}

11
src/pages/Home.jsx Normal file
View File

@@ -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 <>
<section className="home-hero container"><p className="eyebrow">UX / UI Designer & Visual Thinker</p><h1>Making space<br />for <em>better ideas.</em></h1><p className="lede">A starter portfolio for documenting thoughtful digital experiences, experiments, and everything in between.</p><Link className="text-link" to="/about">More about me <span></span></Link></section>
<Section eyebrow="01 / Intro" title="I turn questions into clear, useful experiences."><div className="intro-copy"><p>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.</p><p className="muted">Currently available for selected projects · Seoul, KR</p></div></Section>
<Section eyebrow="02 / Selected works" title="A few things Ive made." className="works-section"><ProjectGrid /></Section>
</>
}

2
src/pages/NotFound.jsx Normal file
View File

@@ -0,0 +1,2 @@
import { Link } from 'react-router-dom'
export default function NotFound() { return <section className="not-found container"><p className="eyebrow">404 / Not found</p><h1>This page took<br /><em>a different route.</em></h1><Link className="text-link" to="/">Back to home </Link></section> }

View File

@@ -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 <article className="project-page case-study"><ProjectHero number="01" category="UX Case Study · 2025" title="Project One" description="A clear, end-to-end case study layout for showing how a design decision moves from question to outcome." image={image} /><Section eyebrow="Overview" title="Designing clarity into a crowded workflow."><div className="detail-grid"><p>Replace this overview with the context, role, timeline, and collaborators for your project.</p><dl><dt>Role</dt><dd>UX / UI Designer</dd><dt>Timeline</dt><dd>8 weeks</dd><dt>Team</dt><dd>Product, Engineering</dd></dl></div></Section><Section eyebrow="Problem / Research" title="Start with the question, not the answer."><div className="prose"><p>Use this section to explain what you learned from users and the opportunity you found. A good case study makes the thinking visible.</p><ImageGrid images={[image, 'https://images.unsplash.com/photo-1559028012-481c04fa702d?auto=format&fit=crop&w=1400&q=80']} /></div></Section><Section eyebrow="Insight / Solution / Result" title="One focused idea can shift the whole experience."><div className="highlight-box"><p>Good design gives people confidence to move forward.</p></div></Section><ProjectNavigation current="01" /></article> }

View File

@@ -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 <article className="project-page editorial"><ProjectHero number="02" category="Editorial Interface · 2024" title="Project Two" description="A looser, editorial canvas for projects where the narrative and visual rhythm lead." /><div className="editorial-feature" style={{ backgroundImage: `url(${images[0]})` }} role="img" aria-label="Editorial project feature" /><Section eyebrow="The idea" title="Let the work set the pace."><p className="editorial-intro">Use large type, generous margins, and changing image scales to give a project its own voice. This layout is intentionally different from Project One.</p><ImageGrid images={images.slice(1)} /></Section><blockquote>The most interesting detail is often the one you almost missed.</blockquote><ProjectNavigation current="02" /></article> }

View File

@@ -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 <article className="project-page visual-project"><ProjectHero number="03" category="Visual Direction · 2024" title="Project Three" description="A visual-first project page where images do most of the talking." image={image} /><div className="visual-stack container"><div className="visual-image" style={{ backgroundImage: `url(${image})` }} /><div className="visual-caption"><p className="eyebrow">A visual system in motion</p><p>Keep the words minimal when the work can carry the story. Add your own images to the public/images folder and update this page.</p></div><div className="visual-image tall" style={{ backgroundImage: `url(https://images.unsplash.com/photo-1558655146-d09347e92766?auto=format&fit=crop&w=1800&q=80)` }} /></div><Section eyebrow="Notes" title="Make room for the unexpected."><p className="narrow-copy">This template is a starting point. Change the visual language, layout, and interaction until it feels like you.</p></Section><ProjectNavigation current="03" /></article> }

View File

@@ -0,0 +1 @@
/* Component-specific styles can be added here as students customize the kit. */

14
src/styles/global.css Normal file
View File

@@ -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; } }

57
src/styles/layout.css Normal file
View File

@@ -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; } }

6
src/styles/reset.css Normal file
View File

@@ -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; }

14
src/styles/variables.css Normal file
View File

@@ -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;
}

6
vite.config.js Normal file
View File

@@ -0,0 +1,6 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
})