v1 of an overhaul for my portfolio
This commit is contained in:
+23
@@ -0,0 +1,23 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Images
|
||||
*.png
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.gif
|
||||
*.svg
|
||||
*.webp
|
||||
*.bmp
|
||||
*.ico
|
||||
|
||||
# Markdown
|
||||
*.md
|
||||
|
||||
# Text files
|
||||
*.txt
|
||||
*.text
|
||||
|
||||
# Exceptions
|
||||
!p_img.png
|
||||
!myprojects.png
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
@import "https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&family=Syne+Tactile&display=swap";:root{font-optical-sizing:auto;font-variation-settings:"wdth" 100, "YTLC" 500;color:#f4f4f4;font-synthesis:none;background:#090909;font-family:Nunito Sans,sans-serif}*{box-sizing:border-box}html{scroll-behavior:smooth}html,body,#root{min-height:100%;margin:0}body{background:#090909}a{color:inherit;text-decoration:none}img,video{max-width:100%}.page{background:#090909;min-height:100vh}.header,main,footer{width:min(1600px,100% - 48px);margin-inline:auto}.header{border-bottom:1px solid #292929;justify-content:space-between;align-items:center;height:88px;display:flex}.brand,nav,.eyebrow,.section-heading,.stack,.project-number,.footer-meta{text-transform:uppercase;letter-spacing:.14em;font-family:Nunito Sans,sans-serif}.brand{font-size:13px;font-weight:700}nav{color:#999;gap:30px;font-size:10px;display:flex}nav a:hover{color:#fff}.hero{flex-direction:column;justify-content:center;min-height:calc(100vh - 88px);padding:90px 0;display:flex}.eyebrow{color:#aaa;margin:0 0 24px;font-size:10px}h1,footer h2{font-family:Syne Tactile,system-ui;font-style:normal;font-weight:400}h1{letter-spacing:-.07em;max-width:1060px;margin:0;font-size:clamp(3.5rem,8.2vw,7.4rem);font-weight:400;line-height:.96}h1 span{color:#777}.hero-bottom{justify-content:space-between;align-items:flex-end;gap:40px;margin-top:54px;display:flex}.hero-cta{flex-direction:column;align-items:flex-end;gap:18px;display:flex;transform:translateY(-300px)}.hero-portrait{width:300px;height:auto}.intro{color:#aaa;max-width:510px;margin:0;font-size:17px;line-height:1.7}.button{text-transform:uppercase;letter-spacing:.1em;border:1px solid #444;border-radius:4px;justify-content:space-between;align-items:center;gap:34px;min-width:250px;padding:15px 18px;font:10px Nunito Sans,sans-serif;transition:background .2s,color .2s;display:inline-flex}.button:hover{color:#111;background:#fff}.split-section{border-top:1px solid #292929;height:300vh;position:relative}.split-sticky{perspective:1200px;justify-content:center;align-items:center;height:100vh;display:flex;position:sticky;top:0;overflow:hidden}.project-row{width:min(900px,100% - 32px);height:400px;transform-style:preserve-3d;margin:auto;padding-inline:8px;display:flex;position:absolute;inset:0}.project-row-primary{z-index:2}.project-row-secondary{z-index:1}.split-card{min-width:0;height:100%;transform-style:preserve-3d;flex:1;position:relative}.split-front,.split-back{backface-visibility:hidden;position:absolute;inset:0;overflow:hidden}.split-front{z-index:2}.split-image{background:url(/projects-cover.png) 50%/100% 100% no-repeat;width:300%;position:absolute;inset-block:0}.split-back{z-index:1;border:1px solid #ffffff26;flex-direction:column;justify-content:space-between;padding:30px;display:flex;transform:rotateY(180deg)}.split-media{object-fit:cover;border-radius:8px;width:100%;height:120px}.split-back h2{letter-spacing:-.05em;margin:0 0 12px;font-size:clamp(1.5rem,3vw,2.5rem);line-height:1}.split-back h2 a:hover{opacity:.65}.split-back p{opacity:.72;margin:0;font-size:13px;line-height:1.55}.split-link{text-transform:uppercase;letter-spacing:.1em;margin-top:20px;font:9px Nunito Sans,sans-serif;display:inline-block}.more-project-card{color:#111;border-radius:16px;flex-direction:column;flex:1;justify-content:space-between;min-width:0;height:400px;padding:30px;display:flex;box-shadow:0 25px 50px -24px #0000004d}.more-project-media{object-fit:contain;background:#ffffff73;border-radius:8px;width:100%;height:120px;padding:32px}.more-project-card h2{letter-spacing:-.05em;margin:0 0 12px;font-size:clamp(1.5rem,3vw,2.5rem);line-height:1}.more-project-card h2 a:hover{opacity:.6}.more-project-card p{opacity:.72;max-width:36ch;margin:0;font-size:13px;line-height:1.55}footer{border-top:1px solid #292929;grid-template-columns:1fr auto;align-content:center;align-items:end;gap:40px;min-height:520px;padding:100px 0 34px;display:grid}footer h2{letter-spacing:-.065em;max-width:760px;margin:0;font-size:clamp(3rem,7vw,6.5rem);font-weight:400;line-height:.95}.button.light{color:#111;background:#fff}.button.light:hover{background:#ddd}.footer-meta{color:#888;grid-column:1/-1;justify-content:space-between;align-self:end;padding-top:80px;font-size:9px;display:flex}@media (width<=760px){.header,main,footer{width:calc(100% - 32px)}.hero{min-height:auto;padding:100px 0 90px}h1{font-size:clamp(3.1rem,15vw,5.5rem)}.hero-bottom{flex-direction:column;align-items:flex-start;margin-top:40px}.hero-cta{align-items:flex-start;transform:none}.hero-portrait{width:160px;height:160px}.project-row{width:100%;height:340px;padding-inline:0}.split-back{padding:18px}.split-media{height:96px}.split-back p{font-size:11px}.more-project-card{height:340px;padding:18px}.more-project-media{height:96px;padding:24px}footer{grid-template-columns:1fr;align-items:start;min-height:480px}.footer-meta{grid-column:1}}
|
||||
Vendored
+9
File diff suppressed because one or more lines are too long
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Chait | Developer</title>
|
||||
<script type="module" crossorigin src="/assets/index-DBBwLqLM.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CngdJY0o.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Vendored
BIN
Binary file not shown.
+12
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Chait | Developer</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.9 MiB |
Generated
+5407
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
{"scripts":{"dev":"vite","build":"vite build","preview":"vite preview"},"dependencies":{"@tailwindcss/vite":"^4.3.3","@vitejs/plugin-react":"latest","class-variance-authority":"^0.7.1","cn":"^0.3.0","framer-motion":"^13.4.0","lucide-react":"^1.47.0","react":"latest","react-dom":"latest","shadcn":"^4.21.0","tailwindcss":"^4.3.3","tw-animate-css":"^1.4.0","vite":"latest"}}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
@@ -0,0 +1,255 @@
|
||||
import {
|
||||
motion,
|
||||
useMotionTemplate,
|
||||
useScroll,
|
||||
useTransform,
|
||||
} from "framer-motion";
|
||||
import { useRef } from "react";
|
||||
|
||||
const projects = [
|
||||
{
|
||||
title: "Android Marketplace",
|
||||
description:
|
||||
"A marketplace app with authentication, location search, and category filtering.",
|
||||
link: "https://streamable.com/df1mxt",
|
||||
media: "/projects/android.mp4",
|
||||
background: "#e8e8e8",
|
||||
color: "#111",
|
||||
},
|
||||
{
|
||||
title: "ForOranges",
|
||||
description:
|
||||
"A full stack commerce experience with authentication and database management.",
|
||||
link: "https://e-com-front-chi.vercel.app/",
|
||||
media: "/projects/fororanges.gif",
|
||||
background: "#d8ff3e",
|
||||
color: "#111",
|
||||
},
|
||||
{
|
||||
title: "PC Building Guide",
|
||||
description:
|
||||
"A resource hub that helps first time builders find guides for every component.",
|
||||
link: "https://pcbuildchait.netlify.app/",
|
||||
media: "/projects/pcb.gif",
|
||||
background: "#181818",
|
||||
color: "#fff",
|
||||
},
|
||||
];
|
||||
|
||||
const moreProjects = [
|
||||
{
|
||||
title: "Self-Hosted Supabase",
|
||||
description: "A privately hosted Supabase deployment for backend services.",
|
||||
link: "https://supabase.omgchait.com",
|
||||
media: "/projects/supabase.svg",
|
||||
color: "#f0ede6",
|
||||
},
|
||||
{
|
||||
title: "Self-Hosted n8n",
|
||||
description: "A self-hosted automation platform for connected workflows.",
|
||||
link: "https://n8n.omgchait.com",
|
||||
media: "/projects/n8n.svg",
|
||||
color: "#cadcff",
|
||||
},
|
||||
{
|
||||
title: "Self-Hosted OpenCloud",
|
||||
description: "A private cloud platform for secure file storage and access.",
|
||||
link: "https://cloud.omgchait.com",
|
||||
media: "/projects/opencloud.svg",
|
||||
color: "#ffd4c4",
|
||||
},
|
||||
];
|
||||
|
||||
export function ScrollSplitCard() {
|
||||
const sectionRef = useRef(null);
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: sectionRef,
|
||||
offset: ["start start", "end end"],
|
||||
});
|
||||
|
||||
const leftX = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.25, 0.58, 1],
|
||||
[0, -48, -24, -24],
|
||||
);
|
||||
const rightX = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.25, 0.58, 1],
|
||||
[0, 48, 24, 24],
|
||||
);
|
||||
const rowScale = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.25, 0.58, 0.74, 1],
|
||||
[1, 0.9, 0.9, 0.72, 0.72],
|
||||
);
|
||||
const rotateY = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.32, 0.58, 1],
|
||||
[0, 0, 180, 180],
|
||||
);
|
||||
const rotateZLeft = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.32, 0.58, 1],
|
||||
[0, 0, 6, 6],
|
||||
);
|
||||
const rotateZRight = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.32, 0.58, 1],
|
||||
[0, 0, -6, -6],
|
||||
);
|
||||
const firstRowY = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.58, 0.74, 1],
|
||||
[0, 0, -190, -190],
|
||||
);
|
||||
const secondRowY = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.58, 0.74, 1],
|
||||
[520, 520, 190, 190],
|
||||
);
|
||||
const secondRowOpacity = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.58, 0.66, 1],
|
||||
[0, 0, 1, 1],
|
||||
);
|
||||
|
||||
const leftRadius = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.15, 1],
|
||||
["16px 0px 0px 16px", "16px 16px 16px 16px", "16px 16px 16px 16px"],
|
||||
);
|
||||
const middleRadius = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.15, 1],
|
||||
["0px 0px 0px 0px", "16px 16px 16px 16px", "16px 16px 16px 16px"],
|
||||
);
|
||||
const rightRadius = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.15, 1],
|
||||
["0px 16px 16px 0px", "16px 16px 16px 16px", "16px 16px 16px 16px"],
|
||||
);
|
||||
const borderOpacity = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.15, 1],
|
||||
[0, 0.2, 0.2],
|
||||
);
|
||||
const shadowOpacity = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 0.15, 1],
|
||||
[0, 0.4, 0.4],
|
||||
);
|
||||
const shadow = useMotionTemplate`inset 0 1px 1px rgba(255,255,255,${borderOpacity}), inset 0 -24px 48px rgba(0,0,0,${shadowOpacity}), 0 25px 50px -12px rgba(0,0,0,${shadowOpacity})`;
|
||||
const radii = [leftRadius, middleRadius, rightRadius];
|
||||
|
||||
return (
|
||||
<section className="split-section" id="work" ref={sectionRef}>
|
||||
<div className="split-sticky">
|
||||
<motion.div
|
||||
className="project-row project-row-primary"
|
||||
style={{ scale: rowScale, y: firstRowY }}
|
||||
>
|
||||
{projects.map((project, index) => (
|
||||
<motion.article
|
||||
className="split-card"
|
||||
key={project.title}
|
||||
style={{
|
||||
x: index === 0 ? leftX : index === 2 ? rightX : 0,
|
||||
rotateY,
|
||||
rotateZ:
|
||||
index === 0 ? rotateZLeft : index === 2 ? rotateZRight : 0,
|
||||
zIndex: index,
|
||||
}}
|
||||
>
|
||||
<motion.div
|
||||
className="split-front"
|
||||
style={{ borderRadius: radii[index], boxShadow: shadow }}
|
||||
>
|
||||
<div
|
||||
className="split-image"
|
||||
style={{ left: `${index * -100}%` }}
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="split-back"
|
||||
style={{
|
||||
backgroundColor: project.background,
|
||||
color: project.color,
|
||||
borderRadius: radii[index],
|
||||
boxShadow: shadow,
|
||||
}}
|
||||
>
|
||||
{project.media.endsWith(".mp4") ? (
|
||||
<video
|
||||
className="split-media"
|
||||
src={project.media}
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
/>
|
||||
) : (
|
||||
<img className="split-media" src={project.media} alt="" />
|
||||
)}
|
||||
<div>
|
||||
<h2>
|
||||
<a href={project.link} target="_blank" rel="noreferrer">
|
||||
{project.title}
|
||||
</a>
|
||||
</h2>
|
||||
<p>{project.description}</p>
|
||||
<a
|
||||
className="split-link"
|
||||
href={project.link}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
View project ↗
|
||||
</a>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.article>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="project-row project-row-secondary"
|
||||
aria-label="More projects"
|
||||
style={{ opacity: secondRowOpacity, scale: rowScale, y: secondRowY }}
|
||||
>
|
||||
{moreProjects.map((project, index) => (
|
||||
<motion.article
|
||||
className="more-project-card"
|
||||
key={project.title}
|
||||
style={{
|
||||
backgroundColor: project.color,
|
||||
x: index === 0 ? leftX : index === 2 ? rightX : 0,
|
||||
rotateZ:
|
||||
index === 0 ? rotateZRight : index === 2 ? rotateZLeft : 0,
|
||||
zIndex: index,
|
||||
}}
|
||||
>
|
||||
<img className="more-project-media" src={project.media} alt="" />
|
||||
<div>
|
||||
<h2>
|
||||
<a href={project.link} target="_blank" rel="noreferrer">
|
||||
{project.title}
|
||||
</a>
|
||||
</h2>
|
||||
<p>{project.description}</p>
|
||||
<a
|
||||
className="split-link"
|
||||
href={project.link}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
View project ↗
|
||||
</a>
|
||||
</div>
|
||||
</motion.article>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./styles.css";
|
||||
import { ScrollSplitCard } from "./ScrollSplitCard";
|
||||
|
||||
function Arrow() {
|
||||
return <span aria-hidden="true">↗</span>;
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="page">
|
||||
<header className="header">
|
||||
<a className="brand" href="#top">
|
||||
CHAIT
|
||||
</a>
|
||||
<nav aria-label="Main navigation">
|
||||
<a href="#work">Work</a>
|
||||
<a href="#contact">Contact</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section className="hero" id="top">
|
||||
<h1>
|
||||
Thoughtful software.
|
||||
<br />
|
||||
<span>Built to be useful.</span>
|
||||
</h1>
|
||||
<div className="hero-bottom">
|
||||
<p className="intro">
|
||||
I'm Chait, a developer focused on clear interfaces, practical
|
||||
products, and ideas worth shipping.
|
||||
</p>
|
||||
<div className="hero-cta">
|
||||
<img className="hero-portrait" src="/p_img.png" alt="Chait" />
|
||||
<a className="button" href="#work">
|
||||
See my work <span>↓</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ScrollSplitCard />
|
||||
</main>
|
||||
|
||||
<footer id="contact">
|
||||
<div>
|
||||
<p className="eyebrow">Have something in mind?</p>
|
||||
<h2>Let's make it real.</h2>
|
||||
</div>
|
||||
<a className="button light" href="mailto:hello@chait.dev">
|
||||
Get in touch <Arrow />
|
||||
</a>
|
||||
<div className="footer-meta">
|
||||
<span>CHAIT / DEVELOPER</span>
|
||||
<span>© 2025</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
);
|
||||
+373
@@ -0,0 +1,373 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&family=Syne+Tactile&display=swap");
|
||||
|
||||
:root {
|
||||
font-family: "Nunito Sans", sans-serif;
|
||||
font-optical-sizing: auto;
|
||||
font-variation-settings:
|
||||
"wdth" 100,
|
||||
"YTLC" 500;
|
||||
color: #f4f4f4;
|
||||
background: #090909;
|
||||
font-synthesis: none;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
background: #090909;
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
img,
|
||||
video {
|
||||
max-width: 100%;
|
||||
}
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background: #090909;
|
||||
}
|
||||
.header,
|
||||
main,
|
||||
footer {
|
||||
width: min(1600px, calc(100% - 48px));
|
||||
margin-inline: auto;
|
||||
}
|
||||
.header {
|
||||
height: 88px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #292929;
|
||||
}
|
||||
.brand,
|
||||
nav,
|
||||
.eyebrow,
|
||||
.section-heading,
|
||||
.stack,
|
||||
.project-number,
|
||||
.footer-meta {
|
||||
font-family: "Nunito Sans", sans-serif;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.14em;
|
||||
}
|
||||
.brand {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
}
|
||||
nav {
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
color: #999;
|
||||
font-size: 10px;
|
||||
}
|
||||
nav a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.hero {
|
||||
min-height: calc(100vh - 88px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 90px 0;
|
||||
}
|
||||
.eyebrow {
|
||||
margin: 0 0 24px;
|
||||
color: #aaa;
|
||||
font-size: 10px;
|
||||
}
|
||||
h1,
|
||||
footer h2 {
|
||||
font-family: "Syne Tactile", system-ui;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
h1 {
|
||||
max-width: 1060px;
|
||||
margin: 0;
|
||||
font-size: clamp(3.5rem, 8.2vw, 7.4rem);
|
||||
font-weight: 400;
|
||||
line-height: 0.96;
|
||||
letter-spacing: -0.07em;
|
||||
}
|
||||
h1 span {
|
||||
color: #777;
|
||||
}
|
||||
.hero-bottom {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
gap: 40px;
|
||||
margin-top: 54px;
|
||||
}
|
||||
.hero-cta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 18px;
|
||||
transform: translateY(-300px);
|
||||
}
|
||||
.hero-portrait {
|
||||
width: 300px;
|
||||
height: auto;
|
||||
}
|
||||
.intro {
|
||||
max-width: 510px;
|
||||
margin: 0;
|
||||
color: #aaa;
|
||||
font-size: 17px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
.button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 34px;
|
||||
min-width: 250px;
|
||||
padding: 15px 18px;
|
||||
border: 1px solid #444;
|
||||
border-radius: 4px;
|
||||
font:
|
||||
10px "Nunito Sans",
|
||||
sans-serif;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
transition:
|
||||
background 0.2s,
|
||||
color 0.2s;
|
||||
}
|
||||
.button:hover {
|
||||
color: #111;
|
||||
background: #fff;
|
||||
}
|
||||
.split-section {
|
||||
position: relative;
|
||||
height: 300vh;
|
||||
border-top: 1px solid #292929;
|
||||
}
|
||||
.split-sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
perspective: 1200px;
|
||||
}
|
||||
.project-row {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: min(900px, calc(100% - 32px));
|
||||
height: 400px;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
padding-inline: 8px;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
.project-row-primary {
|
||||
z-index: 2;
|
||||
}
|
||||
.project-row-secondary {
|
||||
z-index: 1;
|
||||
}
|
||||
.split-card {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
.split-front,
|
||||
.split-back {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
.split-front {
|
||||
z-index: 2;
|
||||
}
|
||||
.split-image {
|
||||
position: absolute;
|
||||
inset-block: 0;
|
||||
width: 300%;
|
||||
background: url("/projects-cover.png") center / 100% 100% no-repeat;
|
||||
}
|
||||
.split-back {
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 30px;
|
||||
transform: rotateY(180deg);
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
.split-media {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
border-radius: 8px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.split-back h2 {
|
||||
margin: 0 0 12px;
|
||||
font-size: clamp(1.5rem, 3vw, 2.5rem);
|
||||
line-height: 1;
|
||||
letter-spacing: -0.05em;
|
||||
}
|
||||
.split-back h2 a:hover {
|
||||
opacity: 0.65;
|
||||
}
|
||||
.split-back p {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.55;
|
||||
opacity: 0.72;
|
||||
}
|
||||
.split-link {
|
||||
display: inline-block;
|
||||
margin-top: 20px;
|
||||
font:
|
||||
9px "Nunito Sans",
|
||||
sans-serif;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
.more-project-card {
|
||||
flex: 1;
|
||||
color: #111;
|
||||
min-width: 0;
|
||||
height: 400px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 30px;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 25px 50px -24px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.more-project-media {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
padding: 32px;
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 0.45);
|
||||
object-fit: contain;
|
||||
}
|
||||
.more-project-card h2 {
|
||||
margin: 0 0 12px;
|
||||
font-size: clamp(1.5rem, 3vw, 2.5rem);
|
||||
line-height: 1;
|
||||
letter-spacing: -0.05em;
|
||||
}
|
||||
.more-project-card h2 a:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.more-project-card p {
|
||||
max-width: 36ch;
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.55;
|
||||
opacity: 0.72;
|
||||
}
|
||||
footer {
|
||||
min-height: 520px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
align-content: center;
|
||||
align-items: end;
|
||||
gap: 40px;
|
||||
padding: 100px 0 34px;
|
||||
border-top: 1px solid #292929;
|
||||
}
|
||||
footer h2 {
|
||||
max-width: 760px;
|
||||
margin: 0;
|
||||
font-size: clamp(3rem, 7vw, 6.5rem);
|
||||
font-weight: 400;
|
||||
line-height: 0.95;
|
||||
letter-spacing: -0.065em;
|
||||
}
|
||||
.button.light {
|
||||
color: #111;
|
||||
background: #fff;
|
||||
}
|
||||
.button.light:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
.footer-meta {
|
||||
grid-column: 1 / -1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-self: end;
|
||||
padding-top: 80px;
|
||||
color: #888;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.header,
|
||||
main,
|
||||
footer {
|
||||
width: calc(100% - 32px);
|
||||
}
|
||||
.hero {
|
||||
min-height: auto;
|
||||
padding: 100px 0 90px;
|
||||
}
|
||||
h1 {
|
||||
font-size: clamp(3.1rem, 15vw, 5.5rem);
|
||||
}
|
||||
.hero-bottom {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
margin-top: 40px;
|
||||
}
|
||||
.hero-cta {
|
||||
align-items: flex-start;
|
||||
transform: none;
|
||||
}
|
||||
.hero-portrait {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
}
|
||||
.project-row {
|
||||
width: 100%;
|
||||
height: 340px;
|
||||
padding-inline: 0;
|
||||
}
|
||||
.split-back {
|
||||
padding: 18px;
|
||||
}
|
||||
.split-media {
|
||||
height: 96px;
|
||||
}
|
||||
.split-back p {
|
||||
font-size: 11px;
|
||||
}
|
||||
.more-project-card {
|
||||
height: 340px;
|
||||
padding: 18px;
|
||||
}
|
||||
.more-project-media {
|
||||
height: 96px;
|
||||
padding: 24px;
|
||||
}
|
||||
footer {
|
||||
min-height: 480px;
|
||||
grid-template-columns: 1fr;
|
||||
align-items: start;
|
||||
}
|
||||
.footer-meta {
|
||||
grid-column: 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user