From 77a552c0aa78ace81683d3db6a59a03e546ce0a7 Mon Sep 17 00:00:00 2001 From: TeoSlayer Date: Fri, 23 Oct 2026 22:42:19 -0700 Subject: [PATCH] home: keep the hero phrase and the numbers readable on phones The longest rotating phrase ("read any web page as Markdown") was wider than a phone screen and got clipped; it now shrinks just enough for the longest phrase to fit, one size for all phrases. The numbers count-up watched the whole section with a 40% threshold, which a stacked phone layout never reaches, so figures read 0 while on screen; it now watches each figure. Co-Authored-By: Claude Opus 5.5 --- src/pages/index.astro | 49 ++++++++++++++++++++++++++++++------- src/pages/plain/index.astro | 2 +- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/pages/index.astro b/src/pages/index.astro index 1fc2e09c..33309d0e 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -3282,14 +3282,16 @@ seq=2 bytes=6 time=144.993333ms [dial=47.968ms echo=96.987ms] } statBigs.forEach(function (el) { render(el, 0); }); // start at 0 pre-reveal + // Watch each figure, not the whole section: stacked on a phone the section + // is taller than the screen, so a 40% threshold on it never fired and the + // figures stayed at 0. var numObs = new IntersectionObserver(function (entries) { entries.forEach(function (e) { - if (e.isIntersecting) { statBigs.forEach(spin); } - else { statBigs.forEach(function (el) { render(el, 0); }); } + if (e.intersectionRatio >= 0.4) spin(e.target); + else if (!e.isIntersecting) render(e.target, 0); }); - }, { threshold: 0.4 }); - var numbersSec = document.getElementById('numbers'); - if (numbersSec) numObs.observe(numbersSec); + }, { threshold: [0, 0.4] }); + statBigs.forEach(function (el) { numObs.observe(el); }); } })(); @@ -3321,10 +3323,39 @@ seq=2 bytes=6 time=144.993333ms [dial=47.968ms echo=96.987ms] var max = box.parentElement ? box.parentElement.clientWidth : Infinity; box.style.width = Math.min(word.offsetWidth, max) + 'px'; } - // Wait for fonts, then lock the initial width. - if (document.fonts && document.fonts.ready) { document.fonts.ready.then(fit); } - fit(); - window.addEventListener('resize', fit); + // On a narrow screen the longest phrase can be wider than the room it has, + // and the box clipped it ("Markdowr" on phones). Shrink the phrase only as + // far as the longest one needs: one size for every phrase keeps the line + // from jumping as it rotates. + var probe = word.cloneNode(false); + probe.style.cssText = 'position:absolute;visibility:hidden;left:0;top:0'; + var lastWidth = -1; + function scale(force) { + var line = box.parentElement; + if (!line || (!force && line.clientWidth === lastWidth)) return; + lastWidth = line.clientWidth; + box.style.fontSize = ''; + var cs = getComputedStyle(line); + var room = line.clientWidth - parseFloat(cs.paddingLeft) - parseFloat(cs.paddingRight) - 1; + // Inline (wider screens), the phrase shares its line with "your agent can". + if (getComputedStyle(box).display !== 'block' && box.previousSibling) { + var r = document.createRange(); + r.selectNodeContents(box.previousSibling); + room -= r.getBoundingClientRect().width; + } + box.appendChild(probe); + var widest = 0; + phrases.forEach(function (p) { probe.textContent = p; widest = Math.max(widest, probe.offsetWidth); }); + box.removeChild(probe); + if (widest > room) { + box.style.fontSize = Math.floor(parseFloat(getComputedStyle(box).fontSize) * room / widest * 10) / 10 + 'px'; + } + fit(); + } + // Wait for fonts, then lock the initial size and width. + if (document.fonts && document.fonts.ready) { document.fonts.ready.then(function () { scale(true); }); } + scale(true); + window.addEventListener('resize', function () { scale(); }); // Refit whenever the word's own size changes (late webfont, vw-based // font size), not only on window resize. if ('ResizeObserver' in window) new ResizeObserver(fit).observe(word); diff --git a/src/pages/plain/index.astro b/src/pages/plain/index.astro index b192ed85..362d82e8 100644 --- a/src/pages/plain/index.astro +++ b/src/pages/plain/index.astro @@ -1,7 +1,7 @@ --- // Plain-text twin of src/pages/index.astro, edited by hand to match it. // plain-source: src/pages/index.astro -// plain-source-sha256: d76fea67c1feca8c09dcb1efcb351f96587322725555f5a79ca52d1c3589cd38 +// plain-source-sha256: 4bd1061ad9d2d35aa3017e00473074b4f393484401489f9a211d472bd4aea2a2 import PlainLayout from '../../layouts/PlainLayout.astro'; import { apps } from '../../data/apps'; import { getLiveStats } from '../../lib/liveStats';