layout, new work, analytics
This commit is contained in:
parent
b019401fb8
commit
7777235104
37 changed files with 1722 additions and 1314 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -11,3 +11,6 @@ vite.config.ts.timestamp-*
|
|||
|
||||
# Local Netlify folder
|
||||
.netlify
|
||||
|
||||
# IDE files
|
||||
.idea
|
||||
746
package-lock.json
generated
746
package-lock.json
generated
|
|
@ -21,6 +21,7 @@
|
|||
"@sveltejs/adapter-node": "^5.0.0",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.1.1",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@types/node": "^20.5.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
|
|
@ -29,11 +30,11 @@
|
|||
"eslint-plugin-svelte": "^3.0.0",
|
||||
"prettier": "^3.0.0",
|
||||
"prettier-plugin-svelte": "^3.0.0",
|
||||
"sass": "^1.64.2",
|
||||
"sharp": "^0.32.5",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"svelte-preprocess": "^6.0.3",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^5.0.0",
|
||||
"vanilla-lazyload": "^17.8.4",
|
||||
|
|
@ -1357,6 +1358,278 @@
|
|||
"vite": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/node": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz",
|
||||
"integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/remapping": "^2.3.4",
|
||||
"enhanced-resolve": "^5.18.3",
|
||||
"jiti": "^2.6.1",
|
||||
"lightningcss": "1.30.2",
|
||||
"magic-string": "^0.30.21",
|
||||
"source-map-js": "^1.2.1",
|
||||
"tailwindcss": "4.1.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz",
|
||||
"integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tailwindcss/oxide-android-arm64": "4.1.18",
|
||||
"@tailwindcss/oxide-darwin-arm64": "4.1.18",
|
||||
"@tailwindcss/oxide-darwin-x64": "4.1.18",
|
||||
"@tailwindcss/oxide-freebsd-x64": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-arm64-musl": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-x64-gnu": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-x64-musl": "4.1.18",
|
||||
"@tailwindcss/oxide-wasm32-wasi": "4.1.18",
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.18",
|
||||
"@tailwindcss/oxide-win32-x64-msvc": "4.1.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-android-arm64": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz",
|
||||
"integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-darwin-arm64": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz",
|
||||
"integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-darwin-x64": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz",
|
||||
"integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-freebsd-x64": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz",
|
||||
"integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz",
|
||||
"integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz",
|
||||
"integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz",
|
||||
"integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz",
|
||||
"integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz",
|
||||
"integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz",
|
||||
"integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==",
|
||||
"bundleDependencies": [
|
||||
"@napi-rs/wasm-runtime",
|
||||
"@emnapi/core",
|
||||
"@emnapi/runtime",
|
||||
"@tybys/wasm-util",
|
||||
"@emnapi/wasi-threads",
|
||||
"tslib"
|
||||
],
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/core": "^1.7.1",
|
||||
"@emnapi/runtime": "^1.7.1",
|
||||
"@emnapi/wasi-threads": "^1.1.0",
|
||||
"@napi-rs/wasm-runtime": "^1.1.0",
|
||||
"@tybys/wasm-util": "^0.10.1",
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz",
|
||||
"integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz",
|
||||
"integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/vite": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz",
|
||||
"integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tailwindcss/node": "4.1.18",
|
||||
"@tailwindcss/oxide": "4.1.18",
|
||||
"tailwindcss": "4.1.18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^5.2.0 || ^6 || ^7"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
|
||||
|
|
@ -1701,19 +1974,6 @@
|
|||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
|
|
@ -1878,15 +2138,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
|
|
@ -1972,42 +2223,19 @@
|
|||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
|
|
@ -2224,10 +2452,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
|
||||
"integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -2272,6 +2501,20 @@
|
|||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.19.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz",
|
||||
"integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
|
||||
|
|
@ -2868,6 +3111,13 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
|
|
@ -2931,12 +3181,6 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.2.tgz",
|
||||
"integrity": "sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
|
@ -3001,18 +3245,6 @@
|
|||
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.16.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||
|
|
@ -3108,6 +3340,16 @@
|
|||
"resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz",
|
||||
"integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw=="
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
||||
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/js-binary-schema-parser": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz",
|
||||
|
|
@ -3169,6 +3411,267 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
|
||||
"integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"lightningcss-darwin-arm64": "1.30.2",
|
||||
"lightningcss-darwin-x64": "1.30.2",
|
||||
"lightningcss-freebsd-x64": "1.30.2",
|
||||
"lightningcss-linux-arm-gnueabihf": "1.30.2",
|
||||
"lightningcss-linux-arm64-gnu": "1.30.2",
|
||||
"lightningcss-linux-arm64-musl": "1.30.2",
|
||||
"lightningcss-linux-x64-gnu": "1.30.2",
|
||||
"lightningcss-linux-x64-musl": "1.30.2",
|
||||
"lightningcss-win32-arm64-msvc": "1.30.2",
|
||||
"lightningcss-win32-x64-msvc": "1.30.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-android-arm64": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
|
||||
"integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
|
||||
"integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
|
||||
"integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
|
||||
"integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
|
||||
"integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
|
||||
"integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
|
||||
"integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
|
||||
"integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
|
||||
"integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
|
||||
"integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"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.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
|
||||
"integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
||||
|
|
@ -3378,15 +3881,6 @@
|
|||
"integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
|
|
@ -3894,15 +4388,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.10.0"
|
||||
"node": ">= 14.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
|
|
@ -4060,23 +4556,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.64.2",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.64.2.tgz",
|
||||
"integrity": "sha512-TnDlfc+CRnUAgLO9D8cQLFu/GIjJIzJCGkE7o4ekIGQOH7T3GetiRR/PsTWJUHhkzcSPrARkPI+gNWn5alCzDg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
"immutable": "^4.0.0",
|
||||
"source-map-js": ">=0.6.2 <2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"sass": "sass.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.7.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||
|
|
@ -4367,36 +4846,6 @@
|
|||
"typescript": ">=5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-check/node_modules/chokidar": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-check/node_modules/readdirp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-cloudinary": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte-cloudinary/-/svelte-cloudinary-1.3.2.tgz",
|
||||
|
|
@ -4567,6 +5016,27 @@
|
|||
"@types/estree": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
|
||||
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
|
||||
"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
"@sveltejs/adapter-node": "^5.0.0",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.1.1",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@types/node": "^20.5.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
|
|
@ -26,11 +27,11 @@
|
|||
"eslint-plugin-svelte": "^3.0.0",
|
||||
"prettier": "^3.0.0",
|
||||
"prettier-plugin-svelte": "^3.0.0",
|
||||
"sass": "^1.64.2",
|
||||
"sharp": "^0.32.5",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"svelte-preprocess": "^6.0.3",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^5.0.0",
|
||||
"vanilla-lazyload": "^17.8.4",
|
||||
|
|
@ -40,8 +41,8 @@
|
|||
"dependencies": {
|
||||
"gsap": "^3.13.0",
|
||||
"mdsvex": "^0.11.0",
|
||||
"pixi.js": "^8.15.0",
|
||||
"pixi-filters": "^6.1.5",
|
||||
"pixi.js": "^8.15.0",
|
||||
"superjson": "^1.13.1",
|
||||
"svelte-cloudinary": "^1.1.0"
|
||||
}
|
||||
|
|
|
|||
200
src/lib/components/Carousel.svelte
Normal file
200
src/lib/components/Carousel.svelte
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { gsap } from 'gsap';
|
||||
import { ScrollToPlugin } from 'gsap/ScrollToPlugin';
|
||||
import { CldImage } from 'svelte-cloudinary';
|
||||
|
||||
interface Props {
|
||||
images: string[];
|
||||
title: string;
|
||||
}
|
||||
let { images, title }: Props = $props();
|
||||
|
||||
gsap.registerPlugin(ScrollToPlugin);
|
||||
|
||||
let wrapperEl: HTMLDivElement;
|
||||
|
||||
onMount(() => {
|
||||
let is_landscape = window.matchMedia('(orientation:landscape)').matches;
|
||||
window.addEventListener('resize', () => {
|
||||
is_landscape = window.matchMedia('(orientation:landscape)').matches;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
document.querySelectorAll('.gallery img')?.forEach((image) => {
|
||||
const img = image as HTMLImageElement;
|
||||
if (!img.complete) {
|
||||
img.classList.add('imageIsLoading');
|
||||
img.onload = () => {
|
||||
gsap.fromTo(
|
||||
img,
|
||||
{ autoAlpha: 0, scale: 1.2 },
|
||||
{ autoAlpha: 1, scale: 1, duration: 1, ease: 'power4.out' }
|
||||
);
|
||||
};
|
||||
}
|
||||
});
|
||||
}, 10);
|
||||
|
||||
const gallery = document.querySelector('.gallery') as HTMLElement;
|
||||
let isAnimating = false;
|
||||
const galleryClickHandler = (e: MouseEvent) => {
|
||||
if (isAnimating) return;
|
||||
const allImgs = gallery.querySelectorAll('figure');
|
||||
const scrollX = gallery.scrollLeft;
|
||||
const imgWidth = allImgs[0].offsetWidth || 0;
|
||||
const imgCount = allImgs.length;
|
||||
const galleryOuterWidth = wrapperEl?.offsetWidth || 0;
|
||||
const galleryOverlap = imgWidth - (galleryOuterWidth % imgWidth);
|
||||
const maxScrollX = imgWidth * (imgCount - 1);
|
||||
const imgIndex =
|
||||
scrollX < maxScrollX ? Math.round(scrollX / imgWidth) : imgCount - 1;
|
||||
let newScrollPos;
|
||||
if (imgIndex < imgCount - 2) {
|
||||
newScrollPos = scrollX + imgWidth;
|
||||
} else if (imgIndex === imgCount - 2) {
|
||||
newScrollPos = is_landscape
|
||||
? scrollX + galleryOverlap * 0.8
|
||||
: scrollX + galleryOverlap * 0.85;
|
||||
} else {
|
||||
newScrollPos = 0;
|
||||
}
|
||||
gsap.to(gallery, {
|
||||
scrollTo: { x: newScrollPos, autoKill: false },
|
||||
duration: 0.75,
|
||||
ease: 'power4.out',
|
||||
onStart: () => {
|
||||
isAnimating = true;
|
||||
},
|
||||
onComplete: () => {
|
||||
isAnimating = false;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const hoverElement = document.createElement('div');
|
||||
hoverElement.classList.add('hoverElement');
|
||||
wrapperEl?.appendChild(hoverElement);
|
||||
|
||||
const galleryHoverHandler = (e: MouseEvent) => {
|
||||
gsap.to(hoverElement, {
|
||||
x: e.clientX,
|
||||
y: e.clientY + 25,
|
||||
rotateX: 10,
|
||||
rotateZ: -5,
|
||||
autoAlpha: 1,
|
||||
duration: 0.3,
|
||||
overwrite: true,
|
||||
});
|
||||
};
|
||||
const galleryLeaveHandler = () => {
|
||||
gsap.to(hoverElement, {
|
||||
autoAlpha: 0,
|
||||
duration: 0.3,
|
||||
overwrite: true,
|
||||
});
|
||||
};
|
||||
|
||||
if (gallery) {
|
||||
gallery.addEventListener('click', galleryClickHandler);
|
||||
gallery.addEventListener('mousemove', galleryHoverHandler);
|
||||
gallery.addEventListener('mouseleave', galleryLeaveHandler);
|
||||
}
|
||||
|
||||
return () => {
|
||||
gallery?.removeEventListener('click', galleryClickHandler);
|
||||
gallery?.removeEventListener('mousemove', galleryHoverHandler);
|
||||
gallery?.removeEventListener('mouseleave', galleryLeaveHandler);
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="
|
||||
gallery-wrapper
|
||||
relative
|
||||
w-screen overflow-hidden
|
||||
pb-[1em] z-1
|
||||
perspective-[250px] perspective-origin-[center_bottom]
|
||||
md:py-[2em] md:pb-[2.5em]
|
||||
md:mb-[-120px]
|
||||
md:perspective-normal
|
||||
"
|
||||
bind:this={wrapperEl}
|
||||
>
|
||||
<div
|
||||
class="
|
||||
gallery
|
||||
relative flex scroll-smooth gap-0
|
||||
overflow-x-auto snap-x snap-mandatory
|
||||
origin-center transform-[rotate3d(-2,0,1,-10deg)]
|
||||
[scrollbar-width:none]
|
||||
w-[115vw] -left-[4vw]
|
||||
md:w-[110vw] md:-left-[3vw]
|
||||
"
|
||||
>
|
||||
{#each images as image (image)}
|
||||
<figure
|
||||
class="
|
||||
flex flex-col overflow-hidden justify-center snap-start
|
||||
px-px flex-[1_0_85%] h-full aspect-140/84 w-auto m-0
|
||||
md:flex-[1_0_66.666%]
|
||||
[&_img]:w-full [&_img]:h-full [&_img]:object-top-left
|
||||
[&_video]:w-full [&_video]:h-full [&_video]:object-top-left [&_video]:object-cover
|
||||
"
|
||||
>
|
||||
{#if image.includes('/video/')}
|
||||
<video src={image} width="1400" height="840" autoplay muted loop></video>
|
||||
{:else}
|
||||
<CldImage
|
||||
src={image}
|
||||
alt={title}
|
||||
sizes="(min-width: 768px) 67vw, 90vw"
|
||||
width={1400}
|
||||
height={840}
|
||||
placeholder="blur"
|
||||
loading="eager"
|
||||
objectFit="cover"
|
||||
/>
|
||||
{/if}
|
||||
</figure>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.gallery::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
:global(.imageIsLoading) {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
:global(.hoverElement) {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: var(--color-bg);
|
||||
z-index: 100;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
box-shadow: -4px 4px 8px rgba(0, 0, 0, 0.2);
|
||||
pointer-events: none;
|
||||
}
|
||||
:global(.hoverElement)::before {
|
||||
content: url('/moveright.svg');
|
||||
font-size: 33px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
@media (pointer: coarse) {
|
||||
:global(.hoverElement) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -70,14 +70,13 @@
|
|||
</div>
|
||||
</details>
|
||||
|
||||
<style lang="scss">
|
||||
<style>
|
||||
details {
|
||||
--height: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
transition: margin-bottom .3s ease-out;
|
||||
margin-bottom: .1em;
|
||||
transition: margin-bottom .3s ease-out;
|
||||
}
|
||||
summary {
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
|
|
@ -88,37 +87,29 @@
|
|||
line-height: 1.2;
|
||||
font-size: 1em;
|
||||
padding: 0.5em 0 0.5em 1.75em;
|
||||
|
||||
&::-webkit-details-marker {
|
||||
display:none;
|
||||
}
|
||||
|
||||
&:before, &:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: .5em;
|
||||
top: 1em;
|
||||
width: 17px;
|
||||
height: 2px;
|
||||
background-color: var(--color-text);
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
&:before {
|
||||
transform: rotate(90deg);
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
|
||||
}
|
||||
:global(summary em) {
|
||||
font-weight: 800;
|
||||
summary::-webkit-details-marker { display: none; }
|
||||
summary::before, summary::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: .5em;
|
||||
top: 1em;
|
||||
width: 17px;
|
||||
height: 2px;
|
||||
background-color: var(--color-text);
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
// details[open] summary,
|
||||
summary::before {
|
||||
transform: rotate(90deg);
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
:global(summary em) { font-weight: 800; }
|
||||
:global(details.is-open summary) {
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
&:before {
|
||||
transition: all .2s ease-in-out;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
:global(details.is-open summary)::before {
|
||||
transition: all .2s ease-in-out;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
.faq-content {
|
||||
border-top: 1px solid var(--color-bg);
|
||||
|
|
@ -129,16 +120,8 @@
|
|||
font-size: 1em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:global(.faq-content p, .faq-content li){
|
||||
font-size: 1em!important;
|
||||
}
|
||||
:global(.faq-content li){
|
||||
margin-left: 2em;
|
||||
}
|
||||
:global(.faq-content > :first-child){
|
||||
margin-top: 0;
|
||||
}
|
||||
:global(.faq-content > :last-child){
|
||||
margin-bottom: 0;
|
||||
}
|
||||
:global(.faq-content p, .faq-content li) { font-size: 1em !important; }
|
||||
:global(.faq-content li) { margin-left: 2em; }
|
||||
:global(.faq-content > :first-child) { margin-top: 0; }
|
||||
:global(.faq-content > :last-child) { margin-bottom: 0; }
|
||||
</style>
|
||||
|
|
@ -10,9 +10,9 @@
|
|||
<MainNav />
|
||||
</header>
|
||||
|
||||
<style lang="scss">
|
||||
<style>
|
||||
@media screen and (max-width: 767px) {
|
||||
.header-nav:before {
|
||||
.header-nav::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
left: 0;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@
|
|||
<HomeIlluShape />
|
||||
<HomeIlluShape />
|
||||
<HomeIlluShape />
|
||||
<HomeIlluShape />
|
||||
<HomeIlluShape />
|
||||
<!-- <HomeIlluShape />
|
||||
<HomeIlluShape />
|
||||
<HomeIlluShape />
|
||||
|
|
@ -90,7 +92,7 @@
|
|||
gap: clamp(1px, 0.3vw, 5px);
|
||||
}
|
||||
:global(.home-illu-shapes > *) {
|
||||
flex-basis: calc(33.333% - clamp(1px, 0.3vw, 5px));
|
||||
flex-basis: calc(25% - clamp(1px, 0.3vw, 5px));
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -3,66 +3,53 @@
|
|||
<p>Loading...</p>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.loader {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
animation: fade-in .5s cubic-bezier(0.165, 0.84, 0.44, 1) .3s forwards;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px var(--spacing-outer);
|
||||
z-index: 1000;
|
||||
background-color: var(--color-bg);
|
||||
|
||||
& p {
|
||||
<style>
|
||||
.loader {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
animation: fade-in .5s cubic-bezier(0.165, 0.84, 0.44, 1) .3s forwards;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px var(--spacing-outer);
|
||||
z-index: 1000;
|
||||
background-color: var(--color-bg);
|
||||
}
|
||||
.loader p {
|
||||
font-size: .75em;
|
||||
line-height: 1;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
.lds-circle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transform: translateZ(1px);
|
||||
}
|
||||
.lds-circle > div {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-text);
|
||||
animation: lds-circle 6s cubic-bezier(0, 0.2, 0.8, 1) infinite;
|
||||
}
|
||||
@keyframes lds-circle {
|
||||
0%, 100% {
|
||||
animation-timing-function: cubic-bezier(0.5, 0, 1, 0.5);
|
||||
.lds-circle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transform: translateZ(1px);
|
||||
}
|
||||
0% {
|
||||
transform: rotateY(0deg);
|
||||
.lds-circle > div {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-text);
|
||||
animation: lds-circle 6s cubic-bezier(0, 0.2, 0.8, 1) infinite;
|
||||
}
|
||||
50% {
|
||||
transform: rotateY(1800deg);
|
||||
animation-timing-function: cubic-bezier(0, 0.5, 0.5, 1);
|
||||
@keyframes lds-circle {
|
||||
0%, 100% { animation-timing-function: cubic-bezier(0.5, 0, 1, 0.5); }
|
||||
0% { transform: rotateY(0deg); }
|
||||
50% {
|
||||
transform: rotateY(1800deg);
|
||||
animation-timing-function: cubic-bezier(0, 0.5, 0.5, 1);
|
||||
}
|
||||
100% { transform: rotateY(3600deg); }
|
||||
}
|
||||
100% {
|
||||
transform: rotateY(3600deg);
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; transform: translateY(100%); }
|
||||
to { opacity: 1; transform: translateY(0%); }
|
||||
}
|
||||
}
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,35 +1,21 @@
|
|||
<script lang="ts">
|
||||
import { logotext } from "$lib/utils/stores";
|
||||
|
||||
// let $logotexttext = logotext.subscribe((value) => JSON.stringify(value));
|
||||
</script>
|
||||
<!-- <svg id="floter-logo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 287.4 83.5" width="290" height="85">
|
||||
<path id="r" d="M259.9 82.4h-24.2l11.6-54.9h22l-2.7 12.9c4.5-8.9 11-14 18.1-14 1 0 2.1 0 2.7.2l-4.7 22.1c-1.4-.4-3.3-.9-6.4-.9-5.4 0-9.7 2.3-10.8 7.7l-5.6 26.9z"/>
|
||||
<path id="e" d="M237.9 59.3h-35.7c.3 5.2 2.2 7.5 6.5 7.5 2.9 0 5.1-1.5 5.9-4.2h22.3c-4.3 13.2-14.5 20.9-30.4 20.9-16.3 0-26.5-9.7-26.5-25.2 0-17.8 13.4-32 32.3-32 16.3 0 26.5 9.7 26.5 25.2 0 2.7-.4 5.3-.9 7.8zM203.3 50h13.5c-.2-4-1.8-6.5-6-6.5-3.4 0-6.1 2.1-7.5 6.5z"/>
|
||||
<path id="t" d="M171.5 65.9c1.9 0 4.3-.3 6.3-1L174 82.2c-2.5.8-7.1 1.3-11.1 1.3-14 0-23.2-5.1-19.6-22.3l3.5-16.7h-5.5l3.6-17h5.5l3.3-15.4H178l-3.3 15.4h11l-3.6 17h-11l-3.3 15.8c-.9 3.9.3 5.6 3.7 5.6z"/>
|
||||
<polygon id="odash" points="137.1,22.5 94.7,22.4 98.2,5.7 140.6,5.9 "/>
|
||||
<path id="o" d="M111.4 26.4c16.7 0 27.2 9.7 27.2 25.2 0 17.8-13.7 32-33.1 32-16.7 0-27.2-9.7-27.2-25.2 0-17.9 13.8-32 33.1-32zm-3.9 36.7c5.3 0 8.8-4.3 8.8-9.4 0-4.2-2.5-6.8-6.6-6.8-5.4 0-8.9 4.3-8.9 9.4 0 4.1 2.5 6.8 6.7 6.8z"/>
|
||||
<polygon id="l" points="45.5,82.4 63,0 87.1,0 69.7,82.4"/>
|
||||
<polygon id="F" points="17.5,0 59.7,0 55.5,19.8 36.9,19.8 34.1,33 50.5,33 46.3,52.7 29.9,52.7 23.6,82.4 0,82.4"/>
|
||||
</svg> -->
|
||||
<div id="floter-logo">{$logotext}</div>
|
||||
|
||||
<style>
|
||||
/* #floter-logo {
|
||||
fill: currentColor;
|
||||
height: 100%;
|
||||
width: auto;
|
||||
display: block;
|
||||
} */
|
||||
#floter-logo {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
font-size: 36px;
|
||||
letter-spacing: -0.033em;
|
||||
line-height: 36px;
|
||||
<div id="floter-logo">
|
||||
{$logotext}
|
||||
</div>
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 48px;
|
||||
}
|
||||
<style>
|
||||
#floter-logo {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
font-size: 36px;
|
||||
letter-spacing: -0.033em;
|
||||
line-height: 36px;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 48px;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
||||
|
|
@ -48,7 +48,11 @@
|
|||
<header>
|
||||
<input aria-hidden="true" type="checkbox" id="menustate" />
|
||||
<label for="menustate" aria-hidden="true">
|
||||
<span class="open">≡</span>
|
||||
<span class="open">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-12 h-12">
|
||||
<path d="M3 4H21V6H3V4ZM9 11H21V13H9V11ZM3 18H21V20H3V18Z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="close">×</span>
|
||||
</label>
|
||||
<nav id="nav">
|
||||
|
|
@ -61,10 +65,10 @@
|
|||
</nav>
|
||||
</header>
|
||||
|
||||
<style lang="scss">
|
||||
<style>
|
||||
header {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 3;
|
||||
padding: var(--spacing-nav);
|
||||
|
|
@ -74,9 +78,7 @@
|
|||
align-items: flex-end;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
label {
|
||||
height: 36px;
|
||||
}
|
||||
label { height: 36px; }
|
||||
.open, .close {
|
||||
font-size: 4em;
|
||||
line-height: 0.3;
|
||||
|
|
@ -84,25 +86,11 @@
|
|||
z-index: 2;
|
||||
cursor: url('/pointer.svg'), auto;
|
||||
}
|
||||
.close {
|
||||
top: 0.033em;
|
||||
}
|
||||
#menustate, #nav, .close {
|
||||
/* Hide the checkbox, menu and close button by default */
|
||||
display: none;
|
||||
}
|
||||
#menustate:checked ~ #nav ,
|
||||
#menustate:checked ~ label .close {
|
||||
/*
|
||||
Show the menu and close button when the menu is open
|
||||
(when the #menustate input field is checked)
|
||||
*/
|
||||
display: block;
|
||||
}
|
||||
#menustate:checked ~ label .open {
|
||||
/* Hide the open button when the menu is open */
|
||||
display: none;
|
||||
}
|
||||
.close { top: 0.033em; }
|
||||
#menustate, #nav, .close { display: none; }
|
||||
#menustate:checked ~ #nav,
|
||||
#menustate:checked ~ label .close { display: block; }
|
||||
#menustate:checked ~ label .open { display: none; }
|
||||
#nav {
|
||||
background-color: var(--color-bg);
|
||||
position: fixed;
|
||||
|
|
@ -118,31 +106,21 @@
|
|||
font-size: 2.5em;
|
||||
font-weight: 800;
|
||||
font-style: italic;
|
||||
// text-transform: lowercase;
|
||||
text-decoration: none;
|
||||
color: var(--color-text);
|
||||
outline: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
transition: color .1s ease-out;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 4.5em;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 1em;
|
||||
}
|
||||
&:hover {
|
||||
color: var(--color-highlight);
|
||||
}
|
||||
&:active {
|
||||
color: var(--color-highlight);
|
||||
}
|
||||
&.current {
|
||||
color: var(--color-highlight);
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
#nav a:first-child { margin-top: 1em; }
|
||||
#nav a:hover, #nav a:active { color: var(--color-highlight); }
|
||||
#nav a.current {
|
||||
color: var(--color-highlight);
|
||||
transition: none;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
#nav a { font-size: 4.5em; }
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
:root {
|
||||
@import "tailwindcss";
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--spacing-outer: 5vw;
|
||||
--spacing-nav: 5vw;
|
||||
--color-bg: rgb(207, 63, 70);;
|
||||
--color-text: rgb(255, 234, 217);
|
||||
--color-highlight: rgb(29, 12, 18);
|
||||
--color-bg: rgb(0, 0, 90);
|
||||
--color-text: rgb(255, 240, 240);
|
||||
--color-highlight: rgb(250, 125, 0);
|
||||
|
||||
--color-bg-variant-1: rgb(207, 63, 70);
|
||||
--color-text-variant-1: rgb(255, 234, 217);
|
||||
|
|
@ -20,13 +23,13 @@
|
|||
--color-bg-variant-4: rgb(238, 127, 1);
|
||||
--color-text-variant-4: rgb(253, 254, 255);
|
||||
--color-highlight-variant-4: rgb(0, 39, 67);
|
||||
|
||||
|
||||
--aspect-ratio-heroes: 1.5;
|
||||
--font-size-p: clamp(20px, 1.6vw, 1.6vw);
|
||||
--font-size-p: clamp(20px, 1.6vw, 125px);
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
--spacing-outer: 5vw;
|
||||
--spacing-nav: 2.5vw;
|
||||
--spacing-nav: 2.5vw;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +51,7 @@
|
|||
a:hover, input:hover, button:hover {
|
||||
cursor: url('/pointer.svg'), auto;
|
||||
}
|
||||
|
||||
body {
|
||||
cursor: url('/cursor.svg'), auto;
|
||||
font-family: stratos, sans-serif;
|
||||
|
|
@ -61,47 +65,59 @@ body {
|
|||
overflow-x: hidden;
|
||||
transition: background-color .5s ease-in-out, color .5s ease-in-out;
|
||||
}
|
||||
|
||||
body * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
h1, h2, h3, h4, h5 {
|
||||
}
|
||||
|
||||
:where(h1, h2, h3, h4, h5) {
|
||||
font-size: 2em;
|
||||
line-height: 1.1;
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: '▪︎ ';
|
||||
}
|
||||
|
||||
p, li {
|
||||
font-weight: 400;
|
||||
font-size: var(--font-size-p);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-underline-offset: 0.25em;
|
||||
text-decoration-thickness: 0.066em;
|
||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
&:hover {
|
||||
text-underline-offset: 0.1em;
|
||||
}
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-underline-offset: 0.1em;
|
||||
}
|
||||
|
||||
.cta {
|
||||
font-size: clamp(20px, 1.6vw, 1.6vw);
|
||||
}
|
||||
|
||||
.button {
|
||||
font-weight: 800;
|
||||
font-style: italic;
|
||||
|
|
@ -118,88 +134,99 @@ a {
|
|||
position: relative;
|
||||
z-index: 2;
|
||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--color-bg);
|
||||
@media screen and (min-width: 768px) {
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0px;
|
||||
bottom: 0;
|
||||
border: 2px solid var(--color-text);
|
||||
background-color: var(--color-bg);
|
||||
box-sizing: border-box;
|
||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
&:hover:before {
|
||||
background-color: var(--color-text);
|
||||
width: calc(100% + 0.25em);
|
||||
height: calc(100% + 10px);
|
||||
left: -0.125em;
|
||||
bottom: -5px;
|
||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
&.button--primary {
|
||||
color: var(--color-text);
|
||||
.button:hover {
|
||||
color: var(--color-bg);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--color-highlight);
|
||||
}
|
||||
&:before {
|
||||
background-color: var(--color-highlight);
|
||||
border: 2px solid var(--color-highlight);
|
||||
}
|
||||
&:hover:before {
|
||||
background-color: var(--color-text);
|
||||
border: 2px solid var(--color-text);
|
||||
}
|
||||
}
|
||||
&.button--xl {
|
||||
font-size: clamp(24px, 3.2vw, 3.2vw);
|
||||
padding: 0.5em;
|
||||
letter-spacing: -0.02em;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
letter-spacing: 0;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
.button:hover {
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
}
|
||||
|
||||
.button::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0px;
|
||||
bottom: 0;
|
||||
border: 2px solid var(--color-text);
|
||||
background-color: var(--color-bg);
|
||||
box-sizing: border-box;
|
||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
.button:hover::before {
|
||||
background-color: var(--color-text);
|
||||
width: calc(100% + 0.25em);
|
||||
height: calc(100% + 10px);
|
||||
left: -0.125em;
|
||||
bottom: -5px;
|
||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
.button.button--primary {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.button.button--primary:hover {
|
||||
color: var(--color-highlight);
|
||||
}
|
||||
|
||||
.button.button--primary::before {
|
||||
background-color: var(--color-highlight);
|
||||
border: 2px solid var(--color-highlight);
|
||||
}
|
||||
|
||||
.button.button--primary:hover::before {
|
||||
background-color: var(--color-text);
|
||||
border: 2px solid var(--color-text);
|
||||
}
|
||||
|
||||
.button.button--xl {
|
||||
font-size: clamp(24px, 3.2vw, 3.2vw);
|
||||
padding: 0.5em;
|
||||
letter-spacing: -0.02em;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.button.button--xl:hover {
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
// border-top: 2px solid var(--color-text);
|
||||
// border-bottom: 2px solid var(--color-text);
|
||||
padding: 1.5em 0;
|
||||
font-size: var(--font-size-p);
|
||||
|
||||
& li {
|
||||
border-bottom: 1px solid;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
& > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
& > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.content{
|
||||
|
||||
.infobox li {
|
||||
border-bottom: 1px solid;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
.infobox > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.infobox > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.hide-on-mobile {
|
||||
@media screen and (orientation: portrait) and (max-width: 767px) {
|
||||
|
||||
@media screen and (orientation: portrait) and (max-width: 767px) {
|
||||
.hide-on-mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,4 +2,4 @@ import { writable } from 'svelte/store';
|
|||
|
||||
export const workbulge = writable(0.25);
|
||||
export const loading = writable(false);
|
||||
export const logotext = writable('Flöter');
|
||||
export const logotext = writable('FlöTeR');
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import '$lib/styles/global.scss';
|
||||
import '$lib/styles/global.css';
|
||||
import Header from '$lib/components/Header.svelte';
|
||||
import Loader from '$lib/components/Loader.svelte';
|
||||
import { page } from '$app/state';
|
||||
|
|
@ -12,11 +12,10 @@
|
|||
pathname: string;
|
||||
}
|
||||
|
||||
// onMount(() => {
|
||||
// // console.log('layout mounted');
|
||||
// // Set initial random background color on first load
|
||||
// setRandomBgColor();
|
||||
// });
|
||||
onMount(() => {
|
||||
// console.log('layout mounted');
|
||||
setTheme();
|
||||
});
|
||||
|
||||
let { children }: { children: Snippet } = $props();
|
||||
|
||||
|
|
@ -31,35 +30,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
function setRandomBgColor() {
|
||||
const currentBgColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--color-bg');
|
||||
const currentHighlightColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--color-highlight');
|
||||
const currentTextColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--color-text');
|
||||
|
||||
let variantNumber: number;
|
||||
let variantBgColor: string;
|
||||
let variantHighlightColor: string;
|
||||
let variantTextColor: string;
|
||||
|
||||
// Keep picking a random variant until it's different from the current color
|
||||
do {
|
||||
variantNumber = Math.floor(Math.random() * 4) + 1;
|
||||
variantBgColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue(`--color-bg-variant-${variantNumber}`);
|
||||
variantHighlightColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue(`--color-highlight-variant-${variantNumber}`);
|
||||
variantTextColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue(`--color-text-variant-${variantNumber}`);
|
||||
} while (variantBgColor.trim() === currentBgColor.trim());
|
||||
|
||||
document.documentElement.style.setProperty('--color-bg', variantBgColor);
|
||||
document.documentElement.style.setProperty('--color-highlight', variantHighlightColor);
|
||||
document.documentElement.style.setProperty('--color-text', variantTextColor);
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
beforeNavigate((nav) => {
|
||||
// token to avoid races between overlapping navigations
|
||||
|
|
@ -68,9 +38,6 @@
|
|||
clearTimer();
|
||||
showLoader = false;
|
||||
|
||||
// Change background color on route change
|
||||
// setRandomBgColor();
|
||||
|
||||
// only show if navigation takes >150ms
|
||||
timer = setTimeout(() => {
|
||||
if (token === navToken) showLoader = true;
|
||||
|
|
@ -81,9 +48,23 @@
|
|||
if (token !== navToken) return;
|
||||
clearTimer();
|
||||
showLoader = false;
|
||||
setTheme();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setTheme() {
|
||||
if (page.data.theme) {
|
||||
document.documentElement.style.setProperty('--color-bg', page.data.theme.bg);
|
||||
document.documentElement.style.setProperty('--color-text', page.data.theme.text);
|
||||
document.documentElement.style.setProperty('--color-highlight', page.data.theme.highlight);
|
||||
} else {
|
||||
document.documentElement.style.setProperty('--color-bg', 'var(--color-bg)');
|
||||
document.documentElement.style.setProperty('--color-text', 'var(--color-text)');
|
||||
document.documentElement.style.setProperty('--color-highlight', 'var(--color-highlight)');
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
|
@ -93,14 +74,13 @@
|
|||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="description" content={page.data.description ? page.data.description : 'Simon Flöter is a designer and creative developer'} />
|
||||
<title>{page.data.title ? page.data.title : 'Simon Flöter, Designer and Creative Developer'}</title>
|
||||
<script defer data-domain="floter.design" src="https://analytics.floter.design/js/script.js"></script>
|
||||
</svelte:head>
|
||||
|
||||
<Header />
|
||||
<!-- {#key data.pathname} -->
|
||||
<div class="content">
|
||||
{#if showLoader}
|
||||
<Loader />
|
||||
{/if}
|
||||
{@render children()}
|
||||
</div>
|
||||
<!-- {/key} -->
|
||||
</div>
|
||||
|
|
@ -22,6 +22,14 @@
|
|||
gsap.registerPlugin( ScrollTrigger, ScrollToPlugin, SplitText );
|
||||
|
||||
const sections = document.querySelectorAll('section');
|
||||
const highlight = document.querySelector('h1 em');
|
||||
|
||||
gsap.to(highlight, {
|
||||
duration: .5,
|
||||
color: 'var(--color-highlight)',
|
||||
ease: 'power4.out',
|
||||
delay: 2
|
||||
})
|
||||
|
||||
sections.forEach( (section) => {
|
||||
if ( section.classList.contains('splash')){
|
||||
|
|
@ -93,210 +101,155 @@
|
|||
|
||||
</script>
|
||||
|
||||
<article class="scroller">
|
||||
<section class="canvasized splash">
|
||||
<h1 class="align-middle">I create digital experiences that <em>stand out</em> from the rest.</h1>
|
||||
<article class="scroller text-[clamp(32px,4.5vw,4.5vw)]">
|
||||
<section
|
||||
class="
|
||||
canvasized splash
|
||||
snap-start box-border
|
||||
px-(--spacing-outer) p-(--spacing-outer)
|
||||
min-h-svh flex flex-col justify-center
|
||||
max-w-full landscape:max-w-[75vw] landscape:mx-auto
|
||||
cursor-[url('/pointer.svg'),auto]
|
||||
"
|
||||
>
|
||||
<h1
|
||||
class="
|
||||
align-middle select-none
|
||||
leading-[0.85] text-[14.75vw] tracking-[-0.05em]
|
||||
text-(--color-text)
|
||||
landscape:text-[9vw] landscape:px-4
|
||||
landscape:-mt-[0.5em]
|
||||
[&_em]:not-italic [&_em]:font-normal
|
||||
opacity-0 invisible
|
||||
"
|
||||
>
|
||||
I'm Simon Flöter. <br>
|
||||
I create brands and websites that <em>stand out.</em>
|
||||
</h1>
|
||||
</section>
|
||||
<section class="dev">
|
||||
<figure class="dev-image">
|
||||
|
||||
<section
|
||||
class="
|
||||
dev snap-start box-border
|
||||
px-(--spacing-outer) min-h-svh
|
||||
flex flex-col justify-center
|
||||
landscape:max-w-[75vw] landscape:mx-auto
|
||||
"
|
||||
>
|
||||
<figure
|
||||
class="
|
||||
dev-image relative left-0 text-center block -z-2
|
||||
-my-2 -mb-[0.5em]
|
||||
landscape:-my-[1.5em] landscape:-mb-[0.5em]
|
||||
"
|
||||
>
|
||||
<HomeIlluDev />
|
||||
</figure>
|
||||
<h2>Creative Development</h2>
|
||||
<p>I create exquisitly tailored web experiences for discerning enterprises and their audiences.</p>
|
||||
<div class="cta">
|
||||
<a href="/service" class="button">Services <span class="hide-on-mobile"> I provide</span></a>
|
||||
<a href="/contact" class="button button--primary">Contact me</a>
|
||||
<h2
|
||||
class="
|
||||
select-none cursor-[url('/pointer.svg'),auto]
|
||||
text-[12vw] leading-[0.9] tracking-[-0.033em] mb-[0.5em]
|
||||
landscape:text-[6vw] landscape:m-0
|
||||
[&_em]:not-italic [&_em]:font-normal [&_em]:text-(--color-highlight)
|
||||
"
|
||||
>
|
||||
Creative Development
|
||||
</h2>
|
||||
<p
|
||||
class="
|
||||
text-[0.66em] mb-[1em]
|
||||
landscape:mt-4 landscape:mb-[0.25em] landscape:text-[0.6em] landscape:tracking-[-0.02em]
|
||||
"
|
||||
>
|
||||
I create exquisitly tailored web experiences for discerning enterprises and their audiences.
|
||||
</p>
|
||||
<div class="cta mt-2 pt-0 landscape:pt-4 landscape:mt-0">
|
||||
<a href="/service" class="button select-none"
|
||||
>Services <span class="hide-on-mobile"> I provide</span></a
|
||||
>
|
||||
<a href="/contact" class="button button--primary select-none">Contact me</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="design">
|
||||
<figure class="design-illu">
|
||||
|
||||
<section
|
||||
class="
|
||||
design overflow-hidden snap-start box-border
|
||||
px-(--spacing-outer) min-h-svh
|
||||
flex flex-col justify-center
|
||||
landscape:max-w-[75vw] landscape:mx-auto
|
||||
"
|
||||
>
|
||||
<figure
|
||||
class="
|
||||
design-illu relative left-0 w-3/5 mx-auto text-center block
|
||||
my-0 mb-4 -z-2
|
||||
landscape:mb-12 landscape:w-[45%]
|
||||
"
|
||||
>
|
||||
<HomeIlluShapes />
|
||||
</figure>
|
||||
<h2>Visual Design</h2>
|
||||
<p>I'm a seasoned designer, with a long list of succesful projects and happy clients.</p>
|
||||
<div class="cta">
|
||||
<a href="/work" class="button">Work <span class="hide-on-mobile"> I've done</span></a>
|
||||
<a href="/contact" class="button button--primary">Contact me</a>
|
||||
<h2
|
||||
class="
|
||||
select-none cursor-[url('/pointer.svg'),auto]
|
||||
text-[12vw] leading-[0.9] tracking-[-0.033em] mb-[0.5em]
|
||||
landscape:text-[6vw] landscape:m-0
|
||||
[&_em]:not-italic [&_em]:font-normal [&_em]:text-(--color-highlight)
|
||||
"
|
||||
>
|
||||
Visual Design
|
||||
</h2>
|
||||
<p
|
||||
class="
|
||||
text-[0.66em] mb-[1em]
|
||||
landscape:mt-4 landscape:mb-[0.25em] landscape:text-[0.6em] landscape:tracking-[-0.02em]
|
||||
"
|
||||
>
|
||||
I'm a seasoned designer, with a long list of succesful projects and happy clients.
|
||||
</p>
|
||||
<div class="cta mt-2 pt-0 landscape:pt-4 landscape:mt-0">
|
||||
<a href="/work" class="button select-none"
|
||||
>Work <span class="hide-on-mobile"> I've done</span></a
|
||||
>
|
||||
<a href="/contact" class="button button--primary select-none">Contact me</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="canvasized hireme">
|
||||
<h2 class="align-middle">I am currently available <em>for freelance work.</em></h2>
|
||||
|
||||
<section
|
||||
class="
|
||||
canvasized hireme snap-start box-border
|
||||
px-(--spacing-outer) min-h-svh
|
||||
flex flex-col justify-center
|
||||
landscape:max-w-[95vw] landscape:mx-auto
|
||||
[&_h2]:text-[12.5vw] [&_h2]:mb-6
|
||||
landscape:[&_h2]:text-[8vw] landscape:[&_h2]:mb-2 landscape:[&_h2]:mt-0 landscape:[&_h2]:px-4
|
||||
"
|
||||
>
|
||||
<div class="
|
||||
mb-16 align-middle
|
||||
">
|
||||
<h2
|
||||
class="
|
||||
align-middle select-none cursor-[url('/pointer.svg'),auto]
|
||||
text-[12.5vw] leading-[0.9] tracking-[-0.033em] mb-6
|
||||
landscape:text-[8vw] landscape:mb-16 landscape:mt-0 landscape:px-4
|
||||
opacity-0 invisible
|
||||
[&_em]:not-italic [&_em]:font-normal [&_em]:text-(--color-highlight)
|
||||
"
|
||||
>
|
||||
I am currently available <em>for freelance work.</em>
|
||||
</h2>
|
||||
</div>
|
||||
{#if mounted}
|
||||
<div class="hireme-date">(as of { currentMonth })</div>
|
||||
<div class="hireme-date text-[0.66em] text-center tracking-tight">
|
||||
(as of {currentMonth})
|
||||
</div>
|
||||
{/if}
|
||||
<div class="cta" style="text-align: center">
|
||||
<a href="/contact" class="button button--xl button--primary">Get in touch</a>
|
||||
<div class="cta text-center mt-2 pt-0 landscape:pt-4 landscape:mt-0">
|
||||
<a href="/contact" class="button button--xl button--primary select-none">Get in touch</a>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
<HomeCanvas textsToCanvas={canvasElems} imgsToCanvas={imgElems}/>
|
||||
<div class="canvasResizeToThis"></div>
|
||||
|
||||
<style lang="scss">
|
||||
.canvasResizeToThis {
|
||||
position: fixed;
|
||||
top: -10vh;
|
||||
left: -10vw;
|
||||
width: 120vw;
|
||||
height: 120vh;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
.scroller {
|
||||
font-size: clamp(32px, 4.5vw, 4.5vw);
|
||||
}
|
||||
section {
|
||||
scroll-snap-align: start;
|
||||
box-sizing: border-box;
|
||||
padding: 0 var(--spacing-outer);
|
||||
min-height: 100svh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
justify-content: center;
|
||||
|
||||
@media screen and (orientation: landscape) {
|
||||
max-width: 75vw;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
.splash {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: start;
|
||||
min-height: 100svh;
|
||||
justify-content: center;
|
||||
max-width: 100%;
|
||||
padding: var(--spacing-outer);
|
||||
cursor: url('/pointer.svg'), auto;
|
||||
|
||||
@media screen and (orientation: landscape) {
|
||||
padding: 0 calc(var(--spacing-outer) * 2);
|
||||
|
||||
& h1 {
|
||||
margin: -.5em 0 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.dev-image {
|
||||
position:relative;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
display: block;
|
||||
z-index: -2;
|
||||
margin: -2em 0 -.5em 0;
|
||||
@media screen and (orientation: landscape) {
|
||||
margin: -1.5em 0 -.5em 0;
|
||||
}
|
||||
}
|
||||
.design {
|
||||
overflow: hidden;
|
||||
}
|
||||
.design-illu {
|
||||
position:relative;
|
||||
left: 0;
|
||||
width: 60%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
display: block;
|
||||
margin: 0 auto 1em auto;
|
||||
z-index: -2;
|
||||
|
||||
@media screen and (orientation: landscape) {
|
||||
margin: 0 auto .5em auto;
|
||||
width: 45%;
|
||||
}
|
||||
}
|
||||
.hireme {
|
||||
@media screen and (orientation: landscape) {
|
||||
max-width: 95vw;
|
||||
}
|
||||
}
|
||||
.hireme h2 {
|
||||
font-size: 12.5vw;
|
||||
margin-bottom: 1.5em;
|
||||
@media screen and (orientation: landscape) {
|
||||
font-size: 8vw;
|
||||
margin-bottom: 0.5em;
|
||||
margin-top: 0;
|
||||
padding: 0 .25em;
|
||||
}
|
||||
}
|
||||
.hireme-date {
|
||||
font-size: .66em;
|
||||
text-align: center;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 12vw;
|
||||
line-height: .9;
|
||||
letter-spacing: -0.033em;
|
||||
margin: 0 0 0.5em 0;
|
||||
-webkit-touch-callout: none; /* Safari */
|
||||
-webkit-user-select: none; /* Chrome */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none;
|
||||
cursor: url('/pointer.svg'), auto;
|
||||
@media screen and (orientation: landscape) {
|
||||
font-size: 6vw;
|
||||
margin: 0;
|
||||
}
|
||||
& > em {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
color: var(--color-highlight);
|
||||
}
|
||||
}
|
||||
h1 {
|
||||
line-height: .85;
|
||||
font-size: 14.75vw;
|
||||
letter-spacing: -0.05em;
|
||||
color: var(--color-highlight);
|
||||
-webkit-touch-callout: none; /* Safari */
|
||||
-webkit-user-select: none; /* Chrome */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none;
|
||||
|
||||
@media screen and (orientation: landscape) {
|
||||
font-size: 10vw;
|
||||
padding: 0 1em;
|
||||
}
|
||||
& > em {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
.canvasized h1, .canvasized h2 {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
p {
|
||||
font-size: .66em;
|
||||
margin: 0 0 1em 0;
|
||||
@media screen and (orientation: landscape) {
|
||||
margin: 1em 0 0.25em 0;
|
||||
font-size: 0.6em;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
}
|
||||
a {
|
||||
-webkit-touch-callout: none; /* Safari */
|
||||
-webkit-user-select: none; /* Chrome */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none;
|
||||
}
|
||||
.cta {
|
||||
margin-top: .5em;
|
||||
padding-top: 0em;
|
||||
@media screen and (orientation: landscape) {
|
||||
// background-color: var(--color-bg);
|
||||
// border-top: 1px solid var(--color-text);
|
||||
padding-top: 1em;
|
||||
margin-top: 0em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<HomeCanvas textsToCanvas={canvasElems} imgsToCanvas={imgElems} />
|
||||
<div
|
||||
class="canvasResizeToThis fixed -top-[10vh] -left-[10vw] w-[120vw] h-[120vh] pointer-events-none -z-10"
|
||||
></div>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ export const prerender = true
|
|||
export function load() {
|
||||
return {
|
||||
title: 'Simon Flöter, creative developer and designer',
|
||||
description: 'Simon Flöter is a creative developer and designer you can hire as a freelancer'
|
||||
description: 'Simon Flöter is a creative developer and designer you can hire as a freelancer',
|
||||
theme: {
|
||||
bg: 'rgb(0, 0, 90)',
|
||||
text: 'rgb(255, 240, 240)',
|
||||
highlight: 'rgb(250, 125, 0)',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -78,9 +78,9 @@
|
|||
</script>
|
||||
|
||||
<div class="pagewrapper">
|
||||
<div class="intro">
|
||||
<h1 class="toCanvas">Let's be strange,<br>not strangers.</h1>
|
||||
<div class="alternatives">
|
||||
<div class="intro w-full min-h-screen flex flex-col justify-center pb-16 md:pb-0">
|
||||
<h1 class="toCanvas contact-h1">Let's be strange,<br>not strangers.</h1>
|
||||
<div class="alternatives mx-auto my-0 mb-4 w-full text-center md:mb-8 md:pb-4 [&_p]:opacity-0 [&_.button]:opacity-0 [&_p]:text-base [&_p]:my-2 md:[&_p]:text-[1.33em] [&_ul]:mx-[var(--spacing-outer)] [&_ul]:list-none [&_ul]:flex [&_ul]:justify-center [&_ul]:gap-1 [&_ul_li]:block [&_ul_li]:m-0 [&_.button]:my-1 [&_.button]:block [&_.button]:text-[0.9em] md:[&_.button]:text-[1.2em]">
|
||||
<p>Choose your flavour of contact:</p>
|
||||
<ul>
|
||||
<li><span class="button button--primary" on:click={contactFormClickHandler} on:keydown={contactFormClickHandler} role="button" tabindex="0">Contact form</span></li>
|
||||
|
|
@ -89,30 +89,27 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formwrapper">
|
||||
<span class="button button-back" on:click={contactFormClickHandler} on:keydown={contactFormClickHandler} role="button" tabindex="0">← Back</span>
|
||||
<form name="contact" method="POST" use:enhance>
|
||||
<div class="inputs-flex-row">
|
||||
<label for="name">
|
||||
<!-- <p>How would you like to be addressed?</p> -->
|
||||
<input type="text" name="name" id="name" placeholder="Your name" value={form?.fields?.name ?? ''}>
|
||||
<div class="formwrapper fixed inset-0 w-full h-full p-[var(--spacing-outer)] pb-16 pl-[var(--spacing-outer)] pr-[var(--spacing-outer)] bg-[var(--color-bg)] z-0 opacity-0 invisible overflow-y-auto [--form-maxwidth:1000px]">
|
||||
<span class="button button-back m-0" on:click={contactFormClickHandler} on:keydown={contactFormClickHandler} role="button" tabindex="0">← Back</span>
|
||||
<form name="contact" method="POST" use:enhance class="box-border max-w-[var(--form-maxwidth)] mx-auto overflow-hidden py-4">
|
||||
<div class="inputs-flex-row md:flex md:gap-4 md:justify-center md:max-w-[var(--form-maxwidth)] md:mx-auto [&_label]:md:basis-1/2">
|
||||
<label for="name" class="contact-label">
|
||||
<input type="text" name="name" id="name" placeholder="Your name" value={form?.fields?.name ?? ''} class="contact-input">
|
||||
</label>
|
||||
<label for="email">
|
||||
<!-- <p>For receiving a reply, add your Email address:</p> -->
|
||||
<input type="email" name="email" id="email" placeholder="Your Email?*" required value={form?.fields?.email ?? ''}>
|
||||
<label for="email" class="contact-label">
|
||||
<input type="email" name="email" id="email" placeholder="Your Email?*" required value={form?.fields?.email ?? ''} class="contact-input">
|
||||
</label>
|
||||
</div>
|
||||
<label for="contact">
|
||||
<!-- <p>Please describe your plight in a few words</p> -->
|
||||
<textarea rows="8" name="contact" id="contact" placeholder="Your business propositions, praise, complaints and/or threats" required>{form?.fields?.contact ?? ''}</textarea>
|
||||
<label for="contact" class="contact-label">
|
||||
<textarea rows="8" name="contact" id="contact" placeholder="Your business propositions, praise, complaints and/or threats" required class="contact-input">{form?.fields?.contact ?? ''}</textarea>
|
||||
</label>
|
||||
<div class="disclaimer">
|
||||
<div class="disclaimer max-w-[var(--form-maxwidth)] my-4 mx-auto text-base">
|
||||
<p>Disclaimer: I will only use the data you submit here (name, email, message) to respond. I will not pass it on to any third party. If I don't hear from you I will delete the data and keep no records of it.</p>
|
||||
</div>
|
||||
{#if form?.error}
|
||||
<p class="form-error" role="alert" aria-live="polite">{form.error}</p>
|
||||
<p class="form-error max-w-[var(--form-maxwidth)] mx-auto mb-4 p-3 border border-[var(--color-text)] rounded text-[0.95em] bg-white/10" role="alert" aria-live="polite">{form.error}</p>
|
||||
{/if}
|
||||
<div class="send">
|
||||
<div class="send max-w-[var(--form-maxwidth)] mx-auto">
|
||||
<button class="button button--xl button--primary" type="submit">Send it!</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -120,118 +117,30 @@
|
|||
</div>
|
||||
<ContactCanvas textsToCanvas={canvasTexts} />
|
||||
|
||||
<style lang="scss">
|
||||
h1 {
|
||||
<style>
|
||||
.contact-h1 {
|
||||
visibility: hidden;
|
||||
font-size: 12vw;
|
||||
line-height: .9;
|
||||
letter-spacing: -0.04em;
|
||||
margin: 1em var(--spacing-nav) 1em var(--spacing-nav);
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
.contact-h1 {
|
||||
margin: 1em var(--spacing-outer) .75em var(--spacing-outer);
|
||||
font-size: 4.5em;
|
||||
}
|
||||
}
|
||||
.intro {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding-bottom: 4em;
|
||||
@media screen and (min-width: 768px) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
.formwrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: var(--spacing-outer) var(--spacing-outer) 4em var(--spacing-outer);
|
||||
background-color: var(--color-bg);
|
||||
z-index: 0;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
overflow-y: scroll;
|
||||
|
||||
--form-maxwidth: 1000px;
|
||||
}
|
||||
.button-back {
|
||||
margin: 0;
|
||||
}
|
||||
form {
|
||||
box-sizing: border-box;
|
||||
max-width: inherit;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
padding: 1em 0;
|
||||
}
|
||||
.inputs-flex-row {
|
||||
@media screen and (min-width: 768px) {
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
justify-content: center;
|
||||
max-width: var(--form-maxwidth);
|
||||
margin: auto;
|
||||
|
||||
& label {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.alternatives {
|
||||
margin: 0em auto 1em auto;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
margin: 0 auto 2em auto;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
& p, & .button {
|
||||
opacity: 0;
|
||||
}
|
||||
& p {
|
||||
font-size: 1em;
|
||||
margin: .5em 0;
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 1.33em;
|
||||
}
|
||||
}
|
||||
& ul {
|
||||
margin: 0 var(--spacing-outer);
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: .25em;
|
||||
}
|
||||
& ul li {
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
& .button {
|
||||
margin: 0.25em 0;
|
||||
display: block;
|
||||
font-size: .9em;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
label {
|
||||
.contact-label {
|
||||
font-size: 1em;
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
}
|
||||
input[type='text'], input[type='email'], textarea {
|
||||
@media screen and (min-width: 768px) {
|
||||
.contact-label { font-size: 1.25em; }
|
||||
}
|
||||
.contact-input {
|
||||
width: 100%;
|
||||
border: 0 solid var(--color-text);
|
||||
background-color: var(--color-text);//Overruled by placeholder-shown if no value
|
||||
background-color: var(--color-text);
|
||||
color: var(--color-bg);
|
||||
border-radius: 4px;
|
||||
font-family: 'Stratos', sans-serif;
|
||||
|
|
@ -242,46 +151,20 @@
|
|||
margin: 0 auto 1em auto;
|
||||
display: block;
|
||||
max-width: var(--form-maxwidth);
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
color: var(--color-bg);
|
||||
background-color: var(--color-text);
|
||||
}
|
||||
&:placeholder-shown {
|
||||
background-color: rgba(255, 255, 225, 0.2);
|
||||
}
|
||||
&:focus:placeholder-shown {
|
||||
background-color: var(--color-text);
|
||||
}
|
||||
&::placeholder {
|
||||
color: var(--color-text);
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
// label p {
|
||||
// max-width: var(--form-maxwidth);
|
||||
// margin: 0 auto 1em auto;
|
||||
// display: block;
|
||||
// font-size: .75em;
|
||||
// margin-bottom: .5em;
|
||||
// }
|
||||
.disclaimer p{
|
||||
max-width: var(--form-maxwidth);
|
||||
margin: 1em auto;
|
||||
font-size: 1rem;
|
||||
.contact-input:focus {
|
||||
outline: none;
|
||||
color: var(--color-bg);
|
||||
background-color: var(--color-text);
|
||||
}
|
||||
.form-error {
|
||||
max-width: var(--form-maxwidth);
|
||||
margin: 0 auto 1em auto;
|
||||
padding: .75em;
|
||||
border: 1px solid var(--color-text);
|
||||
border-radius: 4px;
|
||||
font-size: .95em;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
.contact-input:placeholder-shown {
|
||||
background-color: rgba(255, 255, 225, 0.2);
|
||||
}
|
||||
.send {
|
||||
max-width: var(--form-maxwidth);
|
||||
margin: auto;
|
||||
.contact-input:focus:placeholder-shown {
|
||||
background-color: var(--color-text);
|
||||
}
|
||||
.contact-input::placeholder {
|
||||
color: var(--color-text);
|
||||
opacity: .8;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -9,6 +9,10 @@
|
|||
</article>
|
||||
|
||||
<style>
|
||||
:global(body) {
|
||||
background-color: var(--color-text);
|
||||
color: var(--color-highlight);
|
||||
}
|
||||
article {
|
||||
max-width: 1200px;
|
||||
padding: 0
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
||||
import { SplitText } from 'gsap/SplitText';
|
||||
import Faq from '$lib/components/Faq.svelte';
|
||||
import { page } from '$app/state';
|
||||
import ServiceCanvas from './ServiceCanvas.svelte';
|
||||
import { ScrollToPlugin } from 'gsap/ScrollToPlugin';
|
||||
|
||||
|
|
@ -69,7 +70,7 @@
|
|||
})
|
||||
</script>
|
||||
|
||||
<ServiceCanvas />
|
||||
<ServiceCanvas theme={page.data.theme} />
|
||||
<article>
|
||||
<h1>Services I can provide<br><em>↓ Scroll down</em></h1>
|
||||
<div class="services">
|
||||
|
|
@ -136,7 +137,6 @@
|
|||
</Faq>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
<section>
|
||||
<h2>UX/Visual Design</h2>
|
||||
|
|
@ -178,14 +178,21 @@
|
|||
</div>
|
||||
</article>
|
||||
|
||||
<style lang="scss">
|
||||
<style>
|
||||
article {
|
||||
margin: auto;
|
||||
max-width: 1200px;
|
||||
padding: calc(50vh - var(--spacing-outer) - 10vw) var(--spacing-outer) var(--spacing-outer) var(--spacing-outer);
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
padding: calc(50vh - var(--spacing-outer) - 6vw) var(--spacing-outer) var(--spacing-outer) var(--spacing-outer);
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
article {
|
||||
padding: calc(50vh - var(--spacing-outer) - 6vw)
|
||||
var(--spacing-outer)
|
||||
var(--spacing-outer)
|
||||
calc( 2 * var(--spacing-outer) )
|
||||
;
|
||||
/* padding: 0 var(--spacing-outer) 100px var(--spacing-outer); */
|
||||
width: calc(100% - (2 * var(--spacing-outer)));
|
||||
}
|
||||
}
|
||||
h1 {
|
||||
|
|
@ -193,81 +200,59 @@
|
|||
z-index: 3;
|
||||
font-size: 10vw;
|
||||
line-height: 1;
|
||||
|
||||
& em {
|
||||
position: absolute;
|
||||
top: 120%;
|
||||
font-size: .4em;
|
||||
letter-spacing: -0.02em;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 6vw;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
}
|
||||
h1 em {
|
||||
position: absolute;
|
||||
top: 120%;
|
||||
font-size: .4em;
|
||||
letter-spacing: -0.02em;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
color: var(--color-text);
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
h1 { font-size: 6vw; letter-spacing: -0.025em; }
|
||||
}
|
||||
.services {
|
||||
opacity: 0; //changed in ServiceCanvas
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
padding-bottom: calc( 2 * var(--spacing-outer));
|
||||
padding-top: calc(0.5 * var(--spacing-outer));
|
||||
padding-bottom: calc(2 * var(--spacing-outer));
|
||||
}
|
||||
.service-content {
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
display: flex;
|
||||
gap: 1.5em;
|
||||
}
|
||||
}
|
||||
.service-content > :first-child {
|
||||
flex: 0 0 40%;
|
||||
}
|
||||
.service-content > *,
|
||||
.service-content > * > :first-child {
|
||||
@media screen and (min-width: 768px) {
|
||||
@media screen and (min-width: 768px) {
|
||||
.service-content { display: flex; gap: 1.5em; }
|
||||
.service-content > :first-child { flex: 0 0 40%; }
|
||||
.service-content > *, .service-content > * > :first-child {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
|
||||
}
|
||||
.faqs { margin-top: 0; }
|
||||
}
|
||||
.faqs {
|
||||
margin-top: 2em;
|
||||
width: 100%;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
h2 {
|
||||
border-bottom: 1px solid;
|
||||
padding-bottom: .5em;
|
||||
font-size: 1.5em;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
margin: 1em 0 .5em 0;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.25em;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
margin: 1em 0 .5em 0;
|
||||
}
|
||||
em {
|
||||
font-weight: 800;
|
||||
@media screen and (min-width: 768px) {
|
||||
h3 { font-size: 1.5em; }
|
||||
}
|
||||
em { font-weight: 800; }
|
||||
ul li {
|
||||
margin-bottom: .75em;
|
||||
line-height: 1.25;
|
||||
}
|
||||
li, p {
|
||||
font-size: 1em;
|
||||
li, p {
|
||||
font-size: 1em;
|
||||
margin: 1em 0 .5em 0;
|
||||
}
|
||||
p + .button, p + .button + .button {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
p + .button, p + .button + .button { margin-top: 0.33em; }
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
export function load() {
|
||||
return {
|
||||
title: 'Services I provide',
|
||||
description: 'A list of profesional webdevelopment and design services I provide'
|
||||
description: 'A list of profesional webdevelopment and design services I provide',
|
||||
theme: {
|
||||
bg: '#00005A',
|
||||
text: '#FFF0F0',
|
||||
highlight: '#FA7D00',
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@
|
|||
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let { theme } = $props();
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let introDone = false;
|
||||
|
||||
|
|
@ -17,11 +19,25 @@
|
|||
|
||||
(async () => {
|
||||
let highLightColor = window.getComputedStyle(document.body).getPropertyValue('--color-highlight');
|
||||
|
||||
if (theme) {
|
||||
highLightColor = theme.highlight;
|
||||
} else {
|
||||
highLightColor = window.getComputedStyle(document.body).getPropertyValue('--color-highlight');
|
||||
}
|
||||
|
||||
let is_landscape = window.matchMedia('(orientation:landscape)').matches;
|
||||
let isDestroyed = false;
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
// Ensure Stratos is loaded before canvas text (fixes Firefox black blocks on long text)
|
||||
try {
|
||||
await document.fonts.load('bold italic 1em Stratos');
|
||||
} catch {
|
||||
await document.fonts.ready;
|
||||
}
|
||||
|
||||
let app = new PIXI.Application();
|
||||
await app.init({
|
||||
canvas: canvas,
|
||||
|
|
@ -45,15 +61,17 @@
|
|||
|
||||
let fontSize = window.innerHeight / 3;
|
||||
|
||||
const isFirefox = typeof navigator !== 'undefined' && /Firefox/i.test(navigator.userAgent);
|
||||
|
||||
function createText(string: string): PIXI.Text {
|
||||
let text = getTextFromPool();
|
||||
text.text = string;
|
||||
text.style = {
|
||||
fontFamily: 'Stratos',
|
||||
fontSize: fontSize,
|
||||
fontWeight: '800',
|
||||
fontWeight: 'bold',
|
||||
fontStyle: 'italic',
|
||||
lineHeight: 0,
|
||||
lineHeight: fontSize * 0.85,
|
||||
letterSpacing: -10,
|
||||
fill: highLightColor,
|
||||
padding: 0
|
||||
|
|
@ -63,6 +81,37 @@
|
|||
return text
|
||||
}
|
||||
|
||||
/** Firefox renders long canvas text as a black block; use a container of shorter segments. */
|
||||
function createLongTextAsContainer(): PIXI.Container & { width: number; height: number } {
|
||||
const parts = ['CONSULTATION ', 'DESIGN ', 'WEB ', 'DEVELOPMENT '];
|
||||
const container = new PIXI.Container() as PIXI.Container & { width: number; height: number };
|
||||
let x = 0;
|
||||
for (const part of parts) {
|
||||
const text = getTextFromPool();
|
||||
text.text = part;
|
||||
text.style = {
|
||||
fontFamily: 'Stratos',
|
||||
fontSize: fontSize,
|
||||
fontWeight: 'bold',
|
||||
fontStyle: 'italic',
|
||||
lineHeight: fontSize * 0.85,
|
||||
letterSpacing: -10,
|
||||
fill: highLightColor,
|
||||
padding: 0
|
||||
};
|
||||
text.anchor.set(0);
|
||||
text.x = x;
|
||||
text.y = 0;
|
||||
container.addChild(text);
|
||||
x += text.width;
|
||||
}
|
||||
const bounds = container.getBounds();
|
||||
container.width = bounds.width;
|
||||
container.height = bounds.height;
|
||||
textgroup.addChild(container);
|
||||
return container;
|
||||
}
|
||||
|
||||
// Text object pool management
|
||||
function getTextFromPool(): PIXI.Text {
|
||||
if (textPool.length > 0) {
|
||||
|
|
@ -75,11 +124,12 @@
|
|||
textPool.push(text);
|
||||
}
|
||||
|
||||
let allTexts = [
|
||||
const longLine = 'CONSULTATION DESIGN WEB DEVELOPMENT ';
|
||||
let allTexts: (PIXI.Text | (PIXI.Container & { width: number; height: number }))[] = [
|
||||
createText('SERVICES SERVICES '), createText('SERVICES SERVICES '),
|
||||
createText('CONSULTATION DESIGN WEB DEVELOPMENT '), createText('CONSULTATION DESIGN WEB DEVELOPMENT '),
|
||||
isFirefox ? createLongTextAsContainer() : createText(longLine), isFirefox ? createLongTextAsContainer() : createText(longLine),
|
||||
createText('SERVICES SERVICES '), createText('SERVICES SERVICES '),
|
||||
createText('CONSULTATION DESIGN WEB DEVELOPMENT '), createText('CONSULTATION DESIGN WEB DEVELOPMENT ')
|
||||
isFirefox ? createLongTextAsContainer() : createText(longLine), isFirefox ? createLongTextAsContainer() : createText(longLine)
|
||||
]
|
||||
|
||||
let textRows = [
|
||||
|
|
@ -224,8 +274,15 @@
|
|||
}
|
||||
});
|
||||
|
||||
// Return objects to pools
|
||||
allTexts.forEach(text => returnTextToPool(text));
|
||||
// Return objects to pools (containers: return child texts to pool, then destroy container)
|
||||
allTexts.forEach((el) => {
|
||||
if (el instanceof PIXI.Container && 'width' in el) {
|
||||
el.children.forEach((child) => returnTextToPool(child as PIXI.Text));
|
||||
el.destroy();
|
||||
} else {
|
||||
returnTextToPool(el as PIXI.Text);
|
||||
}
|
||||
});
|
||||
// Now safe to destroy PixiJS app
|
||||
app.destroy(true, { children: true, texture: true });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,12 @@ export async function load() {
|
|||
return {
|
||||
posts,
|
||||
title: 'Work References',
|
||||
description: 'A few of the projects I have worked on'
|
||||
description: 'A few of the projects I have worked on',
|
||||
theme: {
|
||||
bg: '#FA7D00',
|
||||
text: '#FFFFFF',
|
||||
highlight: '#00005A',
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading work posts:', error)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,18 @@
|
|||
return a.meta.order - b.meta.order;
|
||||
}));
|
||||
|
||||
function getColorValue(cssValue: string): string {
|
||||
// If it's a CSS variable reference, resolve it
|
||||
if (cssValue.trim().startsWith('var(')) {
|
||||
// Extract the variable name and resolve it
|
||||
const varName = cssValue.match(/var\(([^)]+)\)/)?.[1];
|
||||
if (varName) {
|
||||
return getComputedStyle(document.documentElement).getPropertyValue(varName.trim()).trim() || cssValue;
|
||||
}
|
||||
}
|
||||
return cssValue.trim();
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
document.querySelectorAll('.workclone')?.forEach(clone => {
|
||||
clone.remove();
|
||||
|
|
@ -17,8 +29,20 @@
|
|||
|
||||
let isZoomed = false;
|
||||
|
||||
const currentBgColor = getComputedStyle(document.documentElement).getPropertyValue('--color-bg');
|
||||
const currentHighlightColor = getComputedStyle(document.documentElement).getPropertyValue('--color-highlight');
|
||||
// const currentBgColor = getComputedStyle(document.documentElement).getPropertyValue('--color-bg');
|
||||
// const currentHighlightColor = getComputedStyle(document.documentElement).getPropertyValue('--color-highlight');
|
||||
|
||||
// Read from data.theme if available, otherwise from CSS
|
||||
let currentBgColor: string;
|
||||
let currentHighlightColor: string;
|
||||
|
||||
if (data.theme) {
|
||||
currentBgColor = getColorValue(data.theme.bg);
|
||||
currentHighlightColor = getColorValue(data.theme.highlight);
|
||||
} else {
|
||||
currentBgColor = getComputedStyle(document.documentElement).getPropertyValue('--color-bg').trim();
|
||||
currentHighlightColor = getComputedStyle(document.documentElement).getPropertyValue('--color-highlight').trim();
|
||||
}
|
||||
|
||||
let works: Array<HTMLElement> = Array.from(document.querySelectorAll('.work'));
|
||||
for ( let i = 0; i < 40; i++ ){
|
||||
|
|
@ -241,4 +265,98 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<style src="./work.scss" lang="scss"></style>
|
||||
<style>
|
||||
:global(html) {
|
||||
overflow: hidden;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
.works-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
perspective: 700px;
|
||||
transform-origin: 0 0;
|
||||
will-change: transform;
|
||||
}
|
||||
.headline {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
letter-spacing: -0.05em;
|
||||
z-index: 10;
|
||||
transform: translateZ(500px);
|
||||
margin-left: 40.5vw;
|
||||
margin-top: 37.25vh;
|
||||
font-size: 14vw;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
.headline {
|
||||
margin-left: 41.66vw;
|
||||
margin-top: 40.5vh;
|
||||
font-size: 7vw;
|
||||
transform: translateZ(600px);
|
||||
}
|
||||
}
|
||||
.works {
|
||||
margin: 0 auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 600vw;
|
||||
height: 600vw;
|
||||
transform: scale(.333);
|
||||
transform-origin: 0 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 100vw);
|
||||
grid-auto-rows: 100vh;
|
||||
gap: 6px;
|
||||
will-change: transform;
|
||||
}
|
||||
.work {
|
||||
background-color: var(--color-highlight);
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateZ(700px);
|
||||
will-change: transform;
|
||||
}
|
||||
:global(.work-logo) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: var(--color-bg);
|
||||
padding: 3em;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
will-change: transform;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
:global(.work-logo) { width: 60%; }
|
||||
}
|
||||
:global(.work-logo svg) {
|
||||
object-fit: fill;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.work-info {
|
||||
display: none;
|
||||
}
|
||||
.work-info .tags {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
gap: .25em;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -14,7 +14,10 @@ export async function load( { params }: { params: { slug: string }} ){
|
|||
description = [],
|
||||
images = [],
|
||||
agency = '',
|
||||
agencyName = ''
|
||||
agencyName = '',
|
||||
colorBg = 'var(--color-bg-variant-2)',
|
||||
colorText = 'var(--color-text-variant-2)',
|
||||
colorHighlight = 'var(--color-highlight-variant-2)',
|
||||
} = post.metadata
|
||||
|
||||
// Don't pass the component - it's not serializable
|
||||
|
|
@ -35,6 +38,18 @@ export async function load( { params }: { params: { slug: string }} ){
|
|||
images,
|
||||
agency,
|
||||
agencyName,
|
||||
colorBg,
|
||||
colorText,
|
||||
colorHighlight,
|
||||
theme: [
|
||||
colorBg,
|
||||
colorText,
|
||||
colorHighlight,
|
||||
].every(Boolean) ? {
|
||||
bg: colorBg,
|
||||
text: colorText,
|
||||
highlight: colorHighlight,
|
||||
} : undefined,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
|
|
|||
|
|
@ -1,176 +1,167 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { gsap } from 'gsap';
|
||||
import { ScrollToPlugin } from 'gsap/ScrollToPlugin';
|
||||
import { CldImage } from 'svelte-cloudinary';
|
||||
import Carousel from '$lib/components/Carousel.svelte';
|
||||
let { data } = $props();
|
||||
|
||||
gsap.registerPlugin(ScrollToPlugin);
|
||||
|
||||
onMount(() => {
|
||||
let is_landscape = window.matchMedia('(orientation:landscape)').matches
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
is_landscape = window.matchMedia('(orientation:landscape)').matches
|
||||
})
|
||||
|
||||
if (document.querySelector('.workclone')) {
|
||||
document.querySelector('.workclone')?.remove();
|
||||
}
|
||||
|
||||
setTimeout( () => {
|
||||
document.querySelectorAll('.gallery img')?.forEach( image => {
|
||||
const img = image as HTMLImageElement;
|
||||
if (!img.complete) {
|
||||
img.classList.add('imageIsLoading');
|
||||
img.onload = () => {
|
||||
gsap.fromTo(img, {
|
||||
autoAlpha: 0,
|
||||
scale: 1.2,
|
||||
}, {
|
||||
autoAlpha: 1,
|
||||
scale: 1,
|
||||
duration: 1,
|
||||
ease: 'power4.out',
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}, 10)
|
||||
|
||||
gsap.to('.logo-wrapper', {
|
||||
opacity: 0,
|
||||
scale: 0.85,
|
||||
zIndex: -1,
|
||||
duration: .5,
|
||||
duration: 0.5,
|
||||
ease: 'power2.out',
|
||||
})
|
||||
});
|
||||
gsap.to('.work', {
|
||||
y: '-100vh',
|
||||
duration: 1,
|
||||
ease: 'power4.out',
|
||||
})
|
||||
gsap.to('.gallery-wrapper', {
|
||||
});
|
||||
gsap.to('.carousel', {
|
||||
y: '100vh',
|
||||
duration: 1,
|
||||
ease: 'power4.out',
|
||||
})
|
||||
});
|
||||
|
||||
const gallery = document.querySelector('.gallery') as HTMLElement;
|
||||
let isAnimating = false;
|
||||
const galleryClickHandler = (e: MouseEvent) => {
|
||||
if (isAnimating) return;
|
||||
const allImgs = gallery.querySelectorAll('figure');
|
||||
const scrollX = gallery.scrollLeft;
|
||||
const imgWidth = allImgs[0].offsetWidth || 0;
|
||||
const imgCount = allImgs.length;
|
||||
const galleryOuterWidth = (document.querySelector('.gallery-wrapper') as HTMLElement)?.offsetWidth || 0;
|
||||
const galleryOverlap = imgWidth - galleryOuterWidth % imgWidth;
|
||||
const maxScrollX = imgWidth * (imgCount - 1);
|
||||
const imgIndex = scrollX < maxScrollX ? Math.round(scrollX / imgWidth) : imgCount - 1;
|
||||
let newScrollPos;
|
||||
if (imgIndex < imgCount - 2) {
|
||||
newScrollPos = scrollX + imgWidth;
|
||||
}
|
||||
else if ( imgIndex === imgCount - 2){
|
||||
newScrollPos = is_landscape ? scrollX + galleryOverlap * .8 : scrollX + galleryOverlap * .85 ;
|
||||
}
|
||||
else {
|
||||
newScrollPos = 0;
|
||||
}
|
||||
gsap.to(gallery, {
|
||||
scrollTo: { x: newScrollPos , autoKill: false },
|
||||
duration: .75,
|
||||
ease: 'power4.out',
|
||||
onStart: () => { isAnimating = true },
|
||||
onComplete: () => { isAnimating = false },
|
||||
})
|
||||
}
|
||||
|
||||
const hoverElement = document.createElement('div');
|
||||
hoverElement.classList.add('hoverElement');
|
||||
|
||||
document.querySelector('.gallery-wrapper')?.appendChild(hoverElement);
|
||||
|
||||
const galleryHoverHandler = (e: MouseEvent) => {
|
||||
gsap.to(hoverElement, { x: e.clientX, y: e.clientY + 25, rotateX: 10, rotateZ: -5, autoAlpha: 1, duration: 0.3, overwrite: true })
|
||||
}
|
||||
const galleryLeaveHandler = (e: MouseEvent) => {
|
||||
gsap.to(hoverElement, { autoAlpha: 0, duration: 0.3, overwrite: true })
|
||||
}
|
||||
|
||||
if (gallery) {
|
||||
gallery.addEventListener('click', galleryClickHandler )
|
||||
gallery.addEventListener('mousemove', galleryHoverHandler )
|
||||
gallery.addEventListener('mouseleave', galleryLeaveHandler )
|
||||
}
|
||||
|
||||
|
||||
return () => {
|
||||
gsap.killTweensOf('.logo-wrapper, .work, .gallery-wrapper')
|
||||
gallery.removeEventListener('click', galleryClickHandler )
|
||||
gallery.removeEventListener('mousemove', galleryHoverHandler )
|
||||
gallery.removeEventListener('mouseleave', galleryLeaveHandler )
|
||||
}
|
||||
})
|
||||
|
||||
gsap.killTweensOf('.logo-wrapper, .work, .carousel');
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="logo-wrapper">
|
||||
<div class="svg-logo">{@html data.svg}</div>
|
||||
</div>
|
||||
<div class="subnav">
|
||||
<a href="/work" class="subnav-item button">← Back</a>
|
||||
</div>
|
||||
<div class="gallery-wrapper">
|
||||
<div class="gallery">
|
||||
{#each data.images as image (image)}
|
||||
<figure>
|
||||
{#if image.includes('/video/')}
|
||||
<video src={image} width="1400" height="840" autoplay muted loop></video>
|
||||
{:else}
|
||||
<CldImage
|
||||
src={image}
|
||||
alt={data.title}
|
||||
sizes="(min-width: 768px) 67vw, 90vw"
|
||||
width={1400}
|
||||
height={840}
|
||||
placeholder="blur"
|
||||
loading="eager"
|
||||
objectFit="cover"
|
||||
/>
|
||||
{/if}
|
||||
</figure>
|
||||
{/each}
|
||||
<div
|
||||
class="
|
||||
logo-wrapper
|
||||
fixed z-1
|
||||
w-screen h-screen text-center
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="
|
||||
svg-logo
|
||||
flex flex-col justify-center
|
||||
w-full h-full m-auto p-[3em]
|
||||
text-(--color-highlight)
|
||||
[&_svg]:object-fill [&_svg]:w-full [&_svg]:h-full
|
||||
md:w-3/5
|
||||
"
|
||||
>
|
||||
{@html data.svg}
|
||||
</div>
|
||||
</div>
|
||||
<article class="work">
|
||||
<div class="description">
|
||||
<div
|
||||
class="
|
||||
subnav
|
||||
fixed z-22
|
||||
md:top-0 md:left-0 md:inline-block
|
||||
"
|
||||
>
|
||||
<a
|
||||
href="/work"
|
||||
class="
|
||||
subnav-item button
|
||||
inline-flex items-center gap-2
|
||||
m-(--spacing-nav)
|
||||
"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"
|
||||
class="
|
||||
w-6 h-6
|
||||
inline-block
|
||||
"
|
||||
>
|
||||
<path d="M7.82843 10.9999H20V12.9999H7.82843L13.1924 18.3638L11.7782 19.778L4 11.9999L11.7782 4.22168L13.1924 5.63589L7.82843 10.9999Z"></path>
|
||||
</svg>
|
||||
Back
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="
|
||||
carousel
|
||||
relative md:landscape:absolute z-1
|
||||
-top-[100vh] md:top-[calc(-100vh-10vw)]
|
||||
"
|
||||
>
|
||||
<Carousel images={data.images} title={data.title} />
|
||||
</div>
|
||||
<article
|
||||
class="
|
||||
work
|
||||
relative overflow-hidden
|
||||
top-[100vh] md:landscape:top-[calc(200vh-11.25rem-2.5vw)]
|
||||
px-(--spacing-outer) pb-[100px] pt-0
|
||||
md:landscape:ml-[150px] md:landscape:mr-(--spacing-outer) md:landscape:my-0
|
||||
md:landscape:px-(--spacing-outer) md:landscape:pb-[100px]
|
||||
md:landscape:w-[calc(100%-150px-var(--spacing-outer))]
|
||||
|
||||
[&_h1]:mt-[0.125em] [&_h1]:mb-[0.5em] [&_h1]:text-[2.5rem] [&_h1]:text-(--color-highlight)
|
||||
md:[&_h1]:text-[6rem]
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="
|
||||
description
|
||||
mt-[1.5em] leading-[1.3] tracking-normal uppercase
|
||||
text-xl md:text-[1.75rem]
|
||||
"
|
||||
>
|
||||
{data.description}
|
||||
</div>
|
||||
<h1>{data.title}</h1>
|
||||
<div class="work-content">
|
||||
<div class="infobox">
|
||||
<div
|
||||
class="
|
||||
work-content
|
||||
relative z-2
|
||||
md:flex md:gap-[2em]
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="
|
||||
infobox
|
||||
text-xl pb-[2em]
|
||||
md:flex-[0_0_25%]
|
||||
"
|
||||
>
|
||||
<div class="tasks">
|
||||
<div class="tasks-title">What I did:</div>
|
||||
<ul>
|
||||
<div class="tasks-title font-bold italic mb-[0.125em]">What I did:</div>
|
||||
<ul class="m-0 flex flex-wrap gap-[0.125em]">
|
||||
{#each data.tags as tag (tag)}
|
||||
<li>{tag}</li>
|
||||
<li
|
||||
class="
|
||||
text-base list-none border-none uppercase rounded-[3px]
|
||||
m-0 py-[0.25em] px-[0.33em]
|
||||
bg-(--color-highlight) text-(--color-bg)
|
||||
"
|
||||
>
|
||||
{tag}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="reference">
|
||||
<div class="reference-title">Reference:</div>
|
||||
<div class="reference-title font-bold italic mt-4 mb-0">Reference:</div>
|
||||
<div><a href={data.reference}>{data.referenceName}</a></div>
|
||||
</div>
|
||||
{#if data.agency}
|
||||
<div class="agency">
|
||||
<div class="agency-title">Agency:</div>
|
||||
<div class="agency-title font-bold italic mt-4 mb-0">Agency:</div>
|
||||
<div><a href={data.agency}>{data.agencyName}</a></div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="work-content-text">
|
||||
<div
|
||||
class="
|
||||
work-content-text
|
||||
[&_p]:mt-5
|
||||
[&_h2]:mt-10 [&_h2]:text-[2rem] md:[&_h2]:text-[2.5rem]
|
||||
*:first:mt-0 [&>h1:first-child]:mt-0
|
||||
"
|
||||
>
|
||||
{#await import(`../md/${data.slug}.md`) then { default: Content }}
|
||||
<Content />
|
||||
{:catch error}
|
||||
|
|
@ -179,227 +170,3 @@
|
|||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<style lang="scss">
|
||||
.subnav {
|
||||
position: fixed;
|
||||
z-index: 22;
|
||||
@media screen and (min-width: 768px) {
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
.subnav-item {
|
||||
margin: var(--spacing-nav);
|
||||
}
|
||||
.logo-wrapper {
|
||||
position: fixed;
|
||||
text-align: center;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 1;
|
||||
}
|
||||
.svg-logo {
|
||||
color: var(--color-highlight);
|
||||
padding: 3em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
@media screen and (min-width: 768px) {
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
:global(.svg-logo svg) {
|
||||
object-fit: fill;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.work {
|
||||
position: relative;
|
||||
top: 100vh;
|
||||
overflow: hidden;
|
||||
padding: 0 var(--spacing-outer) 100px var(--spacing-outer);
|
||||
@media screen and (min-width: 768px) {
|
||||
margin: 0 var(--spacing-outer) 0 150px;
|
||||
padding: 0 var(--spacing-outer) 100px var(--spacing-outer);
|
||||
width: calc(100% - 150px - var(--spacing-outer));
|
||||
}
|
||||
}
|
||||
h1 {
|
||||
margin: .125em 0 0.5em 0;
|
||||
font-size: 2.5rem;
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 6rem;
|
||||
}
|
||||
}
|
||||
.description {
|
||||
margin-top: 1.5em;
|
||||
line-height: 1.3;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
font-size: 1.25rem;
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
.infobox {
|
||||
font-size: 1.25rem;
|
||||
padding: 0 0 2em 0;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
flex: 0 0 25%;
|
||||
}
|
||||
}
|
||||
.reference-title, .agency-title, .tasks-title {
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
margin: 0 0 .125em 0;
|
||||
}
|
||||
.reference-title, .agency-title {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.tasks ul {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .125em;
|
||||
}
|
||||
.tasks li {
|
||||
font-size: 1rem;
|
||||
list-style: none;
|
||||
border: none;
|
||||
text-transform: uppercase;
|
||||
border-radius: 3px;
|
||||
margin: 0;
|
||||
padding: 0.25em 0.33em;
|
||||
background-color: var(--color-highlight);
|
||||
color: var(--color-bg);
|
||||
}
|
||||
.work-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
@media screen and (min-width: 768px) {
|
||||
display: flex;
|
||||
gap: 2em;
|
||||
}
|
||||
}
|
||||
.work-content-text :global(h2) {
|
||||
font-size: 2rem;
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
.work-content-text > :global(:first-child) {
|
||||
margin-top: 0;
|
||||
}
|
||||
.work-content-text :global(p) {
|
||||
font-size: 1rem;
|
||||
@media screen and (min-width: 768px) {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
.work-content-text > :global(h1):first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.gallery-wrapper {
|
||||
position: relative;
|
||||
top: -100vh;
|
||||
width: 100vw;
|
||||
overflow: hidden;
|
||||
padding: 0 0 1em 0;
|
||||
z-index: 1;
|
||||
perspective: 250px;
|
||||
perspective-origin: center bottom;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
margin-bottom: -80px;
|
||||
top: calc(-100vh - 80px);
|
||||
padding: 2em 0 4em 0;
|
||||
margin-bottom: -120px;
|
||||
perspective: 500px;
|
||||
}
|
||||
}
|
||||
.gallery {
|
||||
transform-origin: 50% 50%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
scroll-behavior: smooth;
|
||||
gap: 0;
|
||||
overflow-x: scroll;
|
||||
scroll-snap-type: x mandatory;
|
||||
width: 115vw;
|
||||
left: -4vw;
|
||||
transform: rotate3d(-2, 0, 1, -10deg);
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none;
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
width: 110vw;
|
||||
left: -3vw;
|
||||
}
|
||||
}
|
||||
figure {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
scroll-snap-align: start;
|
||||
padding: 0 1px;
|
||||
flex: 1 0 85%;
|
||||
height: 100%;
|
||||
aspect-ratio: 140/84;
|
||||
width: auto;
|
||||
margin: 0;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
flex: 1 0 66.666%;
|
||||
}
|
||||
|
||||
& :global(img), video {
|
||||
opacity: 0.85;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-position: left top;
|
||||
}
|
||||
video {
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
:global(.imageIsLoading) {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
:global(.hoverElement) {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: var(--color-bg);
|
||||
z-index: 100;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
box-shadow: -4px 4px 8px rgba(0,0,0,.2);
|
||||
pointer-events: none;
|
||||
@media screen and (pointer: coarse) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: url('/moveright.svg');
|
||||
font-size: 33px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -4,10 +4,13 @@ header_bg_image: adidas_hero_ceurd8
|
|||
images: [ '/work/adidas/adidas_hero_ceurd8', '/work/adidas/adidas-mockup_ozihu3', '/work/adidas/adidas-illus-bg_t2t5ts' ]
|
||||
order: 12
|
||||
tags: ['graphic design', 'illustration']
|
||||
description: Design & Illustration for the international sports and lifestyle clothing brand.
|
||||
description: Design & Illustration
|
||||
svg: '<svg id="adidas-logo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 1000 674.2" style="enable-background:new 0 0 1000 674.2; fill: currentColor" xml:space="preserve"><path d="M654.5 442.2 448.9 84.8 596.6 0l255.7 442.2H654.5"/><path d="m106.8 392.1 147.7-85.4 78.2 135.5H135.5l-28.7-50.1"/><path d="M396.7 670.2h42V500.1h-42v170.1z"/><path d="M923.6 674.2c-47 0-75.3-24.3-76.8-58.5h44.3c0 10.7 6.7 26.4 35.4 26.9 19.1 0 28.1-11.3 28.1-19.7-1.1-13.4-18-14.5-35.9-17.4-18-2.9-33.3-6.1-44.3-11.8-14.1-7.3-23.7-22.9-23.7-40.9 0-30.4 26.4-54.5 70.3-54.5 42.6 0 69.6 22.4 72.4 55.6h-42.8c-.4-9-2.1-23.1-27.3-23.1-17 0-28.3 3.4-29.2 15.3 0 17.4 35.4 16.2 62.9 23.5 26.4 6.7 43.2 23.1 43.2 46.1-.2 42.2-34.4 58.5-76.6 58.5"/><path d="m280 240.4 147.7-85.2 165.7 287H438.8v42h-42V442L280 240.4"/><path class="st0" d="M283.8 674.2c-48.9 0-88.7-39.9-88.7-88.3 0-48.9 39.7-87.5 88.7-87.5 18.5 0 35.4 5 50.1 15.1v-71.3h42v228h-42v-11.3c-14.8 9.6-31.6 15.3-50.1 15.3zm-48.4-88.3c0 26.4 22.5 48.3 49.5 48.3 26.4 0 48.9-22 48.9-48.3 0-26.4-22.5-48.9-48.9-48.9-26.9 0-49.5 22.5-49.5 48.9"/><path class="st0" d="M594.5 442.2H636v228h-41.5v-11.3c-14.1 9.6-31.5 15.3-50.6 15.3-48.3 0-88.1-39.9-88.1-88.3 0-48.9 39.7-87.5 88.1-87.5 19.1 0 35.9 5 50.6 15.1v-71.3zm-97.8 143.7c0 26.4 22.5 48.3 48.3 48.3 26.9 0 49.5-22 49.5-48.3 0-26.4-22.5-48.9-49.5-48.9-25.8 0-48.3 22.5-48.3 48.9"/><path class="st0" d="M738.2 674.2c-48.2 0-88.1-39.9-88.1-88.3 0-48.9 39.9-87.5 88.1-87.5 18.5 0 35.9 5 50.1 15.1v-13.6h42v170.3h-42v-11.3c-14.2 9.6-31 15.3-50.1 15.3zM691 585.9c0 26.4 22.5 48.3 48.9 48.3s48.3-22 48.3-48.3c0-26.4-22-48.9-48.3-48.9-26.4 0-48.9 22.5-48.9 48.9"/><path class="st0" d="M40.5 585.9c0 26.4 22.5 48.3 48.9 48.3 26.9 0 49.5-22 49.5-48.3 0-26.4-22.5-48.9-49.5-48.9-26.3 0-48.9 22.5-48.9 48.9zm47.8 88.3c-48.4 0-88.3-40-88.3-88.3 0-48.9 39.9-87.5 88.3-87.5 18.5 0 35.9 5 50.6 15.1v-13.6h41.5v170.3h-41.5v-11.3c-14.1 9.6-31.5 15.3-50.6 15.3"/></svg>'
|
||||
reference: https://www.linkedin.com/in/stanislasdupart/
|
||||
referenceName: Stan Dupart
|
||||
colorBg: '#000033'
|
||||
colorText: '#FFFFFF'
|
||||
colorHighlight: '#D21A00'
|
||||
---
|
||||
|
||||
As a freelancer embedded in adidas' ecommerce and digital experiences team, I worked on digital campaigns and assets.
|
||||
|
|
|
|||
28
src/routes/work/md/aqr.md
Normal file
28
src/routes/work/md/aqr.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
title: Association for Qualitative Research
|
||||
images: [
|
||||
'https://res.cloudinary.com/dkvjosg5p/image/upload/v1770633579/work/aqr/aqr_home_ecla11.png',
|
||||
'https://res.cloudinary.com/dkvjosg5p/image/upload/v1770640900/work/aqr/aqr_logo_spacing_qb0a4w.jpg',
|
||||
'https://res.cloudinary.com/dkvjosg5p/image/upload/v1770640900/work/aqr/aqr_handdrawn_varur8.jpg',
|
||||
'https://res.cloudinary.com/dkvjosg5p/image/upload/v1770641360/work/aqr/aqr_join_vx8nwf.png',
|
||||
'https://res.cloudinary.com/dkvjosg5p/image/upload/v1770633577/work/aqr/aqr_directory_vireyu.png',
|
||||
'https://res.cloudinary.com/dkvjosg5p/image/upload/v1770633578/work/aqr/aqr_business_vohd6a.png',
|
||||
'https://res.cloudinary.com/dkvjosg5p/image/upload/v1770641578/work/aqr/aqr_timeline2_q3eue7.png'
|
||||
]
|
||||
order: 12
|
||||
tags: ['Tech consultancy', 'Frontend development', 'Backend Development']
|
||||
description: Brand refresh & new website
|
||||
reference: https://www.linkedin.com/in/judy-taylor-8859822/
|
||||
referenceName: Judy Taylor
|
||||
svg: '<svg width="88" height="77" viewBox="-29.333 -22.666 132 115.5" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M43.0239 67.0494C36.5058 67.0494 31.2033 61.7469 31.2033 55.2288C31.2033 48.7107 36.5058 43.4082 43.0239 43.4082C49.542 43.4082 54.8445 48.7107 54.8445 55.2288C54.8445 61.7469 49.542 67.0494 43.0239 67.0494ZM43.0239 46.7032C38.3241 46.7032 34.4998 50.5275 34.4998 55.2273C34.4998 59.9271 38.3241 63.7515 43.0239 63.7515C47.7237 63.7515 51.548 59.9271 51.548 55.2273C51.548 50.5275 47.7237 46.7032 43.0239 46.7032Z" fill="currentColor"></path><path d="M26.7191 66.1578H30.2179L22.358 44.3144H18.5498L10.6899 66.1578H14.1888L16.1889 60.3773H24.7233L26.7206 66.1578H26.7191ZM17.1465 57.6044L20.3725 48.2825H20.5426L23.7628 57.6044H17.1465Z" fill="currentColor"></path><path d="M75.2303 66.1578L70.3941 57.3272C70.62 57.2436 70.8385 57.1527 71.0437 57.0486C72.1641 56.487 73.0028 55.6995 73.5615 54.6862C74.1202 53.673 74.3989 52.4984 74.3989 51.161C74.3989 49.8237 74.1217 48.6315 73.5674 47.6036C73.0131 46.5756 72.1758 45.7706 71.0555 45.1884C69.9352 44.6048 68.5289 44.3144 66.8367 44.3144H59.0501V66.1578H62.3451V57.8918H66.8249C66.8968 57.8918 66.9657 57.8888 67.0361 57.8874L71.4749 66.1578H75.2303ZM62.3466 47.1416H66.4847C67.5728 47.1416 68.4526 47.3029 69.1242 47.627C69.7958 47.9511 70.29 48.4145 70.6068 49.0186C70.9235 49.6228 71.0819 50.3369 71.0819 51.1625C71.0819 51.9881 70.925 52.6802 70.6126 53.2638C70.3003 53.8475 69.8076 54.2918 69.136 54.5968C68.4644 54.9033 67.5948 55.0558 66.5287 55.0558H62.348V47.1416H62.3466Z" fill="currentColor"></path><path d="M44.3862 54.2991L52.9676 73.5645H83.8835V3.29645H3.29645V73.5645H32.8824L34.0687 76.861H0V0H87.18V76.861H50.4454L40.3962 54.2991H44.3862Z" fill="currentColor"></path></svg>'
|
||||
colorBg: '#4c8618'
|
||||
colorText: 'rgb(255, 228, 207)'
|
||||
colorHighlight: 'rgb(57, 0, 17)'
|
||||
---
|
||||
Zya’s mission is simple: to make better nutrition accessible without sacrificing the taste and enjoyment of everyday food.
|
||||
|
||||
In another collaboration with the ever-inspiring creative agency [forpeople](https://forpeople.com), we created a website with scroll-based storytelling animations that playfully brings the complex information behind the science to life.
|
||||
|
||||
In a second phase we added more storytelling features and a blog.
|
||||
|
||||
<a href="https://zya.co" class="button button--primary" target="_blank">Check it out live</a>
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,11 +1,14 @@
|
|||
---
|
||||
title: etosis
|
||||
images: ['work/etosis/etosis_og_ogqfae', 'https://res.cloudinary.com/dkvjosg5p/video/upload/v1696948648/work/etosis/etosis_mail_wawrua.mp4', 'work/etosis/scrnli_Oct_10_2023_3_._xkz9er', 'work/etosis/scrnli_Oct_10_2023_2_._lxh0xh' ]
|
||||
description: Simple housestyle and website for a software company specialised in complexity
|
||||
description: Housestyle and website
|
||||
referenceName: Patrick Simpson
|
||||
reference: https://www.linkedin.com/in/patricksimpson/
|
||||
tags: ['Housestyle', 'Graphic Design', 'Web Development', 'Animation']
|
||||
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1136.37 547.52"><path style="fill: currentColor" d="M412.35 274.93c.19 3.41.19 6.84 0 10.25H270.51c1.9 26.58 27.34 51.18 60.29 51.18a67.587 67.587 0 0 0 52.7-25.82l20.12 20.88a97.618 97.618 0 0 1-72.82 34.47c-49.3.89-90.04-38.25-91.12-87.55v-4.56c0-51.18 34.93-92.18 87.63-92.18 48.98 0 85.35 36.83 85.35 93.32m-31.13-16.33c-2.78-27.6-26.49-48.32-54.22-47.38-28.03-.97-52.18 19.56-55.73 47.38h109.95ZM421.84 186.16h34.17v-53.15h31.89v53.15h54.67v28.55H487.9v94.69c0 17.08 8.35 26.96 25.44 26.96a42.01 42.01 0 0 0 20.12-7.59l11.77 26.2c-11 6.7-23.57 10.37-36.45 10.63-25.06 0-53.15-16.33-53.15-55.05v-95.83h-34.17l.38-28.55ZM736.66 273.79c1.11 49.86-38.41 91.18-88.27 92.3s-91.18-38.41-92.3-88.27v-4.02c-1.13-49.86 38.37-91.2 88.23-92.33 49.86-1.13 91.2 38.37 92.33 88.23v4.1m-31.89 0c0-34.55-23.16-62.57-58.39-62.57s-58.39 28.1-58.39 62.57 22.78 62.57 58.39 62.57 58.39-28.1 58.39-62.57M772.35 308.64a67.313 67.313 0 0 0 53.15 28.47c17.84 0 37.97-7.59 37.97-21.64 0-15.19-12.91-22.78-39.79-28.1-37.97-7.59-64.09-22.32-64.09-55.35 0-25.44 25.36-50.42 64.47-50.42a91.14 91.14 0 0 1 64.85 26.58l-21.03 21.72a64.366 64.366 0 0 0-43.96-19.29c-22.78 0-33.41 10.93-33.41 22.32 0 13.29 13.67 20.5 42.45 26.58 33.41 7.21 61.81 19.74 61.81 55.43 0 33.71-35.69 51.18-69.4 51.18a95.993 95.993 0 0 1-75.1-36.83l22.1-20.65ZM944.56 108.41c11.95 0 21.64 9.69 21.64 21.64s-9.69 21.64-21.64 21.64c-11.95 0-21.64-9.69-21.64-21.64 0-11.95 9.69-21.64 21.64-21.64m-15.87 77.75h31.89v175.25h-31.89V186.16ZM1013.89 308.64a67.569 67.569 0 0 0 53.15 28.47c17.77 0 37.97-7.59 37.97-21.64 0-15.19-12.91-22.78-39.79-28.1-37.97-7.59-64.09-22.32-64.09-55.35 0-25.44 25.36-50.42 64.47-50.42a91.14 91.14 0 0 1 64.85 26.58l-20.96 21.72a64.583 64.583 0 0 0-43.96-19.29c-22.4 0-33.41 10.93-33.41 22.32 0 13.29 13.67 20.5 42.45 26.58 33.41 7.21 61.81 19.74 61.81 55.43 0 33.71-35.69 51.18-69.4 51.18a95.993 95.993 0 0 1-75.1-36.83l22.02-20.65ZM0 142.65l90.11 59.43-62.71 40.93-.11.09c-4.22 3.38-7.72 7.13-10.41 11.17-10.73 16.86-6.06 38.93 10.59 50.29l63.27 40.21L0 404.19V142.65Z"/><path style="fill: currentColor" d="m68.58 314.96-32.87-21.68c-4.98-3.11-8.65-8.65-9.9-14.86-1.29-6.43.08-13.12 3.65-17.89 1.9-2.54 3.8-4.44 6.32-6.34l66.8-44.31 44.44 28.95c4.92 3.53 8.65 7.47 11.73 12.4 12.08 18.44 6.8 44.18-11.73 57.46l-44.43 28.95-34.01-22.67ZM0 420.44l102.58-67.94 44.44 28.95c4.92 3.52 8.65 7.46 11.73 12.4 12.09 19.1 6.83 44.86-11.73 57.45L0 547.52V420.44ZM0 127.07V0l147.02 96.21c4.55 3.26 8.51 7.21 11.77 11.75 5.83 9.77 7.8 20.33 5.85 31.39-1.88 10.68-8.12 19.9-17.54 25.96l-44.52 29L0 127.07Z"/></svg>'
|
||||
colorBg: '#FFFFFF'
|
||||
colorText: '#000000'
|
||||
colorHighlight: '#FD9C09'
|
||||
---
|
||||
Etosis is a small software consultancy and development company based in Helsinki, Finland that specialises in solving extremely complex software challenges.
|
||||
|
||||
|
|
@ -23,4 +26,4 @@ So I developed simplistic vector-based animations for each product that make the
|
|||
|
||||
The website was built in [Eleventy](https://www.11ty.dev/), a static site generator. The animations were created as SVGs and then animated with Javascript.
|
||||
|
||||
<a class="button" href="https://etosis.com">Live Site</a>
|
||||
<a class="button button--primary" href="https://etosis.com">Live Site</a>
|
||||
|
|
@ -11,6 +11,9 @@ reference: https://www.linkedin.com/in/ozollmanthomas/
|
|||
referenceName: Oscar Zollman
|
||||
agency: https://forpeople.com
|
||||
agencyName: forpeople
|
||||
colorBg: '#0000FE'
|
||||
colorText: '#FFF7E9'
|
||||
colorHighlight: '#FFCA11'
|
||||
---
|
||||
Formo is using precision fermentation instead of cows to make dairy products and save the world. Creative agency [forpeople](https://forpeople.com) is in charge of branding and brought me on board to develop a brand new website.
|
||||
|
||||
|
|
@ -22,4 +25,4 @@ After consulting with the team, we decided that the comfort of the new visual ed
|
|||
|
||||
With custom-made, React-based content blocks and the Gutenberg editor, creating new pages and articles in the new formo identity framework is now easily achievable through a WYSIWYG interface.
|
||||
|
||||
<a class="button" href="https://formo.bio">Live site</a>
|
||||
<a class="button button--primary text-[#0000FE]" href="https://formo.bio">Live site</a>
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -2,13 +2,16 @@
|
|||
title: JustPeace Labs
|
||||
header_bg_image: jpl_hero_eukxaw
|
||||
images: [ '/work/jpl/jpl_hero_eukxaw.jpg', '/work/jpl/website_01_zsk9oe.png', '/work/jpl/jpllogo_v7s2pl']
|
||||
description: Housestyle, website and design for the peacebuilding tech non-profit organisation.
|
||||
description: Branding & Website
|
||||
order: 11
|
||||
tags: ['branding', 'logo design', 'graphic design', 'illustration']
|
||||
tasks: ['Housestyle', 'Visual Design', 'Product Design', 'Frontend Development']
|
||||
reference: 'https://www.linkedin.com/in/jennifereasterday/'
|
||||
referenceName: 'Jennifer Easterday'
|
||||
svg: '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Layer_1" x="0" y="0" viewBox="0 0 240 63" style="enable-background:new 0 0 240 63" xml:space="preserve"><style>.st0{fill:currentColor}.st1{fill:currentColor}</style><g id="Layer_1-2"><path class="st0" d="M82.4 23.4c.4-2.3.6-4.7.5-7.1V3.1h4.6v13.1c.1 2.5 0 5-.3 7.5-.8 4.1-4.9 6-7.4 6.1l-1.1-2.4c1.9-.6 3.3-2.1 3.7-4zM92 3.1h4.5v12.3c0 5.1 1.6 6.2 4.4 6.2s4.3-1.3 4.3-6.2V3.1h4.5v12.7c0 6.1-3 9.5-8.9 9.5-6.6 0-8.8-3.8-8.8-9.6V3.1zM114 20.3c1.7.9 3.7 1.4 5.7 1.4 2.4 0 3.2-.8 3.2-2.2s-.9-2.2-4.2-3.9c-2.6-1.3-5.4-3.2-5.4-6.8 0-4.3 3.5-5.9 7.7-5.9 2-.1 3.9.4 5.7 1.3l-.8 3.6c-1.4-.9-3.1-1.4-4.7-1.4-2.4 0-3.3.9-3.3 2.2 0 1.6 1.1 2.2 3.8 3.7 3.4 1.8 6 3.4 6 7 0 4-3.1 6.1-7.5 6.1-2.3 0-4.5-.4-6.6-1.3l.4-3.8zM135.3 6.6H129V3.1h17.2v3.5h-6.3V25h-4.6V6.6zM149.4 3.1h1.4c2.4 0 4.4-.2 6.5-.2 5 0 8 2.2 8 7.6 0 5-3.1 8-8.8 8H154V25h-4.6V3.1zm7 11.8c2.2 0 4.3-.9 4.3-4.6 0-2.8-1.5-4.3-4.4-4.2-.8 0-1.6.1-2.4.2v8.4c.8.2 1.6.2 2.5.2zM168.4 3.1h13.4v3.5H173V12h6.8v3.5H173v5.9h9.7V25h-14.3V3.1zM192.8 2.9h4.6l8.2 22.1h-5l-1.5-4.6H191l-1.5 4.6h-4.9l8.2-22.1zm5.3 14.2-2.4-7.5-.6-2.3-.6 2.3-2.4 7.5h6zM216.4 2.9c2 0 4 .3 6 .9l-.7 4c-1.5-.9-3.2-1.3-5-1.3-3.6 0-6.3 2.7-6.3 7.3s2.5 7.9 6.7 7.9c1.8 0 3.5-.5 5.1-1.4v3.8c-1.7.8-3.6 1.2-5.5 1.1-6.8 0-11-4.5-11-11.1 0-7.3 4.7-11.2 10.7-11.2zM225.7 3.1h13.4v3.5h-8.8V12h6.7v3.5h-6.7v5.9h9.7V25h-14.3V3.1z"/><path class="st1" d="M80.4 39h2.5v20H92v2H80.4V39zM98 52.1c2.1-.7 4.2-1 6.4-1v-1.9c0-2.7-1.4-3.1-3.8-3.1-1.7.1-3.4.5-4.8 1.4l-.6-1.6c1.8-1 3.9-1.6 6-1.6 3.3 0 5.6.9 5.6 5v11.9h-1c-.8 0-1.3-.1-1.3-1.2v-.6c-1.4 1.2-3.2 1.8-5.1 1.8-2.9 0-5-1.7-5-4.6 0-2.1 1.3-3.6 3.6-4.5zm2.2 7.3c1.5 0 3-.5 4.2-1.4v-5.3c-1.7 0-3.4.2-5.1.8-1.6.6-2.5 1.5-2.5 3 0 1.7 1 2.9 3.4 2.9zM112 37h2.4v6.8l-.1 2.5c1.3-1.3 3.1-2 5-2 3.6 0 6.5 2.6 6.5 7.8s-3.3 9.1-8.3 9.1c-1.9 0-3.8-.4-5.5-1.2V37zm5.8 22.4c2.9 0 5.5-2.3 5.6-7 0-4.1-1.6-6.3-4.7-6.3-1.6 0-3.1.6-4.2 1.7v10.9c.9.6 2.1.8 3.3.7zM129.4 58.2c1.5.8 3.1 1.2 4.7 1.2 2.1 0 3.6-.8 3.6-2.5s-2-2.5-3.9-3.3c-2.5-1-4.7-2.4-4.7-5.1s2.7-4.1 5.7-4.2c1.5 0 2.9.3 4.2.9l-.4 1.8c-1.1-.6-2.4-.9-3.7-.9-2.4 0-3.6.9-3.6 2.2 0 1.7 1.4 2.5 3.6 3.4s5 2.2 5 5-2.2 4.5-5.7 4.5c-1.8 0-3.6-.4-5.2-1.2l.4-1.8zM7.2 31.7c0-12.2 8.9-22.6 21-24.4L27.1 0C11.6 2.4.1 15.7 0 31.5c0 6.8 2.2 13.5 6.2 19l5.8-4.3C8.9 42 7.2 36.9 7.2 31.7zM17.1 51.4l-4.2 5.7c4.2 3.1 9.1 5.1 14.2 5.9l1-7c-4-.6-7.8-2.2-11-4.6zM36.5 0l-1.1 7.3c13.5 2 22.7 14.5 20.7 28-.6 3.9-2.1 7.7-4.5 10.9l5.7 4.2c4.1-5.5 6.3-12.1 6.2-19 .1-15.7-11.4-29-27-31.4zM35.5 56l1 7c5.2-.8 10-2.8 14.2-5.9l-4.2-5.7c-3.2 2.4-7 4-11 4.6z"/></g></svg>'
|
||||
colorBg: '#013563'
|
||||
colorText: '#FFFFFF'
|
||||
colorHighlight: '#F9A870'
|
||||
---
|
||||
|
||||
JustPeace Labs is a non-profit organization that works with local communities to build peace and prevent violence.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
---
|
||||
title: Letshost.ie
|
||||
description: Design and development for the irish hosting provider
|
||||
description: Design & development
|
||||
images: ['work/letshost/letshost_hero_ibd4sx', 'work/letshost/letshost_sharedhosting_desktop_sriv5t', 'work/letshost/letshost_testimonials_desktop_ijwxmy', 'work/letshost/letshost_wordpress_desktop_qaknlm']
|
||||
tags: ['Graphc Design', 'Web Design', 'Frontend Development']
|
||||
reference: https://www.linkedin.com/in/daraghmacloughlin/
|
||||
referenceName: Daragh Mac Loughlin
|
||||
svg: '<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 115.2 16.4"><path fill="currentColor" d="M54.4.5H58v6.2h5.9V.5h3.6v15.6h-3.6v-6H58v6h-3.6V.5zM12.6 16.1V.5h11.1v3.3h-7.4v2.9H23v3.2h-6.7v2.9h7.8v3.4l-11.5-.1zM51.3 2.3l-1.7 2.4c-1.4-.5-2.6-.9-3.8-1.3-.4-.1-.9-.1-1.3.1s-.8.7-.8 1.1c.1.5.4.9.8 1.2.8.3 1.6.6 2.4.8.8.2 1.5.5 2.3.8 3.2 1.4 3.2 6 .6 7.8-3.2 2.2-8.2.9-10.6-1.8l2.1-2.6c.2.2.4.3.7.5 1.1.6 2.2 1.2 3.4 1.6.5.2 1 .1 1.5-.1.4-.2.7-.6.9-1 .2-.5-.1-1.1-.6-1.3h-.1c-.8-.3-1.5-.5-2.3-.8s-1.7-.5-2.5-.9c-1.4-.6-2.3-1.9-2.4-3.4-.3-1.7.5-3.5 1.9-4.4 3.1-2 7.1-.9 9.3.9.1.2.2.3.2.4zM88.9 13.6l2.2-2.7c.3.2.5.4.8.6 1 .6 2 1.1 3.1 1.5.5.2 1.1.1 1.6-.1s.8-.6.9-1.1c0-.5-.3-1-.7-1.2-.7-.3-1.4-.6-2.1-.7-.9-.3-1.8-.6-2.6-.9-1.6-.6-2.7-2.3-2.5-4-.1-1.7.9-3.3 2.4-4.1 2.7-1.4 7.2-.7 9.1 1.5l-1.7 2.4c-1.2-.5-2.4-.9-3.6-1.3-.5-.1-1-.1-1.5.1s-.8.6-.9 1.1c0 .5.3 1 .8 1.2.8.3 1.6.6 2.4.8.8.2 1.5.5 2.3.8 1.7.7 2.7 2.3 2.6 4.1 0 1.8-1 3.4-2.7 4.1-2.3 1.1-4.9 1-7.1-.3-1-.6-1.9-1.2-2.8-1.8zM38.1.5v3.1h-4.3v12.5h-3.7V3.6h-4.3V.5h12.3zM110.8 16.1h-3.6V3.7h-4.3V.6h12.3v3h-4.4v12.5zM3.7 12.8h6.6v3.3H0V.5h3.7v12.3zM86.2 5.9C85.4 3.7 83.7 2 81.6 1c-.1.1-3.1 1.3-4.7 3.6 2.2-.5 4-.1 5.4.6 1.8 1.1 3.2 2.8 4 4.8.3-1.2.3-2.7-.1-4.1z"/><path fill="currentColor" d="M81 15.8c2.2-.8 3.9-2.5 4.9-4.6-.1-.1-1.3-3.1-3.6-4.7.5 2.2.1 4-.6 5.4-1.1 1.8-2.8 3.2-4.8 4 1.3.3 2.8.3 4.1-.1z"/><path fill="currentColor" d="M71.1 10.7c.8 2.2 2.5 3.9 4.6 4.9.1-.1 3.1-1.3 4.7-3.6-2.2.5-4 .1-5.4-.6-1.8-1.1-3.2-2.8-4-4.8-.3 1.2-.3 2.7.1 4.1z"/><path fill="currentColor" d="M76.3.8c-2.2.8-3.9 2.5-4.9 4.6.1.1 1.3 3.1 3.6 4.7-.5-2.2-.1-4 .6-5.4 1.1-1.8 2.8-3.2 4.8-4-1.3-.3-2.8-.3-4.1.1z"/></svg>'
|
||||
colorBg: '#011355'
|
||||
colorText: '#FFFFFF'
|
||||
colorHighlight: '#96DA1F'
|
||||
---
|
||||
LetsHost.ie is the leading irish webhosting provider. I worked with the marketing team to redesign their website and improve their user journeys.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
---
|
||||
title: peak.capital
|
||||
header_bg_image: peak_hero_ewp1wb
|
||||
images: ['/work/peak/peak-mobile-mockup_wtp3ea', '/work/peak/peak_hero_ewp1wb']
|
||||
images: [
|
||||
'https://res.cloudinary.com/dkvjosg5p/video/upload/v1770654489/work/peak/peak_home_out_x3ljcp.mp4',
|
||||
'/work/peak/peak-mobile-mockup_wtp3ea',
|
||||
'/work/peak/peak_hero_ewp1wb'
|
||||
]
|
||||
order: 12
|
||||
description: A new website for the european investment fund
|
||||
tags: ['Webdesign', 'Frontend Development']
|
||||
svg: '<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 97 97"><path style="fill:currentColor" fill-rule="evenodd" d="M.1 48.5C.1 21.7 21.8 0 48.6 0 75.3.1 97 21.8 97 48.5 97 75.3 75.3 97 48.5 97S.1 75.3.1 48.5zm14.5 3.2H18c5.4 0 8.8-2.6 8.8-7s-3.4-7-8.8-7h-8v21.7h4.6v-7.7zm19.2-9.9h9.9v-4.1H29.2v21.7h14.5v-4.1h-9.9v-4.9h9.3v-4.1h-9.3v-4.5zm28.4 15.9.7 1.7h5l-8.7-21.7h-4.9l-8.7 21.7h5l.6-1.5c0-.1.1-.2.2-.4 1.1-2.2 3.2-3.6 5.4-3.6s4.2 1.3 5.3 3.4c0 .1 0 .3.1.4zm12.1-5.8 3.2-3.3 6 10.7h5.9L81.1 45l7.3-7.4h-5.8l-8.3 8.3v-8.3h-4.6v21.8h4.6v-7.5zM18 41.8h-3.3v5.8H18c2.6 0 4.1-1 4.1-2.9-.1-1.9-1.5-2.9-4.1-2.9zM54.2 50c.8-.2 1.6-.3 2.5-.3.8 0 1.7.1 2.5.3l-2.5-6.3-2.5 6.3z" clip-rule="evenodd"/></svg>'
|
||||
referenceName: Madeline Lawrence
|
||||
reference: https://www.linkedin.com/in/madelinelawren/
|
||||
colorBg: '#000000'
|
||||
colorText: '#FFFFFF'
|
||||
colorHighlight: '#FF00FF'
|
||||
---
|
||||
Peak is an early-stage investment fund backed by entrepreneurs in Europe.
|
||||
|
||||
|
|
@ -15,4 +22,4 @@ In 2021 the creative agency [forpeople](https://forpeople.com) helped Peak with
|
|||
|
||||
Over the past years I have worked with the team at peak to develop the site further.
|
||||
|
||||
<a class="button" href="https://peak.capital">Live site</a>
|
||||
<a class="button button--primary" href="https://peak.capital">Live site</a>
|
||||
|
|
@ -10,6 +10,9 @@ referenceName: Patrick Niall
|
|||
agency: https://forpeople.com
|
||||
agencyName: forpeople
|
||||
svg: '<svg id="uncommonLogo" x="0" y="0" viewBox="0 0 932 110.7" style="enable-background:new 0 0 932 110.7; fill: currentColor;"><path id="n7" class="uncommonLogo-letter" d="M828.9 3.5h30.5v9.6C865.6 4.9 878.2 0 889.3 0c10.2 0 21.6 3.1 28.1 9.1 8.4 7.5 14.7 19.9 14.7 32v66.4h-30.3V48.8c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.5V3.5z"></path><path id="o6" class="uncommonLogo-letter" d="M801.2 17.2c-10.8-10.7-24.1-16-39.6-16s-28.7 5.3-39.5 16C711.4 27.7 706 40.6 706 56c0 15.3 5.4 28.3 16.1 39 10.7 10.5 23.9 15.8 39.5 15.8s28.8-5.3 39.6-16C812 84.3 817.5 71.3 817.5 56c0-15.4-5.4-28.3-16.3-38.8zm-21.7 57.1c-4.9 5-10.8 7.5-17.9 7.5s-13-2.5-17.7-7.5c-4.9-5-7.3-11.1-7.3-18.4 0-7.2 2.4-13.4 7.1-18.4 4.9-5 10.8-7.5 17.9-7.5s13 2.5 17.9 7.5c4.9 5 7.3 11.1 7.3 18.4 0 7.3-2.5 13.4-7.3 18.4z"></path><path id="mm5" class="uncommonLogo-letter" d="M446.9 3.5h30.5v9.6C483.6 4.9 496.2 0 507.3 0c10.2 0 21.6 3.1 28.1 9.1 3.3 2.9 6.3 6.7 8.7 10.8 3.7-4.2 6.3-6.8 6.3-6.8C557.1 6.2 569.1 0 580.2 0c10.2 0 21.6 3.1 28.1 9.1 3.3 3 6.3 6.7 8.7 10.9 3.7-4.2 6.4-6.9 6.4-6.9C630.1 6.2 642.1 0 653.2 0c10.2 0 21.6 3.1 28.1 9.1 8.4 7.5 14.7 19.9 14.7 32v66.4h-30.3V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.7V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.6V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.5V3.5z"></path><path id="o4" class="uncommonLogo-letter" d="M420 17.2c-10.8-10.7-24.1-16-39.6-16s-28.7 5.3-39.5 16c-10.7 10.5-16.1 23.5-16.1 38.8 0 15.3 5.4 28.3 16.1 39 10.7 10.5 23.9 15.8 39.5 15.8s28.8-5.3 39.6-16c10.8-10.5 16.3-23.5 16.3-38.8 0-15.4-5.4-28.3-16.3-38.8zm-21.7 57.1c-4.9 5-10.8 7.5-17.9 7.5s-13-2.5-17.7-7.5c-4.9-5-7.3-11.1-7.3-18.4 0-7.2 2.4-13.4 7.1-18.4 4.9-5 10.8-7.5 17.9-7.5s13 2.5 17.9 7.5c4.9 5 7.3 11.1 7.3 18.4 0 7.3-2.4 13.4-7.3 18.4z"></path><path id="c3" class="uncommonLogo-letter" d="M247.1 16.8c10.4-10.4 23.4-15.6 39.1-15.6 13.6 0 25.5 4.5 35.6 13.4l-11.3 26.5c-6.8-7.3-14.6-11-23.2-11-7.2 0-13.2 2.5-18.1 7.5-4.9 4.9-7.3 11.2-7.3 18.9 0 7.6 2.4 13.7 7.1 18.4 4.9 4.7 10.8 7 17.9 7 8.9 0 16.7-3.7 23.6-11l11.3 26.5c-10.1 8.9-22 13.4-35.6 13.4-15.7 0-28.8-5.2-39.3-15.6-10.4-10.4-15.5-23.5-15.5-39.1s5.2-28.9 15.7-39.3z"></path><path id="n2" class="uncommonLogo-letter" d="M117.8 3.5h30.5v9.6C154.5 4.9 167.1 0 178.2 0c10.2 0 21.6 3.1 28.1 9.1 8.4 7.5 14.7 19.9 14.7 32v66.4h-30.3V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.5V3.5z"></path><path id="u1" class="uncommonLogo-letter" d="M103.1 107.2H72.6v-9.6c-6.2 8.2-18.8 13.1-29.9 13.1-10.2 0-21.6-3.1-28.1-9.1C6.3 94.1 0 81.7 0 69.6V3.2h30.3V62c0 5 1.8 12.9 4.6 15.7 2.7 2.8 6.7 6.8 16.2 6.8s14.8-4.9 17.5-8.9c2.3-3.3 4.1-7.4 4.1-13.6V3.2h30.5v104z"></path></svg>'
|
||||
colorBg: '#4D2C7C'
|
||||
colorText: '#F0EBE6'
|
||||
colorHighlight: '#B3B6FE'
|
||||
---
|
||||
Uncommon's mission is to sell rashers and rashers of cultivated pork at price parity. For happy pigs and piggy banks.
|
||||
|
||||
|
|
|
|||
27
src/routes/work/md/zya.md
Normal file
27
src/routes/work/md/zya.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
title: zya.co
|
||||
images: [
|
||||
'https://res.cloudinary.com/dkvjosg5p/video/upload/v1770392733/work/zya/zya_home_2pxpms_opt_pjyitt.mp4',
|
||||
'https://res.cloudinary.com/dkvjosg5p/image/upload/v1770392695/work/zya/zya_approach_hzpelu.png',
|
||||
'https://res.cloudinary.com/dkvjosg5p/video/upload/v1770392738/work/zya/zya_convero_2pxpms_opt_qqq5jt.mp4',
|
||||
'https://res.cloudinary.com/dkvjosg5p/image/upload/v1770392695/work/zya/zya_mission_ygzf3t.png'
|
||||
]
|
||||
order: 12
|
||||
tags: ['Tech consultancy', 'Frontend development',]
|
||||
description: An enzyme that converts sugar into fiber
|
||||
reference: https://www.linkedin.com/in/josh-sauer-phd/
|
||||
referenceName: Joshua Sauer
|
||||
agency: https://forpeople.com
|
||||
agencyName: forpeople
|
||||
svg: '<svg width="63" height="27" viewBox="0 0 63 27" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M41.3897 0.751722H36.7294L30.8702 14.1349C30.3853 15.2437 29.1064 15.26 28.5986 14.1615L23.6313 4.04019C22.3656 1.85951 20.8935 0.762177 17.7699 0.73737H0.0858154V4.20059H10.8866C11.9013 4.20059 12.3754 5.45712 11.6136 6.1274L0.0858154 16.2698V20.0347H18.3518V16.4572H8.49249C7.47837 16.4572 7.00397 15.2019 7.76461 14.5312L17.5524 5.90035C18.4396 5.10514 19.5278 5.18885 20.1305 6.33562L26.3524 18.2129C27.7389 20.8917 25.5924 22.6567 22.8737 22.6567H18.3767V26.3184H23.5596C26.4774 26.3184 27.3679 25.8441 28.5796 25.0435C29.7913 24.2429 31.0462 22.4471 32.2011 20.1197L41.3829 0.751722H41.3897Z" fill="currentColor"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M54.7502 4.08113C53.7068 1.86811 51.4799 0.456055 49.0332 0.456055C46.5875 0.456055 44.3612 1.86706 43.3173 4.07883L35.7943 20.018H40.5601C44.4933 12.2573 53.9182 12.5632 57.5545 20.018H62.2643L54.7502 4.08113ZM51.5265 6.28748C51.0983 5.36275 50.1463 4.65315 49.0531 4.65315C47.8995 4.65315 47.0475 5.36324 46.6167 6.28748L44.293 11.2673C44.2341 11.3935 44.3564 11.5299 44.4891 11.4877C47.2687 10.6047 50.9197 10.5062 53.6226 11.4649C53.757 11.5126 53.8871 11.3739 53.8271 11.2445L51.5265 6.28748Z" fill="currentColor"></path></svg>'
|
||||
colorBg: '#083247'
|
||||
colorText: '#FFFBF3'
|
||||
colorHighlight: '#E681FF'
|
||||
---
|
||||
Zya’s mission is simple: to make better nutrition accessible without sacrificing the taste and enjoyment of everyday food.
|
||||
|
||||
In another collaboration with the ever-inspiring creative agency [forpeople](https://forpeople.com), we created a website with scroll-based storytelling animations that playfully brings the complex information behind the science to life.
|
||||
|
||||
In a second phase we added more storytelling features and a blog.
|
||||
|
||||
<a href="https://zya.co" class="button" target="_blank">Check it out live</a>
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
:global(html){
|
||||
overflow: hidden;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
.works-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
perspective: 700px;
|
||||
transform-origin: 0 0;
|
||||
will-change: transform;
|
||||
}
|
||||
.headline {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
letter-spacing: -0.05em;
|
||||
z-index: 10;
|
||||
transform: translateZ(500px);
|
||||
margin-left: 40.5vw;
|
||||
margin-top: 37.25vh;
|
||||
font-size: 14vw;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
margin-left: 41.66vw;
|
||||
margin-top: 40.5vh;
|
||||
font-size: 7vw;
|
||||
transform: translateZ(600px);
|
||||
}
|
||||
}
|
||||
.works {
|
||||
margin: 0 auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 600vw;
|
||||
height: 600vw;
|
||||
transform: scale(.333);
|
||||
transform-origin: 0 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 100vw);
|
||||
grid-auto-rows: 100vh;
|
||||
gap: 6px;
|
||||
will-change: transform;
|
||||
}
|
||||
.work {
|
||||
background-color: var(--color-highlight);
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateZ(700px);
|
||||
will-change: transform;
|
||||
}
|
||||
:global(.work-logo) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: var(--color-bg);
|
||||
padding: 3em;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
will-change: transform;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
:global(.work-logo svg) {
|
||||
object-fit: fill;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.work-info {
|
||||
display: none;
|
||||
}
|
||||
.work-info .tags {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
gap: .25em;
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [ sveltekit() ]
|
||||
plugins: [tailwindcss(), sveltekit()]
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue