- readsLaunch Library's T−0 times
- becomesimminence → mass, recomputed every second
- writes
--w - you seethe next launch literally gains weight as T−0 approaches — time itself drives the field
No canvas is drawn here — the field is invisible; these variables are its only output. Without it you would build: a countdown per row and a cron that re-sorts.
Data honesty
- Data source
- Real Launch Library 2 data (thespacedevs.com) — upcoming rocket launches with T−0 times, free API (attribution).
- Snapshot
- Committed snapshot in src/data/examples/, stamped snapshotAt on refresh via scripts/snapshot-examples.mjs — the build never fetches, so it is deterministic.
- Live refresh
- Upgrades to live in the browser; additionally, imminence (mass) is recomputed every second in-page as T−0 approaches. The committed snapshot is the SSR baseline.
- Not claimed
- The field reads imminence as mass. It does not predict whether a launch will happen on time or succeed — it makes the countdown drive weight in real time.
Fundamental · invisible fields · calendar
The next launch pulls hardest.
A launch schedule lists every mission at the same weight: a rocket lifting off in nineteen hours sits in the same row style as one penciled in for the end of the month. This is the same schedule from Launch Library 2 run as a field: imminence is gravitational mass, and the weight ramps as T−0 approaches — heavier type, darker ink, a stronger left anchor.
This is the one page where the field's input is time itself. The soonest launch is the biggest thing on the wall — a featured "next up" card with the countdown as its centerpiece — and the rest lay out as a day agenda, a seven-column week, or a month grid: three calendar geometries over the same thirty launches. A 1-second clock recomputes every weight and re-picks the featured launch in whichever view is mounted, so when a window passes the wall advances on its own; passed and undated launches drift to a dimmed "unscheduled" cluster. Toggle the field off and the wall flattens — but the countdowns keep ticking, because they're data, not field.
size = imminence — weight ramps as T−0 approaches, recomputed every second · color = launch status — Go is confirmed, TBC awaits confirmation
- Aa size = imminence — the next launch is the biggest thing on the wall
- color = status (Go teal · TBC amber · TBD dim)
- T− the countdown is live — when a window passes, the wall re-picks "next up"
- the ink is live — --w is the clock's imminence and --cat the status lens; --d is the engine's local density (hold a card and the field gathers — the hero's countdown burns brighter) and --field-attention the pattern's eased attention as you scroll.
Next up
Mir | Demo Flight
ADD Offshore launch platform · Sea Launch
Wednesday, November 4UTC
- Mir | Demo FlightT− 16:35:19 TBC LEO
Thursday, November 5UTC
- Long March 2C | Unknown PayloadT− 2d 03:35:19 Go
- Long March 12 | SatNet LEO Group TBD?T− 2d 08:50:19 Go LEO
Friday, November 6UTC
- Ceres-2 | Unknown PayloadT− 3d 11:10:19 Go
Saturday, November 7UTC
- Falcon 9 Block 5 | USSF-432T− 3d 12:21:19 Go LEO
Monday, November 9UTC
- Falcon 9 Block 5 | USSF-xxx ("R-5")T− 5d 14:52:19 TBC LEO
Friday, November 20UTC
- Long March 8A | SatNet LEO Group TBD?T− 16d 22:35:19 TBC LEO
Tuesday, November 24UTC
- Soyuz 2.1b | Progress MS-36 (97P)T− 20d 16:38:19 TBC LEO
- Long March 12 | SatNet LEO Group TBD?T− 20d 18:35:19 TBC LEO
Thursday, November 26UTC
- Spectrum | AT-Astra and Others (Spectrum Flight 3)T− 23d 07:35:19 TBC SSO
Sunday, November 29UTC
- Falcon 9 Block 5 | Cygnus CRS-2 NG-25T− 26d 03:24:19 Go LEO
Unscheduledwindow passed · date TBD
- Electron | The Sea God Surveys (iQPS Launch 9)window passed · snapshot Success LEO
- Kinetica 2 | SpaceSail Polar Group #17window passed · snapshot Success PO
- Vulcan VC6L | Amazon Leo (LV-01)TBD TBD LEO
- Electron | The Mountain God Rises (iQPS Launch 10)TBD TBD LEO
- Ariane 64 Block 2 | Amazon Leo (LE-04)TBD TBD LEO
- Long March 2F/G | Shenzhou 24TBD TBD LEO
- Falcon 9 Block 5 | NROL-195TBD TBD LEO
- Falcon 9 Block 5 | OneWeb 21TBD TBD PO
- Falcon 9 Block 5 | Starlink Group 15-21TBD TBD LEO
- LVM-3 | Gaganyaan-1TBD TBD LEO
- PSLV-XL | TDS-01TBD TBD GTO
- Starship | Flight 15TBD TBD LEO
- Ariane 62 | Metop-SG B1TBD TBD SSO
- Falcon 9 Block 5 | SDA Tranche 2 Transport Layer DTBD TBD PO
- Falcon 9 Block 5 | SDA Tranche 2 Transport Layer ETBD TBD PO
- LVM-3 | GSAT-32 (GSAT-N3)TBD TBD GTO
- New Glenn | Blue Ring-1TBD TBD GTO
- Falcon 9 Block 5 | BlueBird 14-16 (Block 2 #9-11)TBD TBD LEO
- Falcon 9 Block 5 | CHORUSTBD TBD LEO
How it's built
Every launch is an ordinary <li> with its NET timestamp in a data
attribute. A 1-second clock turns distance-to-T−0 into a weight, writes it back as a CSS
custom property, and the type carries the measurement. No canvas, no chart library — the
only moving part is time. On top of the clock sit two live channels the engine writes back
every frame — --d (local density, gathered by data-hot on hover)
and --field-attention (the pattern's eased attention) — which touch only ink;
the 1 Hz weight ramp is untouched. The day / week / month toggle re-renders the records
zone from the same launch list and re-applies the scoped field over the new bodies — full
cards in day, compact cards in week, chips in month — and every channel keeps working.
1 — each launch is a field body
<!-- each launch is a body. data-feedback: the engine writes
--d (live local density) back every frame. data-hot:
hover/focus a card and the field gathers toward it —
hold the hero and its countdown burns brighter. -->
<li
data-body="attract"
data-strength="1.43"
data-feedback
data-hot
data-net="2026-06-11T04:00:00Z"
data-status="Go"
style="--w: 0.646; --cat: #2dd4bf;"
>
<!-- name · provider · countdown -->
</li> data-net— the no-earlier-than instant the clock measures againstdata-strength— gravitational mass, re-set every second--cat— the status color the CSS mixes indata-feedback— opt in to--field-*writebacks (--d)data-hot— hover/focus gathers the field toward this card
2 — one clock, three geometries
// the world-time kernel — 1 at T−0,
// log-ramping from 0 across the horizon:
import { imminence, weightToStrength }
from "@fundamental-engine/core";
// every second, for every launch:
const netMs = Date.parse(row.dataset.net);
const w = netMs > Date.now()
? Math.max(0.08, // the page's floor
imminence(netMs, Date.now(),
30 * 24 * 36e5)) // 30-day horizon
: 0.08; // window passed · snapshot
row.style.setProperty("--w", w);
row.dataset.strength =
weightToStrength(w).toFixed(2);
// the 0.4..2.0 attract-body contract
// the scoped field runs invisible (renderless)
// and asks for the attention metric lane —
// the pipeline writes --field-attention per
// card (eased 0..1):
field = applyPattern(zone, base, {
renderless: true,
extraMetrics: ["attention"],
/* …bodies below */
}); // three geometries, one contract — every
// view renders the same 30 launches
// as the same bodies:
const render =
{ day, week, month }[view];
viewAc?.abort(); // the old view's
viewAc = // listeners die with it
new AbortController();
zone.innerHTML = render(records, now);
// the bodies changed — destroy the
// scoped field and re-apply the pattern
// over the new geometry:
field?.destroy();
const bodies = [
...zone.querySelectorAll("[data-body]"),
hero,
];
field = applyPattern(zone, base, {
bodies,
annotateBodies: false,
renderless: true,
extraMetrics: ["attention"],
});
// the field doesn't care about the
// layout — it measures whatever
// geometry you give it. The soonest launch is the heaviest; as its T−0 approaches the ramp steepens, so the page's center of gravity slides toward the pad. The day / week / month toggle swaps the entire geometry under the same bodies — the field doesn't care about the layout; it measures whatever geometry you give it. That's the lesson of this page.
3 — CSS reads the field's output
.cal-row {
/* --w = imminence (1 Hz clock) · --d = live engine
density, data-hot gathers it · --field-attention =
the pattern's eased attention */
--live: var(--d, 0);
opacity: calc(0.58 + var(--w) * 0.42);
box-shadow: 0 0 calc(var(--live) * 16px) -6px
color-mix(in srgb,
var(--cat) calc(var(--live) * 55%), transparent);
}
/* the rail dot charges with the density */
.cal-row::before {
transform: translateY(-50%)
scale(calc(1 + var(--live) * 0.35));
}
/* hold the hero — the T-minus digits burn brighter */
.cal-hero-count {
text-shadow: 0 0 calc(var(--live) * 18px)
color-mix(in srgb,
var(--cat) calc(var(--live) * 65%), transparent);
}