Closeness sets the orbit.
Each friend carries a single score, closeness ∈ [3, 98]. It maps to an orbit radius — higher closeness, tighter orbit. The 0.92 exponent gently widens the inner zones so your closest people don't pile up on the sun.
Drag the slider — the five bands are the “friendzones.”
Moments push. Silence pulls.
Logging a moment nudges closeness by how it felt: 🔥 radiant +12, ☀️ warm +7, 🌗 steady +2, 🌫️ distant −6, ❄️ cold −12.
Between moments, time drifts a friend outward — but gently: a 4-day grace period costs nothing, then 0.45 points per quiet day, capped at −28. Silence alone can never erase a friendship.
Tap a feeling to log a moment (it resets the silence clock), then scrub the quiet days.
Every signal decays with a half-life.
There are no cutoff windows anywhere in the app. Every observation keeps a vote forever — the vote just halves with each half-life. One knob per signal:
Which way are they leaning?
Two kinds of evidence live on one timeline: reads you tag on moments (“leaning in” / “pulling away”, weight 1) and their explicit declaration (weight 2.5). Lean is the decay-weighted average — the newest evidence naturally leads, no precedence rules needed. Even one ancient read fully drives the value until it's superseded.
New events land at “today” (right edge) and outweigh the past. Diamonds are declarations (2.5×).
History is mass.
Warm history accumulates into a foundation (90-day half-life), and a solid past damps how hard fresh negative signals can swing you — a rough week with an old friend reads differently than one with a stranger. Positive lean always passes through untouched.
displayedLean = lean < 0 ? lean · (1 − 0.6 · f) : lean
Energy, momentum, volatility.
Three more decayed signals give each planet its weather:
⚡ Energy
How alive the bond is. Sign-agnostic — a fight is energy too. Saturates around ~4 fresh moments.
🧭 Momentum
Decay-weighted net change — which way things are actually going. Feeds the prediction below.
🌪 Volatility
How often the story flips sign, weighted so recent weaving beats ancient flip-flops.
Energy drives orbital speed — a neglected bond crawls at 0.35×, a vivid one races at 1.5×. Speed also falls off Kepler-style with radius: far planets move slower.
Signals paint the planet.
Nothing about a planet's look is random or stored — appearance is a pure function of the signals. Energy → radiance (body lightness and glow). Lean → temperature: the hue rotates at most 18° toward gold (45°) when they lean in, toward ice (255°) when they pull away — the identity hue always survives, and a cold lean drains saturation. Volatility → turbulence, a progressive stack: storm bands from 0, an unstable rim above 0.4, an erratic corona above 0.7.
core = 66 + 20·e %L, glowα = 0.18 + 0.42·e
bands ∝ v, rim = smoothstep(0.4, 0.8, v), corona = smoothstep(0.7, 1.0, v)
Push volatility past 0.4, then 0.7, to watch the rim and corona kick in.
A ghost shows where you're headed.
Set an intention for a friend and a ghost planet appears about a month out — your stated pull, plus the momentum you've actually got:
drift → eff − 18 + min(0, m)
No streaks. No scores to win.
Just honest orbits.
Thirty seconds after seeing a friend: tap them, tap how it felt, done. The physics remembers everything else — gently, forever.
open your cosmos