New design: studio backdrop with a perspective floor and X/Z axis lines, an orientation gizmo that orbits on scroll, Bricolage Grotesque and Instrument Sans (bundled, no build-time network). Projects are laid out as plates by a row planner that keeps every row full for any count; a demo image from the repo root is shown when present, otherwise a generated voxel sculpture. Text and projects still come live from Gitea. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XtcZtnG4GQA1d6mW5PNrS9
192 lines
4.0 KiB
CSS
192 lines
4.0 KiB
CSS
.hero {
|
|
--sway: 0deg;
|
|
position: relative;
|
|
isolation: isolate;
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: min(100svh, 1000px);
|
|
overflow: clip;
|
|
background: linear-gradient(180deg, #f5f7fa 0%, #e6e9ee 100%);
|
|
}
|
|
|
|
/* The floor is a stage of its own below the text, so the grid never runs through the copy at any window height. */
|
|
.stage {
|
|
position: relative;
|
|
flex: 1;
|
|
min-height: 260px;
|
|
overflow: hidden;
|
|
background: linear-gradient(180deg, #d8dde4 0%, var(--studio-deep) 100%);
|
|
border-top: 1px solid rgba(21, 24, 29, 0.2);
|
|
}
|
|
|
|
.stage::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: auto 0 0 0;
|
|
height: 45%;
|
|
background: linear-gradient(180deg, transparent, var(--paper));
|
|
}
|
|
|
|
.floor {
|
|
position: absolute;
|
|
inset: 0;
|
|
perspective: 620px;
|
|
perspective-origin: 50% 0;
|
|
animation: open 1.7s cubic-bezier(0.2, 0.7, 0.2, 1) 0.1s both;
|
|
}
|
|
|
|
.plane {
|
|
position: absolute;
|
|
left: -70%;
|
|
right: -70%;
|
|
top: 0;
|
|
height: 300%;
|
|
transform-origin: 50% 0;
|
|
transform: rotateX(76deg) rotateZ(var(--sway));
|
|
background-image:
|
|
linear-gradient(to right, rgba(21, 24, 29, 0.2) 1px, transparent 1px),
|
|
linear-gradient(to bottom, rgba(21, 24, 29, 0.2) 1px, transparent 1px);
|
|
background-size: 80px 80px;
|
|
background-position: center top;
|
|
-webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 18%, #000 100%);
|
|
mask-image: linear-gradient(to bottom, transparent 0%, #000 18%, #000 100%);
|
|
}
|
|
|
|
/* The red X axis crosses the floor; the blue Z axis runs into the distance, like the axes of a 3D viewport. */
|
|
.plane::before,
|
|
.plane::after {
|
|
content: '';
|
|
position: absolute;
|
|
}
|
|
|
|
.plane::before {
|
|
left: 0;
|
|
right: 0;
|
|
top: 240px;
|
|
height: 3px;
|
|
background: var(--x);
|
|
}
|
|
|
|
.plane::after {
|
|
top: 0;
|
|
bottom: 0;
|
|
left: calc(50% - 1.5px);
|
|
width: 3px;
|
|
background: var(--z);
|
|
}
|
|
|
|
.content {
|
|
position: relative;
|
|
width: var(--shell);
|
|
margin: 0 auto;
|
|
padding: 136px 0 72px;
|
|
}
|
|
|
|
.status {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
max-width: 100%;
|
|
padding: 8px 16px 8px 13px;
|
|
border-radius: 999px;
|
|
background: rgba(255, 255, 255, 0.72);
|
|
box-shadow: inset 0 0 0 1px var(--line);
|
|
font-size: 15px;
|
|
font-weight: 500;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
.dot {
|
|
flex: none;
|
|
width: 9px;
|
|
height: 9px;
|
|
border-radius: 50%;
|
|
background: var(--y);
|
|
box-shadow: 0 0 0 4px rgba(90, 163, 0, 0.2);
|
|
}
|
|
|
|
.name {
|
|
margin: 30px 0 0 -0.045em;
|
|
font: 800 clamp(56px, 12.6vw, 204px) / 0.88 var(--font-head);
|
|
letter-spacing: -0.048em;
|
|
}
|
|
|
|
.role {
|
|
margin-top: 22px;
|
|
font: 500 clamp(22px, 2.7vw, 38px) / 1.15 var(--font-head);
|
|
letter-spacing: -0.022em;
|
|
}
|
|
|
|
.bio {
|
|
max-width: 58ch;
|
|
margin-top: 44px;
|
|
font-size: 19px;
|
|
line-height: 1.62;
|
|
color: rgba(21, 24, 29, 0.88);
|
|
}
|
|
|
|
.actions {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
margin-top: 32px;
|
|
}
|
|
|
|
.button {
|
|
padding: 14px 24px;
|
|
border-radius: var(--radius-control);
|
|
font: 600 16px/1.2 var(--font-body);
|
|
text-decoration: none;
|
|
transition: background-color 0.2s, color 0.2s, box-shadow 0.2s;
|
|
}
|
|
|
|
.primary {
|
|
background: var(--ink);
|
|
color: var(--paper);
|
|
}
|
|
|
|
.primary:hover {
|
|
background: var(--z);
|
|
}
|
|
|
|
.secondary {
|
|
box-shadow: inset 0 0 0 1.5px var(--ink);
|
|
}
|
|
|
|
.secondary:hover {
|
|
background: var(--ink);
|
|
color: var(--paper);
|
|
}
|
|
|
|
/* One orchestrated moment on load: the floor opens out from the Z axis while the text settles in. */
|
|
.status,
|
|
.name,
|
|
.role,
|
|
.bio,
|
|
.actions {
|
|
animation: rise 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) both;
|
|
}
|
|
|
|
.name { animation-delay: 0.06s; }
|
|
.role { animation-delay: 0.16s; }
|
|
.bio { animation-delay: 0.26s; }
|
|
.actions { animation-delay: 0.34s; }
|
|
|
|
@keyframes rise {
|
|
from { opacity: 0; transform: translateY(16px); }
|
|
to { opacity: 1; transform: none; }
|
|
}
|
|
|
|
@keyframes open {
|
|
from { clip-path: inset(0 50% 0 50%); }
|
|
to { clip-path: inset(0 0 0 0); }
|
|
}
|
|
|
|
@media (max-width: 760px) {
|
|
.content { padding: 112px 0 72px; }
|
|
.bio { margin-top: 32px; font-size: 18px; }
|
|
.stage { min-height: 200px; }
|
|
.plane::before { top: 170px; }
|
|
.plane { background-size: 56px 56px; }
|
|
}
|