Concept & Inspiration
The brief for this direction was “quiet-money, high-fashion editorial” — the idea that a studio confident in its work doesn’t need to shout. The reference point isn’t a typical SaaS landing page; it’s a design annual or a photography monograph: near-black stock, generous margins, one disciplined accent colour, and work presented as numbered “plates” rather than portfolio cards. That last idea became the structural gimmick of the Selected Work section — each client project is Plate I, II, or III, with a duotone image, a roman numeral, and a caption, styled the way a fashion or architecture book would present a spread.
Restraint was treated as a design constraint, not an afterthought:
the gold accent (#b08d57) is never used as a fill or a
button background — only as 1px hairlines and 0.72rem
letter-spaced small-caps labels. If gold shows up anywhere else,
that’s a bug, not a variation.
Typography & Colour
Display type is Fraunces, used at its italic and
optical-size variants for pull-quotes (the manifesto line and the
four belief statements) — Fraunces was built for exactly this:
it has a soft, wet-ink italic that reads as considered rather than
decorative. Body copy is Work Sans at a light
weight (300–400), chosen for its neutrality: it needed to
disappear next to Fraunces, not compete with it. Both are
self-hosted via @fontsource/fraunces and
@fontsource/work-sans rather than loaded from Google
Fonts at runtime — one less third-party request, no render
blocking on an external origin, and it works if a build ever needs
to run somewhere offline.
Colour is three values on purpose: background #0b0b0a,
ink #f2ede4, accent #b08d57. Cream on
near-black measures at roughly 16.9:1 contrast — comfortably
past WCAG AA (4.5:1) and AAA (7:1) for body text, which matters more
here than usual because the whole design leans on long-form reading
(the manifesto, the beliefs, this page).
The Reveal Technique
Two distinct mechanisms are in play, deliberately not unified into one library-driven system:
Every section (pillars, disciplines, plates, beliefs, contact) uses
a plain IntersectionObserver. Elements start with
opacity: 0 and translateY(12px) in CSS; when
an element crosses 15% into the viewport, JS adds
.is-visible, which triggers a CSS transition back to
rest. Stagger comes from an inline --i custom property
read by a CSS transition-delay: calc(var(--i) * 0.09s)
rule — no animation library needed for the vast majority of
the page.
The hero gets special treatment because the brief called for two
specific hero-only beats: the headline splits into one
<span> per letter and animates in with
GSAP (opacity, a few pixels of Y, and letter-spacing
easing from 0.06em to 0) on load, and the hero image drifts via
GSAP ScrollTrigger (yPercent: 14,
scrubbed against hero scroll progress) for the parallax. GSAP is
imported dynamically (await import('gsap')) only inside
that hero-init function, so the ~30kb of GSAP core plus ScrollTrigger
never loads on a reduced-motion visit or blocks anything else on the
page. Everything motion-related checks
prefers-reduced-motion first and short-circuits to the
final, settled state if it's set.
The Imagery
Three images were generated with gpt_image_2 (via the Higgsfield CLI), all in the same photographic language so they'd read consistently once treated:
- Hero portrait (3:4) — “a majestic owl portrait, dramatic single-source studio lighting, deep shadow, high contrast black and white photography, sharp focus on eyes, minimal background”. Used full-bleed behind the hero headline and again, cropped, as Plate I.
- Feather macro (16:9) — “extreme macro close-up of owl feather texture, soft directional light, monochrome, fine detail”. Used as the full-bleed section divider between the pillars and the disciplines grid, and again as Plate III.
- Wing in flight (3:4) — “owl wing extended mid-flight, motion blur at wingtip, dramatic side lighting, monochrome high contrast photography, dark background”. Used as Plate II.
All three run through Astro's built-in <Image />
component (astro:assets, sharp-backed) at build time,
which emits responsive .webp variants at the specific
widths each placement needs rather than shipping one oversized
source file everywhere. The duotone look (near-black shadows,
warm-gold midtones) is a CSS treatment —
grayscale(1) contrast(1.15) brightness(0.92) on the
<img>, plus a mix-blend-mode: color
gradient overlay — rather than being baked into the source PNG.
That keeps the three source images reusable and means the exact
tone can still be tuned in one place (global.css)
without regenerating anything.
Two Honest Tradeoffs
1. The plates aren't literal project screenshots. The three real client projects (Rentsy, a rental aggregator; Bali Destination Wedding, a wedding reseller platform; Non La Vietnam Tours, a tour operator site) don't have production screenshots available as content assets for this brief. Rather than fabricate fake interface mockups, the Selected Work plates reuse the same three owl photographs as a consistent editorial motif — a legitimate convention in photography-book design, but it does mean the three plates aren't visually distinct from one another beyond the crop. A production version of this site would swap in real project photography per plate.
2. GSAP is a real dependency for a small amount of the page. It's dynamically imported and scoped to the hero only, but it's still a second animation system alongside the IntersectionObserver path used everywhere else. The alternative — doing the letter stagger and scroll-scrubbed parallax in hand-rolled JS or pure CSS scroll-timelines — was considered and rejected: CSS scroll-timelines aren't reliably supported across browsers yet, and hand-rolling scrub-linked transforms duplicates what ScrollTrigger already does correctly. The cost is accepted as worth it for the two moments the brief specifically called for, not used as a general-purpose animation crutch.