Adds a Russian version (data/resume.ru.json, default language) with an RU/EN switch stored under the key shared with the front page and the portfolio. The top bar becomes the site-wide one (brand, Resume, Portfolio, Gitea, Contact, language, theme) with a second row of anchors for this page's sections, and the fonts move to Unbounded and Onest so the three pages share one type system. Portfolio links now point at /portfolio/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XtcZtnG4GQA1d6mW5PNrS9
221 lines
4.5 KiB
CSS
221 lines
4.5 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, var(--hero-top) 0%, var(--hero-bottom) 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, var(--stage-top) 0%, var(--stage-bottom) 100%);
|
|
border-top: 1px solid var(--horizon);
|
|
}
|
|
|
|
.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, var(--grid) 1px, transparent 1px),
|
|
linear-gradient(to bottom, var(--grid) 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: var(--pill-bg);
|
|
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 var(--dot-glow);
|
|
}
|
|
|
|
.name {
|
|
margin: 30px 0 0 -0.045em;
|
|
font: 700 clamp(38px, 7.1vw, 118px) / 1 var(--font-head);
|
|
letter-spacing: -0.05em;
|
|
overflow-wrap: break-word;
|
|
}
|
|
|
|
.role {
|
|
margin-top: 22px;
|
|
font: 500 clamp(18px, 2.1vw, 30px) / 1.2 var(--font-head);
|
|
letter-spacing: -0.035em;
|
|
}
|
|
|
|
.bio {
|
|
max-width: 58ch;
|
|
margin-top: 44px;
|
|
font-size: 19px;
|
|
line-height: 1.62;
|
|
color: var(--ink-2);
|
|
}
|
|
|
|
.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: 1000px) {
|
|
.name {
|
|
font-size: clamp(44px, 12.5vw, 104px);
|
|
}
|
|
}
|
|
|
|
@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; }
|
|
}
|
|
|
|
.link {
|
|
margin-left: 10px;
|
|
padding: 14px 0;
|
|
font: 600 16px/1.2 var(--font-body);
|
|
text-decoration: underline;
|
|
text-decoration-thickness: 1.5px;
|
|
text-underline-offset: 5px;
|
|
text-decoration-color: var(--ink-line);
|
|
transition: text-decoration-color 0.2s, color 0.2s;
|
|
}
|
|
|
|
.link:hover {
|
|
color: var(--z-text);
|
|
text-decoration-color: currentColor;
|
|
}
|
|
|
|
@media (max-width: 620px) {
|
|
.link {
|
|
margin-left: 0;
|
|
}
|
|
}
|