# 🌼 Dandelion — watch a star cluster go to seed

A browser-based, GPU-accelerated **direct N-body star cluster evolution
simulator**. Build a cluster in the Nursery, sling it onto a Galactic orbit,
and watch gigayears unfold: two-body relaxation, mass segregation,
supernovae, evaporation, and the slow unwinding of the cluster into tidal
tails.

**No build step, no dependencies, no server logic** — vanilla JS + WebGL2.
Serve the directory statically (or open `index.html` over any local server).

Live at: https://dandelion.smeingast.eu

## Why "Dandelion"

A star cluster in the Galaxy's tidal field is a dandelion clock. Two-body
encounters slowly hand stars just enough energy to cross the cluster's Jacobi
radius, the tide plucks them away through the Lagrange points L1/L2, and they
drift into two long arcs of seeds — the leading and trailing tidal tails.

Open clusters are the rare astrophysical system whose *true star count* fits
in a browser: for the open-cluster presets, **every point of light is one
star**.

## The physics

### Self-gravity (collisional core)
- All-pairs O(N²) softened gravity evaluated in a WebGL2 fragment shader
  (one star per texel, RGBA32F ping-pong, ~20 flops per pair; GPU Gems 3
  ch. 31 lineage). N up to 32k; open-cluster presets use their real N.
- Plummer softening ε ≈ 0.005 r_h (4000/N)^{1/3} (≈ 1500–4000 AU), well
  below the interparticle separation: relaxation, segregation and
  evaporation survive; the effective Coulomb logarithm ln(r_h/ε) stays
  within ~10% of the unsoftened ln(0.11 N) in our regime.
- Staggered leapfrog (kick–drift), one force evaluation per substep, fixed
  **encounter-resolving timestep** dt = 0.4·√(ε³/G m_max) — softening caps
  the maximum acceleration, so this dt is safe by construction even through
  core collapse and cold collapse.

### The Galaxy and the reference frame
- Milky Way potential, MWPotential2014-flavored (Bovy 2015): Hernquist
  bulge stand-in + Miyamoto–Nagai disk + NFW halo, calibrated to
  v_c(8 kpc) = 220 km/s with 5/60/35% shares. Full 3D orbits (the smooth
  vertical disk tide at crossings comes with it).
- The precision trick: fp32 galactocentric coordinates would quantize star
  positions to ~200 AU at 8 kpc. Instead a **guiding-center origin is
  integrated in fp64 on the CPU** (JS numbers are doubles), stars live as
  **fp32 offsets**, and the shader applies the exact differential tide
  **a_MW(O + x) − a_MW(O)** — no linearized tidal tensor, which would be
  wrong by O(1) at tail distances (Renaud & Gieles 2015). The origin is
  periodically re-anchored to the cluster's density center by an exact
  identity transform (position *and* velocity, mirrored in all offsets).
- Far escapers (>6 kpc from the cluster) retire from the self-gravity sum
  but continue to feel the Galaxy.

### Stellar evolution (parametrized "toy SSE")
- t_MS ≈ 10 Gyr (m/M☉)^−2.5 (floor 3.5 Myr); red-giant phase for the last
  10% (swollen, orange); then:
  - m < 8 M☉ → white dwarf, m_f = 0.109 m_i + 0.394 (Kalirai et al. 2008),
  - 8–20 M☉ → supernova flash; 1.4 M☉ neutron star with a Hobbs et al.
    (2005) Maxwellian kick (σ = 265 km/s — it escapes immediately),
  - > 20 M☉ → black hole, m_f = max(3, 0.15 m_i), retained.
- Early mass loss physically puffs young clusters (~12% of the population
  mass is gone by ~40 Myr for a Kroupa IMF) and seeds the first tails.
- Main-sequence colors/luminosities from broken power laws + T_eff
  anchors → blackbody RGB rendering; giants swell, white dwarfs are tiny
  and hot, black holes are dark.

### Initial conditions (mcluster-style, fp64 at build time)
- **King (1966)** models: the lowered-isothermal Poisson ODE is integrated
  (RK4) for W₀ ∈ [1, 12]; radii by inverse-CDF of M(<r), speeds by rejection
  from the lowered Maxwellian. Concentration c(W₀) reproduces published
  values to 3 digits (W₀ = 5 → c = 1.03).
