From 382f44167b25909fb484775b087e232673e8ebfd Mon Sep 17 00:00:00 2001 From: Andrew Moore Date: Sun, 9 Aug 2026 16:40:50 -0700 Subject: [PATCH] Merge nucleic/upbeat-jade-ibis-kt5e into main Mirrored from corpo d65aaeb. --- src/pages/index.astro | 50 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/src/pages/index.astro b/src/pages/index.astro index 8e1c459..cf778ba 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -167,7 +167,16 @@ const canonical = new URL('/', Astro.site); .ambient { position: fixed; z-index: -2; - inset: 0; + top: 0; + right: 0; + left: 0; + /* Deliberately not inset: 0. A fixed box pinned to the bottom stops at the small + viewport, but iOS Safari keeps rendering the page behind its translucent + toolbar — so the strip between svh and lvh fell back to flat paper and read as + a grey bar under the chrome, several shades off the ambient-lit page above it. + Sized to the large viewport, the field paints through the toolbar instead. */ + height: 100%; + height: 100lvh; overflow: hidden; pointer-events: none; } @@ -559,8 +568,13 @@ const canonical = new URL('/', Astro.site); /* The footer is parked past the fold: on a phone its rule is a third horizontal line competing with the masthead's and the card's, and the page reads calmer without it. The drop has to pay for the footer's own height and the shell's - bottom padding before it buys any clearance, hence a value this large. */ - --footer-drop: clamp(6.5rem, 16vh, 9rem); + bottom padding before it buys any clearance, hence a value this large. + The (100lvh - 100svh) term is the toolbar: main is sized to the small + viewport so the hero centres in what you can actually see, but Safari's + bottom bar is translucent and the page shows through it, so clearing svh + only put the footer's rule behind the controls rather than out of sight. + Both terms collapse to the clamp anywhere the two viewports agree. */ + --footer-drop: calc(100lvh - 100svh + clamp(6.5rem, 16vh, 9rem)); min-height: calc(100svh + var(--footer-drop)); } @@ -619,6 +633,36 @@ const canonical = new URL('/', Astro.site); } } + /* The phone footer is below the fold, so a timed entrance would have played out + unseen. Driven off the scroll position instead, it and its rule arrive as they + come up the screen. Scroll-driven animations are still the newest thing here, so + this stays behind @supports: without it the footer keeps the timed fade above, + which lands on load and leaves it plainly visible. */ + @supports (animation-timeline: view()) { + @media (max-width: 720px) { + .footer { + opacity: 0; + animation: footer-reveal linear both; + animation-timeline: view(); + /* Finishes at 88% rather than 100%: the last stretch of "entry" is the + element clearing Safari's translucent toolbar, and waiting that long + means it is still fading while it looks fully on screen. */ + animation-range: entry 12% entry 88%; + } + } + } + + @keyframes footer-reveal { + from { + transform: translate3d(0, 1.15rem, 0); + opacity: 0; + } + to { + transform: translate3d(0, 0, 0); + opacity: 1; + } + } + @media (max-width: 440px) { .mark { width: 2.35rem;