From cc2b426119879896cdc4f59ab2a20cbc5fa412b7 Mon Sep 17 00:00:00 2001 From: Hisham Aburaqibah Date: Wed, 23 Sep 2026 23:22:57 +0200 Subject: [PATCH] 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 --- .../components/ui/Navigation/Navigation.css | 75 ++++++++++++++++--- apps/web/app/routes/_page-kit/sections.tsx | 6 -- apps/web/app/routes/home.tsx | 2 +- 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/apps/web/app/components/ui/Navigation/Navigation.css b/apps/web/app/components/ui/Navigation/Navigation.css index 3a14c20..3fb363e 100644 --- a/apps/web/app/components/ui/Navigation/Navigation.css +++ b/apps/web/app/components/ui/Navigation/Navigation.css @@ -29,20 +29,30 @@ last, slowest part of the decelerating slide. The translate is physical (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 - Arabic too. Pure CSS, so it runs from the server-rendered HTML without - waiting for hydration, and the `both` fill keeps the suffix hidden through - the delay instead of flashing in first. It replays whenever the navigation - mounts again, e.g. on a client-side navigation back to a page. Under - prefers-reduced-motion the animation is 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. */ + Arabic too. + +After that one-time reveal the mark keeps breathing: after a long rest + (~26s of stillness per cycle) it slides back out from behind the P and + returns, so the wordmark quietly draws the eye without the glyphs moving + while they are visible. The two + 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 { overflow: hidden; } .sh-brand-suffix__mark { - animation: sh-brand-suffix-in var(--motion-duration-reveal) - var(--motion-ease-entrance) var(--motion-delay-reveal) both; + animation: + 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) { @@ -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 { from { opacity: 0; diff --git a/apps/web/app/routes/_page-kit/sections.tsx b/apps/web/app/routes/_page-kit/sections.tsx index 4f66548..bb18cf1 100644 --- a/apps/web/app/routes/_page-kit/sections.tsx +++ b/apps/web/app/routes/_page-kit/sections.tsx @@ -583,12 +583,6 @@ export function PageHero({ aria-hidden="true" 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. */} -