- **Plummer (1911)** via the exact Aarseth, Hénon & Wielen (1974) recipe.
- **EFF (1987)** profiles with isotropic Jeans velocities (young clusters).
- Uniform sphere (cold-collapse laboratory).
- **IMF**: Kroupa (2001) segmented power law (exact inverse-CDF), Salpeter,
  custom slope, or equal masses; adjustable m_max.
- Virial ratio Q (exact pairwise rescale up to N = 8k), primordial mass
  segregation (Baumgardt et al. 2008 energy-ordering), optional "tidally
  filling" scaling to the orbit's Jacobi radius, seeded PRNG
  (same seed = same cluster, shareable by URL).

### Live theory overlays
- Jacobi radius r_J = [G M_b/(4Ω² − κ²)]^{1/3} with Ω, κ from the actual
  rotation curve at the cluster's current R (circular-orbit approximation,
  labeled; off by default, toggle via the r_J chip). Also drawn as the grey
  line in the Observatory's radii chart and as dashed markers on the
  along-tail histogram.
- L1/L2 markers on the line from the cluster to the Galactic center.

### Diagnostics
Bound membership uses a Jacobi-style criterion (E_int < −1.5 G M_b/r_J,
within 2 r_J, iterated); the Observatory tracks bound mass, Lagrangian radii
plus r_J, core σ, the galactocentric orbit, the evolving mass function
(bound vs unbound vs initial), the along-tail star counts, and the
leading/trailing tail extent. The mission log narrates
supernovae, disk crossings, perigalacticon passages, mass milestones, core
contraction, and dissolution.

## What it honestly does not do
- No binaries and no few-body regularization → late core collapse stalls at
  the softening length instead of bouncing (binary burning).
- No GMC encounters, no spiral arms, no bar: real clusters near the Sun
  dissolve ~3–5× faster than the smooth tide alone (Lamers et al. 2005) —
  the prognosis card shows both numbers.
- Stellar evolution is a lookup prescription, not SSE/BSE.
- fp32 force sums: the energy-drift readout is the raw fractional change in
  the cluster's total energy since release. Once stellar evolution and tidal
  stripping begin it is dominated by that real physics (mass loss, neutron-star
  kicks, tidal work on escapers), not by integration error, which stays at the
  ~0.1% level for a well-resolved bound cluster between events.

## Controls
- **Nursery**: sculpt the cluster; drag it on the map, sling the velocity
  arrow; the orbit preview and prognosis update live. Presets are "inspired
  by" real clusters with literature values.
- **Flight**: drag to orbit the camera, wheel/pinch to zoom, click a star to
  inspect it ("ride this star" follows an escaper down the tail).
  `Space` pause · `h` hide UI (photo mode) · 🔗 copies a URL that reproduces
  the exact run (parameters + seed) · 📷 saves a PNG.
- The tab must stay visible — browsers pause animation frames in background
  tabs.

## Files
`galaxy.js` (potential, fp64 orbits, frequencies) · `models.js` (King ODE +
samplers) · `imf.js` · `physics.js` (world build, death schedule, frame
bookkeeping, diagnostics) · `shaders.js` + `renderer.js` (WebGL2 sim +
HDR/bloom rendering) · `map.js` (galaxy map) · `charts.js` · `ui.js` ·
`presets.js` · `main.js` (state machine & loop). `PLAN.md` documents the
design and the adversarial review that shaped it.

## Key references
King 1966, AJ 71, 64 · Plummer 1911 · Aarseth, Hénon & Wielen 1974, A&A 37,
183 · Elson, Fall & Freeman 1987 · Kroupa 2001, MNRAS 322, 231 · Bovy 2015,
ApJS 216, 29 · Renaud & Gieles 2015, MNRAS 448, 3416 · Küpper et al. 2008,
MNRAS 387, 1248 · Baumgardt & Makino 2003, MNRAS 340, 227 · Lamers et al.
2005, A&A 441, 117 · Kalirai et al. 2008 · Hobbs et al. 2005 · Meingast &
Alves 2019, A&A 621, L3 · Röser et al. 2019 · Jerabkova et al. 2021, A&A
647, A137 · Meingast et al. 2021, A&A 645, A84.

---
*Built in one session by Claude (Fable 5) with research + adversarial review
by subagents (Opus) and Codex. Sibling of* waltz *, the galaxy collider.*
