Orbit

Twenty-six labelled cursors ride an invisible sphere around a thin breathing ring, and the sphere can be thrown.

npx skills add https://design.how/vault/orbit

Installs the template, the brief and a check script as one skill.

What it is

A near-white card holds a thin violet ring at its centre and twenty-six cursors, each an arrow with a rounded name pill in one of eight hues. They ride a sphere that is never drawn. Every cursor only grows, shrinks and fades, but because they all do it on one hidden globe the eye builds the volume at once. The ring is not the sphere's outline: it breathes between 0.23 and 0.27 of the height twice per spin, inside a sphere of radius 0.36, and the cursors always draw over it.

The projection is orthographic, so depth never moves a cursor sideways. It shows only as scale, linear in depth from a pill 0.057 of the height at the front to 0.020 at the back, and as opacity, full through the front half and gone below -0.85, so the deepest few vanish. A slab of depth of field softens the back. Points start Fibonacci-spread over the sphere with a little seeded jitter, so coverage is even but nothing reads as a grid.

The spin is integrated, not a function of time. A 27-second phrase sets a target rate: a long drift at 0.03 turns a second, a build, one fast pass at 0.45, a settle and a held beat. A spring gives the sphere mass, so a fast pass carries a little past and settles back, and cursors lag in proportion to acceleration. The spin axis leans 0.5 radians and nods and rolls on two slow sines of 17 and 23 seconds that never line up.

The pointer is followed across the whole window, so the card sees it coming. Cursors close to it come into focus, lift a little and turn their arrows toward it, and a moving pointer pushes them aside on sprung offsets, harder the faster it moves, while the card draws its own cursor labelled You. A drag injects rate into the same integrator, a vertical drag tips the axis, and a release throws the sphere, with friction bleeding the throw back into the phrase.

How it works

  • Spread the cursors over a unit sphere with the golden angle and seeded jitter; rotate the points by the spin and the wobbling axis each frame.
  • Project orthographically: x and y straight onto the card, depth only into pill size, opacity and blur.
  • Integrate the spin angle from a rate. Ease the rate toward the phrase's target through a damped spring, and add any drag or throw to the same rate.
  • Measure every label from the live face at mount and again when the face loads; size pills from the measured widths.
  • Draw back to front: ring first, then every cursor sorted by depth, the drawn pointer last.
  • Track the pointer on the window, ease every pointer-driven value against real time, and never preventDefault a vertical touch.
  • Under reduced motion, draw t = 2.6 seconds once.

What you can change

  • CAST (twenty-six first names in eight hues): The names and their colours.
  • RING_COLOR (#6B3EB5): The ring.
  • BG (#fdfdfd): The ground.
  • PHRASE (27): Seconds in one phrase of drift, build, fast pass and settle.
  • RATE_DRIFT, RATE_WHIP (0.03, 0.45): The calm and the fast spin rate, in turns per second.
  • MAG_RADIUS, MAG_FORCE (0.19, 5.2): How far and how hard a moving pointer pushes cursors aside.
  • THROW_FRICTION (1.25): How fast a throw bleeds back into the phrase.
  • FONT_VAR (--visual-sans): The CSS variable holding the label font family.