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

+198
View File
@@ -806,3 +806,201 @@
.brief-sheet .sheet-head {
padding-bottom: 4px;
}
/* ------------------------------------------------------------------ */
/* Round two: instrument chrome over the globe */
/* ------------------------------------------------------------------ */
.gc-readout {
height: auto;
min-height: 44px;
padding: 7px 11px 7px 10px;
border-radius: 6px;
background: rgba(5, 6, 7, 0.66);
-webkit-backdrop-filter: blur(16px);
backdrop-filter: blur(16px);
box-shadow: inset 0 0 0 0.5px var(--hairline-strong);
gap: 3px;
}
.gc-alt {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 0.6875rem;
font-weight: 600;
color: var(--band, var(--ink));
}
.gc-alt i {
width: 6px;
height: 6px;
border-radius: 1px;
background: var(--band, var(--ink));
}
.gc-ll {
font-size: 0.5625rem;
color: var(--ink-2);
}
.gc-buttons .icon-btn.glass-strong,
.world-back.glass-strong {
border-radius: 10px;
background: rgba(5, 6, 7, 0.66);
box-shadow: inset 0 0 0 0.5px var(--hairline-strong);
}
.gc-buttons .liquid::after,
.world-back.liquid::after {
display: none;
}
.gc-attr {
font-family: var(--mono);
font-size: 0.5rem;
letter-spacing: 0.04em;
top: calc(var(--safe-t) + 62px);
}
/* Altimeter rail */
.alt-rail {
position: absolute;
right: calc(14px + var(--safe-r));
top: calc(var(--safe-t) + 190px);
height: min(34vh, 260px);
width: 64px;
pointer-events: auto;
}
.alt-rail::before {
content: '';
position: absolute;
right: 6px;
top: 0;
bottom: 0;
width: 1px;
background: linear-gradient(
to bottom,
var(--b-orbit) 0 40%,
var(--b-sky) 40% 72%,
var(--b-ground) 72% 100%
);
opacity: 0.55;
}
.alt-ticks i {
position: absolute;
right: 3px;
top: var(--y);
width: 7px;
height: 1px;
background: var(--ink-3);
}
.alt-rail [data-alt] {
position: absolute;
right: 14px;
top: var(--y);
transform: translateY(-50%);
min-height: 32px;
padding: 0 2px;
color: var(--ink-3);
}
.alt-rail [data-alt] span {
display: inline-block;
padding: 2px 4px;
border-radius: 2px;
background: rgba(5, 6, 7, 0.62);
font-size: 0.5rem;
}
.alt-rail[data-band='orbit'] [data-alt='orbit'],
.alt-rail[data-band='sky'] [data-alt='sky'],
.alt-rail[data-band='ground'] [data-alt='ground'] {
color: var(--band);
}
.alt-mark {
position: absolute;
right: 0;
top: var(--h, 0%);
transform: translateY(-50%);
transition: top 300ms var(--ease-out);
}
.alt-mark i {
display: block;
width: 0;
height: 0;
border: 5px solid transparent;
border-right: 7px solid var(--band, var(--ink));
filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.8));
}
.app.is-world .alt-rail {
display: none;
}
/* Family chips as instrument keys */
.fam-chip {
border-radius: 6px;
height: 36px;
background: rgba(5, 6, 7, 0.7);
box-shadow: inset 0 0 0 0.5px var(--hairline-strong);
font-size: 0.8125rem;
}
.fam-chip.on {
background: rgba(5, 6, 7, 0.82);
box-shadow:
inset 0 0 0 0.5px var(--hairline-strong),
inset 0 -2px 0 var(--fam);
}
.fam-count {
font-family: var(--mono);
font-weight: 500;
font-size: 0.625rem;
}
/* Ribbon: white is time, not alarm. */
.ribbon {
border-radius: 10px;
background: rgba(5, 6, 7, 0.72);
box-shadow: inset 0 0 0 0.5px var(--hairline-strong);
}
.ribbon.liquid::after {
display: none;
}
.rb-live {
border-radius: 6px;
font-family: var(--mono);
font-weight: 600;
}
.rb-live.is-live {
background: rgba(255, 255, 255, 0.12);
color: #fff;
}
.rb-live.is-live .live-dot {
--fam: #fff;
}
.ribbon.is-live .rb-head {
background: #fff;
box-shadow: 0 0 10px rgba(255, 255, 255, 0.6);
}
.rb-head {
background: var(--b-inside);
box-shadow: 0 0 10px rgba(235, 199, 119, 0.7);
}
.gc-labels span {
border-radius: 3px;
}