Light, held behind glass.
Nimbus is a sleep service that refuses the anxious grammar of scores and streaks. The page needed to feel like the time before sleep: dark, spacious, responsive to a little light, and never inert.
The central image is a bedside report hovering over an animated field of moving color. Frosted panels don’t merely sit on top of that field: real backdrop blur lets the canvas refract through them, while a bright inner border suggests the light collecting at the edge of a piece of glass.
An actual canvas mesh, not a background image.
The fixed canvas starts with soft color pools, then builds a 10 × 7 mesh. Every frame, each node takes a slightly different sine and cosine path. Two clipped gradient triangles fill every mesh cell, so the field has real moving facets instead of a static CSS gradient. The panels above it use backdrop-filter: blur(24px), which is what makes the Aurora visibly bleed into the UI.
function point(col, row, time, cols, rows) {
const x = width * col / (cols - 1)
+ Math.sin(time*.00012 + row*.93 + col*.61) * (32 + row*2);
const y = height * row / (rows - 1)
+ Math.cos(time*.00015 + col*.82 - row*.49) * (35 + col*1.5);
return { x, y };
}
for (let row = 0; row < rows - 1; row++) {
for (let col = 0; col < cols - 1; col++) {
const a = point(col, row, time, cols, rows);
const b = point(col + 1, row, time, cols, rows);
const c = point(col, row + 1, time, cols, rows);
const d = point(col + 1, row + 1, time, cols, rows);
const ca = colors[(row + col) % colors.length];
const cb = colors[(row * 2 + col + 1) % colors.length];
triangle(a, b, c, ca, cb);
triangle(b, d, c, cb, ca);
}
}
The live page caps canvas density at two device pixels and stops its frame loop while the tab is hidden. Its glass cards also use a pointer-driven spring, and the canvas shifts its pooled light slightly as the reader moves from night report to morning invitation.
Cold light, warm interruption.
Sleep is a weather system.
Inter, Arial, sans-serif · 300–700. Large type uses a -0.07em track and a light 300 weight; reading copy returns to a more open 14px rhythm.
Pass 1 — correctness
- Guarded both canvas initializers so a missing canvas or unavailable 2D context leaves the static CSS aurora fallback intact instead of throwing.
- Capped render density at 2×, made motion preference changes live, and cancel frame loops when the tab is hidden or the observed canvas/panel is outside the viewport.
- Added shrink-safe grid tracks, 44px minimum targets for navigation and gallery links, and a text alternative for the seven-night chart.
- Darkened the translucent surfaces and ambient veils so reading text keeps a reliable contrast buffer while the aurora remains visible behind the glass.
- Known limitation: browsers without
backdrop-filterstill show layered dark panels and the aurora, but cannot reproduce the refracted blur.
Pass 2 — design depth
- Weak moment: repeated, side-by-side glass cards. The weekly story became one large report with a smaller interpretation card deliberately overlapping its lower edge, giving the section a clear foreground and background.
- Weak moment: timid display rhythm. A spacing scale now governs the long pauses; headlines are larger, tighter, balanced, and the weekly headline is split into intentional lines instead of accepting a chance wrap.
- Weak moment: the aurora stopped at the backdrop. Brighter chromatic seams, a diffused spill behind the weekly report, and a second glass surface in the morning note make the moving light feel held and refracted by the interface.
Pass 3 — complexify
- New visitor moment: the lower-page Night Context explorer. Three ordinary moments now reveal different Nimbus responses. It begins in a deliberate “nothing pinned yet” state and can be cleared back there, so the interaction never implies that every signal needs an interpretation.
- New page state: the aurora progresses with the reader. Scroll position slowly lifts the light beam and eases the veil, making the long page feel like it moves toward morning. Reduced-motion preference keeps that state still.
- Final finish: less theatrics, more trust. The controls are native buttons with pressed states and visible focus rings; their color field changes are soft, bounded, and disabled under reduced motion. Social metadata now names Nimbus consistently, while the inline fallback keeps the first paint composed before canvas or font work finishes.