more style changes

- Removed the sheen over the homepage hero image
- Animated the SHARP-ER logo in the navbar
- More padding on the bottom of the hero section in the homepage
This commit is contained in:
2026-09-23 23:22:57 +02:00
parent e930318f14
commit cc2b426119
3 changed files with 67 additions and 16 deletions
@@ -29,20 +29,30 @@
last, slowest part of the decelerating slide. The translate is physical last, slowest part of the decelerating slide. The translate is physical
(translateX) on purpose: the lockup row is pinned to dir="ltr" because a (translateX) on purpose: the lockup row is pinned to dir="ltr" because a
Latin wordmark never mirrors, so the P is always left of the suffix, in Latin wordmark never mirrors, so the P is always left of the suffix, in
Arabic too. Pure CSS, so it runs from the server-rendered HTML without Arabic too.
waiting for hydration, and the `both` fill keeps the suffix hidden through
the delay instead of flashing in first. It replays whenever the navigation After that one-time reveal the mark keeps breathing: after a long rest
mounts again, e.g. on a client-side navigation back to a page. Under (~26s of stillness per cycle) it slides back out from behind the P and
prefers-reduced-motion the animation is removed outright - app.css only returns, so the wordmark quietly draws the eye without the glyphs moving
collapses the duration and would leave the delay holding the suffix while they are visible. The two
hidden - so the full name is simply there from the start. */ animations are sequenced by delay - the reveal (once, `both` fill, so the
suffix stays hidden through its delay instead of flashing in) hands over
to the loop, whose later position in the list wins from its start, and
whose own delay is when the revealed lockup is simply at rest. Pure CSS,
so it runs from the server-rendered HTML without waiting for hydration.
Under prefers-reduced-motion both animations are removed outright -
app.css only collapses the duration and would leave the delay holding the
suffix hidden - so the full name is simply there from the start. */
.sh-brand-suffix { .sh-brand-suffix {
overflow: hidden; overflow: hidden;
} }
.sh-brand-suffix__mark { .sh-brand-suffix__mark {
animation: sh-brand-suffix-in var(--motion-duration-reveal) animation:
var(--motion-ease-entrance) var(--motion-delay-reveal) both; sh-brand-suffix-in var(--motion-duration-reveal)
var(--motion-ease-entrance) var(--motion-delay-reveal) both,
sh-brand-breathe calc(var(--motion-duration-reveal) * 37.5)
ease-in-out calc(var(--motion-duration-reveal) * 5) infinite;
} }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
@@ -68,6 +78,53 @@
} }
} }
/* One 30s breath: dwell at rest (~26s - the stillness is what stretches, the
gestures stay at a human pace), slide back out behind the P (the reverse of
the reveal - solid while it pulls away, fading as it leaves), pass on
hidden, then play the reveal again, and hold. Looped, with the cycle ending
where it starts so the seam is invisible. Each slide is ONE eased interval
of roughly one reveal duration - the opacity stop inside the out-slide is
opacity-only, so it never splits the transform's easing and the glyphs
cannot stall or hitch mid-gesture. */
@keyframes sh-brand-breathe {
/* settled */
0%, 87% {
transform: translateX(0);
opacity: 1;
animation-timing-function: var(--motion-ease-standard);
}
/* pull back solid - opacity only, so the 87→90 transform still runs one
eased interval and the slide never hitches */
88.5% {
opacity: 1;
}
/* gone, behind the P */
90% {
transform: translateX(-100%);
opacity: 0;
}
/* pass, hidden, then the reveal again - one eased slide back in */
94% {
transform: translateX(-100%);
opacity: 0;
animation-timing-function: var(--motion-ease-entrance);
}
97% {
transform: translateX(0);
opacity: 1;
}
/* settled until the cycle hands over (0% is settled too) */
100% {
transform: translateX(0);
opacity: 1;
}
}
@keyframes sh-nav-menu-in { @keyframes sh-nav-menu-in {
from { from {
opacity: 0; opacity: 0;
@@ -583,12 +583,6 @@ export function PageHero({
aria-hidden="true" aria-hidden="true"
className="pointer-events-none absolute inset-0 bg-[var(--overlay-picture-tint)]" className="pointer-events-none absolute inset-0 bg-[var(--overlay-picture-tint)]"
/> />
{/* A highlight travelling across the picture - the draft's
`sheen`. Decorative, and it rides on top of both washes. */}
<span
aria-hidden="true"
className="sh-sheen pointer-events-none absolute inset-0 bg-[linear-gradient(100deg,transparent_35%,var(--overlay-veil)_50%,transparent_65%)]"
/>
</div> </div>
{/* The colour band (478:16360, redrawn in the drafts' home {/* The colour band (478:16360, redrawn in the drafts' home
+1 -1
View File
@@ -479,7 +479,7 @@ export default function Home({ loaderData }: Route.ComponentProps) {
/> />
<PageHero <PageHero
className="bg-[var(--surface-sunken)] [--layout-hero-top:clamp(2.5rem,6vw,4.5rem)] [--layout-hero-bottom:var(--spacing-md)]" className="bg-[var(--surface-sunken)] [--layout-hero-top:clamp(2.5rem,6vw,4.5rem)]"
title={headline} title={headline}
lead={lead} lead={lead}
leadWithActions leadWithActions