feat(mobile): rooms, live and upload capture, and the altitude-band identity

The Now feed mixes sensor, eye, track, number, witness and room cards
across Orbit, Sky, Ground and Inside, ordered so neighbours differ, with
composited thumbnails and live public-camera frames.

Every situation has a room: typed, place- and time-anchored posts,
evidence badges, bridging-rated notes and a cited Known / Disputed /
Unknown local synthesis, with cross-tab presence over BroadcastChannel.
Example posts are labelled as such.

Capture adds Live (10 s segments sealed into a hash chain, shown on the
globe as a view frustum) and Upload (EXIF placement, Unverified tier),
and an attach sheet that files any capture into a nearby situation.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VVYRAqiQj9Y1V9ZfG1RcDH
This commit is contained in:
Claude committed 2026-10-19 02:49:03 +00:00
1 parent ba1673a6db
commit 8b7fcb09df
38 files changed
+9837 -1081

No files matched your search

+9 -1
View File
@@ -141,7 +141,7 @@ export function createTimeRibbon(parent, { getWindow, onTime }) {
if (!custom) {
const xn = x(n);
if (xn > -10 && xn < W + 10) {
ctx.fillStyle = '#FF453A';
ctx.fillStyle = '#FFFFFF';
ctx.beginPath();
ctx.arc(xn, mid + 13, 2.4, 0, Math.PI * 2);
ctx.fill();
@@ -392,6 +392,14 @@ export function createTimeRibbon(parent, { getWindow, onTime }) {
}
resize();
},
/** Animate to a moment and tell the globe (post anchors). */
scrubTo(ms) {
const lo = start();
const hi = end();
const target = Math.min(hi, Math.max(lo, ms));
setLive(false);
animateTo(target, () => emit());
},
/** Programmatic scrub (narrative playback). */
seek(ms) {
cancelAnimationFrame(raf);