Skip to content

Motion and design refresh for the homepage - #1

Merged
felirami merged 4 commits into
mainfrom
design/motion-refresh
Sep 2, 2026
Merged

Motion and design refresh for the homepage#1
felirami merged 4 commits into
mainfrom
design/motion-refresh

Conversation

@felirami

@felirami felirami commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Motion and design refresh for the homepage. The page keeps its editorial identity (Manrope + DM Mono, hairline grids, bronze labels, teal signal) and gains a living hero, choreographed entrances, scroll reveals, pointer-aware cards, a self-drawing operating-model diagram, and a public metrics strip. Zero runtime dependencies: 4.4 KB of gzipped TypeScript bundled by Astro plus CSS.

What changed

  • Hero "signal board" (src/scripts/signal-board.ts): a Canvas 2D board of procedurally routed PCB-like traces with teal pulses travelling along them, pads that flash as pulses pass, and a pointer spotlight that tints nearby traces. Pauses off-screen and when the tab is hidden; renders one static frame under prefers-reduced-motion. Runs at the display refresh rate with a 14 ms worst frame at 1440×900.
  • Entrance choreography: masthead, eyebrow, masked line-rise headline (with a mint gradient on the second line), lede, buttons and index cells stage in over ~1.2 s using transform and opacity only.
  • Scroll reveals (src/scripts/motion.ts): IntersectionObserver reveals with batch stagger; elements hand control back to their own transitions once revealed.
  • Masthead: condenses on scroll with backdrop blur (no layout shift, the sticky box keeps its height), a scroll-progress hairline, animated nav underlines, scroll-position-based active section, and a new Deck link.
  • Work grid: six-column layout (two featured + three regular, no orphan row), product marks and status pills with live dots on every card, pointer-follow highlight and border glow, animated link underlines and arrow nudges.
  • Operating model: the signal path draws itself when in view (measured in screen space so the non-scaling stroke dashes line up), nodes light in sequence, a packet travels the path continuously via SMIL, and a progress hairline draws across the four steps.
  • Operator network: a unique sigil per agent (drawn on hover), live dots, hover highlight.
  • Public proof: a metrics strip with count-up numerals using the figures already published in the deck (75 repos, 2,051+ downloads, 49 detectors, Open ledger) and an "as of August 30, 2026" line. A contract test keeps these in sync with public/deck/index.html.
  • Company / contact / footer: monogram watermark and pill links on the founder card, a "Read the company deck" call to action, an outlined ARCA watermark in the footer.
  • Fonts: Google Fonts now load via preconnect + <link> instead of a render-blocking CSS @import.
  • Progressive enhancement: a one-line inline script adds html.js; every hidden-until-animated rule is scoped to it and to prefers-reduced-motion: no-preference, so the page is fully readable without JavaScript and for reduced-motion users. The blanket reduced-motion reset is replaced with a policy (short opacity fades stay; transforms, blur, delays, counters and the packet are dropped).

Verification

  • npm run check green: astro check (0 errors), 9 contract tests, build, built-site contract, wrangler dry run.
  • npm run qa against wrangler dev --local-protocol https at 1440×1000 and 390×844: HTTP 200, zero console errors, zero axe-core violations, no horizontal overflow, contact link on one line. The QA walk now scrolls the page (instantly, bypassing scroll-behavior: smooth) before the screenshot and axe run so reveals have fired.
  • Manual review at 1440, 900 and 390 widths and with prefers-reduced-motion: reduce (all content visible immediately, board static).
  • /deck untouched; /404 unaffected.

Not in this PR

Production deploy (npm run deploy) is still a manual step after merge.

Deck (/deck) gets the same treatment

  • /deck moves from a static HTML file to src/pages/deck.astro, rendered through BaseLayout (new stylesheet prop) and sharing motion.ts and signal-board.ts. Same URL, same content, same deck stylesheet.
  • Cover: signal board behind the title, masked line-rise headline, staged entrance for kicker, lead, index rows and diagram; the cover diagram draws itself with sequenced nodes and a travelling packet.
  • Every slide reveals its content on arrival; launchpad, product-strip, range, metric and system cards carry the pointer glow; proof metrics count up; the header gets the progress hairline and the rail keeps its active state (now scroll-position based).
  • Shared engine styles live in public/motion.css (tokens, board host, reveal system, .glow cards, drawing transitions, reduced-motion policy, print overrides). Print forces every reveal visible and hides the canvas, so PDF export of the deck still works. The homepage stylesheet keeps only page-specific rules.
  • Since /deck is now a real route, the sitemap lists it automatically; trailingSlash: 'never' keeps the URL identical to the canonical. The old public/deck/index.html and deck.js are removed; public/deck/styles.css and assets stay.
  • QA now covers / and /deck at both viewports (all four runs: 200, zero console errors, zero axe violations, no overflow). Contract tests read the Astro page, keep the deck content assertions, and add checks for the shared motion layer and print safety.

Introduce two dependency-free TypeScript modules bundled by Astro: motion.ts
(scroll reveals, condensed masthead with progress line, active nav, pointer
highlights, magnetic buttons, metric counters, self-drawing signal map) and
signal-board.ts (the hero canvas: procedurally routed traces with travelling
pulses, pointer spotlight, off-screen and hidden-tab pausing, static frame
under reduced motion).

Load Google Fonts through preconnect and link tags instead of a CSS @import,
and add the inline html.js gate that scopes every hidden-until-animated rule
so the page stays fully readable without JavaScript.
Hero: masked line-rise headline with a mint gradient on the second line,
staged entrance for eyebrow, lede, buttons and index cells, and the signal
board layered behind the copy. Masthead condenses on scroll with backdrop
blur, a scroll-progress hairline, animated nav underlines and a Deck link.

Sections: scroll reveals with staggered children; a six-column work grid
(two featured plus three) with product marks and status pills on every card;
pointer-follow highlight and border glow on cards; the operating-model map
draws itself with sequenced nodes and a travelling packet; unique sigils and
live dots for the five operators; a metrics strip above the proof tiles using
the figures already published in the deck; a monogram and pill links on the
founder card; a deck call to action in the contact section; an outlined ARCA
watermark in the footer.

Replace the blanket reduced-motion reset with a policy: transforms, blur,
delays, counters and the packet are dropped while short opacity fades stay.
Add tests covering the progressive-enhancement gate, font loading, the
reduced-motion policy, the deck links, and that the homepage metrics match
the deck figures exactly. Walk the page in the Playwright QA before the
screenshot and axe run so scroll-triggered reveals have fired. Document the
motion layer in the README.
Move /deck from a static HTML file to src/pages/deck.astro so it renders
through BaseLayout and reuses motion.ts and signal-board.ts. The cover gets
the signal board, a masked line-rise title, staged entrance, and a cover
diagram that draws itself with sequenced nodes and a travelling packet.
Every slide reveals its content on arrival; launchpad, product, range,
metric, and system cards carry the pointer glow; the proof metrics count up.

Extract the shared engine styles into public/motion.css (tokens, board host,
reveal system, glow cards, drawing transitions, reduced-motion policy, and
print overrides that force every reveal visible and hide the canvas so the
deck still exports cleanly to PDF). The homepage stylesheet keeps only its
page-specific rules and its cards use the shared .glow class. BaseLayout
takes a stylesheet prop and always loads motion.css.

Because /deck is now a real route, the sitemap lists it on its own with
trailingSlash set to never so the URL matches the canonical. The QA script
covers both pages, check-build requires motion.css, and the deck content
contracts read the Astro page. The old static deck HTML and rail script are
removed.
@felirami
felirami merged commit 935d482 into main Sep 2, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant