the guide
how this site was made
stillpoint is a breathwork studio that teaches exactly one protocol — 4–7–8 — to stressed professionals. so the site does exactly one thing: it puts a working breath pacer in the center of the first viewport and lets you try a cycle before it asks for anything. the art direction is a dawn that the page moves through as you breathe — rose on the inhale, sky on the hold, dusk on the long exhale — with enormous whitespace and one idea per viewport.
palette
a dawn, split into phases
- rose #f4dfe0 — the inhale
- pale sky #cfe0f0 — the hold
- mid dusk #93a2c8 — the exhale begins
- dusk blue #57689a — the long letting-go
- deep dusk #333f68 — the bottom of the gradient
- charcoal #343a44 — every word on the page
no accent color, no pure white, no black. the three sky gradients are fixed full-screen layers; only their opacity changes, so the whole page can breathe at 60fps without repainting a single gradient.
type
wide, light, lowercase
asap (variable, width axis pushed to 125%, weights around 210–380) carries the display voice: a rounded humanist sans that turns soft and unhurried when you stretch it wide and strip the weight out. hanken grotesk at 300 does the reading. there is almost no bold anywhere — emphasis comes from width, spacing, and silence — and every character on the site is lowercase, because the brand never raises its voice. the giant 4 / 7 / 8 numerals are the only loud thing, and they are the literal content of the protocol.
techniques
the breathing engine
one requestAnimationFrame loop drives everything: the blob, the ring, the
countdown, and the sky. the blob is an svg path rebuilt every frame — a circle whose radius is
modulated by three slow sine harmonics, then scaled by the breath:
// radius = base × breathScale × (1 + soft harmonics)
var w = 1 + wobble * ( 0.52 * Math.sin(3*a + t*0.50)
+ 0.30 * Math.sin(5*a - t*0.34)
+ 0.18 * Math.sin(2*a + t*0.21) );
var r = R_BASE * scale * w;
the breath scale follows the protocol timeline — 4s up, 7s shimmering hold, 8s down — through an ease-in-out sine, and everything chases its target with frame-rate–independent lerps so a dropped frame never jolts the breath:
if (ph.i === 0) s = lerp(0.62, 1.0, easeInOutSine(ph.p)); // in, 4s
if (ph.i === 1) s = 1.0 + 0.006 * Math.sin(ph.p*TAU*1.5); // hold, 7s
if (ph.i === 2) s = lerp(1.0, 0.62, easeInOutSine(ph.p)); // out, 8s
scale = lerp(scale, s, Math.min(1, dt * 9));
the progress ring’s track is three arcs whose lengths are exactly 4/19, 7/19 and
8/19 of the circumference — the structure of the ring is the protocol. the sky crossfade
and the blob’s gradient stops interpolate between rose, day and dusk triplets in the same loop.
under prefers-reduced-motion the form stands still and the cycle runs as a stepped,
once-per-second countdown with gentle discrete sky changes.
iteration
three passes
- pass one — correctness. the scroll-reveal effect was hiding whole sections until javascript let them in — deleted it outright; a calm page never gates its content. also flattened the blob’s gradient (it was reading as a shaded 3d ball), gave the idle breath more presence, and eased the section heights.
- pass two — elevate. put a quiet 4 / 7 / 8 numeral at the middle of each ring segment, added a fourth “deep dusk” sky layer that sinks further with every finished cycle, choreographed the staggered page-load settle, and made the breath itself clickable to begin.
- pass three — taste. chanel rule: the hero hint used to recite the whole protocol — the ring already says 4/7/8, so the hint now says only what the ring can’t. fixed a bad mobile line-break in the protocol heading, laid a static dawn gradient under the fixed sky for overscroll, and re-verified reduced motion and keyboard focus.
do this yourself
a recipe
- give claude a subject with a built-in rhythm — a breath, a tide, a metronome — and ask for the page to physically perform it, not illustrate it.
- pin the palette to a real phenomenon (here: one dawn) and assign each color a moment in time, not a ui role.
- pick one variable font and spend its axes deliberately — width for voice, weight for volume — instead of adding more typefaces.
- ask for a single rAF loop that owns all motion, with targets and lerps, so every element breathes from the same clock.
- make structure carry data: if a ring has segments, their lengths should mean something.
- demand a real reduced-motion fallback and test it — a calm page that can also hold still.
- screenshot, critique, fix — three times, at 1440px and 390px. read the screenshots like a stranger would.
- end by removing one thing you like. it will hurt. do it anyway.