${esc(T.title)}
${esc(T.place)} · ${esc(T.date)}
diff --git a/mobile/vision/index.html b/mobile/vision/index.html
index f08b7dd12..e45c79f63 100644
--- a/mobile/vision/index.html
+++ b/mobile/vision/index.html
@@ -307,7 +307,7 @@ input, textarea { font: inherit; color: inherit; }
.compose .in input { flex: 1; background: none; border: 0; outline: none; color: var(--text); font-size: 15px; min-width: 0; }
/* ---------- capture ---------- */
-#v-capture { background: #000; z-index: 25; }
+#v-capture { background: transparent; z-index: 25; }
#v-capture.on { display: block; }
.cap-ui { position: absolute; inset: 0; pointer-events: none; }
.cap-ui > * { pointer-events: auto; }
@@ -320,7 +320,7 @@ input, textarea { font: inherit; color: inherit; }
.callout span { color: var(--text2); font-size: 11px; }
.callout .ci { width: 28px; height: 28px; border-radius: 9px; display: grid; place-items: center; background: color-mix(in oklab, var(--c) 22%, transparent); color: var(--c); }
.reticle { position: absolute; width: 34px; height: 34px; margin: -17px 0 0 -17px; border: 1.5px solid var(--c, #fff); border-radius: 10px; pointer-events: none; box-shadow: 0 0 12px var(--c); }
-.cap-bottom { position: absolute; left: 0; right: 0; bottom: 0; padding: 10px 16px calc(var(--sab) + 18px); display: flex; flex-direction: column; align-items: center; gap: 14px; background: linear-gradient(to top, rgba(0,0,0,.55), transparent); }
+.cap-bottom { position: absolute; left: 0; right: 0; bottom: 0; padding: 10px 16px calc(var(--sab) + var(--tabH) + 26px); display: flex; flex-direction: column; align-items: center; gap: 14px; background: linear-gradient(to top, rgba(0,0,0,.55), transparent); }
.zooms { display: flex; gap: 6px; padding: 4px; border-radius: 22px; }
.zooms button { width: 36px; height: 36px; border-radius: 50%; font-size: 12px; font-weight: 700; color: var(--text2); }
.zooms button.on { background: rgba(255,255,255,.14); color: var(--warn); }
@@ -334,7 +334,7 @@ input, textarea { font: inherit; color: inherit; }
.shutter:active i { transform: scale(.88); }
.lastcap { width: 48px; height: 48px; border-radius: 12px; background: #111 center/cover; box-shadow: inset 0 0 0 1px rgba(255,255,255,.2); position: relative; }
.lastcap .seal { position: absolute; right: -6px; top: -6px; width: 20px; height: 20px; }
-.sensors { position: absolute; left: 12px; bottom: calc(var(--sab) + 210px); border-radius: 16px; padding: 8px 10px; font-size: 11px; display: none; gap: 3px; flex-direction: column; min-width: 158px; color: var(--text2); }
+.sensors { position: absolute; left: 12px; bottom: calc(var(--sab) + var(--tabH) + 236px); border-radius: 16px; padding: 8px 10px; font-size: 11px; display: none; gap: 3px; flex-direction: column; min-width: 158px; color: var(--text2); }
.sensors.on { display: flex; }
.sensors b { color: var(--text); font-variant-numeric: tabular-nums; font-weight: 600; }
.sensors svg { width: 140px; height: 26px; }
@@ -351,7 +351,7 @@ input, textarea { font: inherit; color: inherit; }
.step .ck { width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; box-shadow: inset 0 0 0 1.5px var(--text3); color: transparent; transition: all .3s; }
.step.done .ck { background: var(--gold); box-shadow: none; color: #1A1408; }
.step b { font-weight: 600; } .step .h { font-family: var(--mono); font-size: 11px; color: var(--text2); word-break: break-all; line-height: 1.35; margin-top: 2px; }
-.step svg { width: 100%; height: 30px; margin-top: 4px; }
+.step svg.trace { width: 100%; height: 30px; margin-top: 4px; display: block; }
.btnrow { display: flex; gap: 8px; }
.btn { flex: 1; height: 50px; border-radius: 25px; font-weight: 700; font-size: 15px; display: inline-flex; align-items: center; justify-content: center; gap: 7px; background: rgba(255,255,255,.1); box-shadow: inset 0 0 0 .5px rgba(255,255,255,.12); }
.btn.gold { background: linear-gradient(180deg, #F3D68A, #D9AE4F); color: #1C1405; box-shadow: inset 0 .5px 0 rgba(255,255,255,.6); }
@@ -377,7 +377,7 @@ input, textarea { font: inherit; color: inherit; }
.ws .wsh > * { pointer-events: auto; }
.ws .wsh .tt { flex: 1; min-width: 0; height: 44px; border-radius: 22px; display: flex; align-items: center; gap: 10px; padding: 0 8px 0 14px; }
.ws .wsh .tt b { font-size: 14.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
-.ws .wsh .tt span { font-size: 11.5px; color: var(--text2); }
+.ws .wsh .tt span { font-size: 11.5px; color: var(--text2); display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ws .body { position: absolute; left: 0; right: 0; bottom: 0; top: 40%; border-radius: 28px 28px 0 0; display: flex; flex-direction: column; overflow: hidden; }
.ws .seg { display: flex; margin: 12px 14px 8px; padding: 3px; border-radius: 12px; background: rgba(255,255,255,.07); flex: none; }
.ws .seg button { flex: 1; height: 34px; border-radius: 9px; font-size: 13px; font-weight: 600; color: var(--text2); transition: all .25s; }
@@ -391,7 +391,7 @@ input, textarea { font: inherit; color: inherit; }
.obs .ot { font-size: 14px; font-weight: 600; line-height: 1.3; }
.obs .om { font-size: 11.5px; color: var(--text3); margin-top: 3px; display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; }
.obs .om .mono { color: var(--text2); }
-.obs .tagid { font-family: var(--mono); font-size: 11px; color: var(--gold2); background: rgba(233,196,106,.12); padding: 1px 6px; border-radius: 6px; }
+.tagid { display: inline-block; font-family: var(--font); font-weight: 700; font-size: 11px; letter-spacing: .02em; color: var(--gold2); background: rgba(233,196,106,.13); box-shadow: inset 0 0 0 .5px rgba(233,196,106,.35); padding: 2px 7px; border-radius: 7px; line-height: 1.3; }
.hyp { border-radius: 20px; padding: 13px 14px; margin: 0 0 10px; background: var(--card2); box-shadow: inset 0 0 0 .5px rgba(255,255,255,.08); }
.hyp.ai { box-shadow: inset 0 0 0 1px rgba(183,156,255,.45); background: linear-gradient(180deg, rgba(183,156,255,.10), rgba(183,156,255,.02)), var(--card2); }
.hyp .hh { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text2); }
@@ -500,7 +500,9 @@ input, textarea { font: inherit; color: inherit; }
.cold .eye { width: 60px; height: 60px; margin-bottom: 18px; opacity: 0; transition: opacity 1.2s; color: #fff; }
.cold.s2 .eye { opacity: .95; }
.concept-tag { position: absolute; z-index: 90; left: 14px; top: calc(var(--sat) + 58px); pointer-events: none; font-size: 9.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: rgba(246,223,160,.72); padding: 3px 7px; border-radius: 6px; background: rgba(10,12,18,.35); box-shadow: inset 0 0 0 .5px rgba(233,196,106,.3); }
-.app[data-tab="now"] .concept-tag, .app[data-tab="threads"] .concept-tag, .app[data-tab="you"] .concept-tag { top: calc(var(--sat) + 14px); left: auto; right: 14px; }
+.app[data-tab="now"] .concept-tag { top: calc(var(--sat) + 14px); left: auto; right: 14px; }
+.app[data-tab="threads"]:not([data-mode="workspace"]) .concept-tag, .app[data-tab="you"] .concept-tag { display: none; }
+.app[data-mode="workspace"] .concept-tag { top: calc(var(--sat) + 62px); left: auto; right: 14px; }
.app[data-tab="capture"] .concept-tag { top: calc(var(--sat) + 100px); left: 14px; }
.app[data-mode="situation"] .concept-tag { left: auto; right: 14px; top: calc(var(--sat) + 62px); }
@@ -1407,7 +1409,7 @@ vec3 aurora(vec3 n, float nightF){
float curt = 0.45 + 0.55*fbm(vec2(lonm*9. + uT*0.0006, uT*0.00025));
float g = exp(-pow((ml-band)/(2.2+uAurora*0.6), 2.)) * curt;
float r = exp(-pow((ml-band-3.5)/3.5, 2.)) * 0.25;
- return (vec3(0.12, 1.0, 0.5)*g + vec3(0.75, 0.15, 0.45)*r*0.45) * nightF * uAurora * 1.15;
+ return (vec3(0.12, 1.0, 0.5)*g + vec3(0.75, 0.15, 0.45)*r*0.45) * nightF * uAurora * 0.75;
}
vec3 cityDetail(vec3 base, vec2 q, float urban, float night, float fw, out vec3 emis){
emis = vec3(0.);
@@ -1437,7 +1439,7 @@ vec3 cityDetail(vec3 base, vec2 q, float urban, float night, float fw, out vec3
if (uTraffic > 0.5) {
vec2 rp = p/B; float along = abs(f.x-0.5) < abs(f.y-0.5) ? rp.y : rp.x;
float cars = smoothstep(0.75, 1., sin(along*38. - uT*2.5 + h*20.)) * road * urban * (1.-aa);
- emis += mix(vec3(1.,0.15,0.1), vec3(1.,0.95,0.8), step(0.5, fract(along*3.)))*cars*(0.25 + night*1.4);
+ emis += mix(vec3(1.,0.15,0.1), vec3(1.,0.95,0.8), step(0.5, fract(along*3.)))*cars*(0.03 + night*1.2);
}
float lit = step(0.72, hash12(id*3.1)) * (1.-road) * urban * night;
emis += vec3(0.9,0.8,0.6)*lit*0.035;
@@ -1565,7 +1567,7 @@ void main(){
float tc = -b; vec3 cp = ro + rd*max(tc,0.); float hr = length(cp);
if (uAurora > 0. && hr > 1.004 && hr < 1.05) {
vec3 cn = normalize(cp); float nf = 1.-smoothstep(-0.2,0.0,dot(cn,uSun));
- col += aurora(cn, nf) * smoothstep(1.05,1.012,hr) * smoothstep(1.004,1.012,hr) * 0.3;
+ col += aurora(cn, nf) * smoothstep(1.05,1.012,hr) * smoothstep(1.004,1.012,hr) * 0.12 * smoothstep(1.5, 0.4, uRange);
}
heat = 0.;
}
@@ -1849,8 +1851,8 @@ void main(){
vec3 base; vec3 emis = vec3(0.); float heat = 0.35; float spec = 0.;
if (type == 0) { // building
float h = vAttr.y;
- base = mix(vec3(0.34,0.35,0.37), vec3(0.62,0.57,0.5), h);
- base = mix(base, vec3(0.2,0.25,0.3), step(0.7, h)); // glass towers
+ base = mix(vec3(0.15,0.155,0.165), vec3(0.32,0.29,0.25), fract(h*7.13));
+ base = mix(base, vec3(0.07,0.09,0.11), step(0.68, h)); // glass towers
if (abs(n.z) < 0.5) {
vec2 f = vec2(vUV.x/3.2, vUV.y/3.6);
vec2 id = floor(f); vec2 fr = fract(f);
@@ -1860,7 +1862,7 @@ void main(){
vec3 wc = mix(vec3(1.0,0.72,0.42), vec3(0.75,0.85,1.0), step(0.6, hash12(id*1.3+h)));
emis += wc * lit * (0.9 + 0.6*r) * uNight * 2.2;
base = mix(base, base*0.45 + uSkyCol*0.08, win*0.8);
- spec = win*(1.-uNight)*0.6;
+ spec = win*(1.-uNight)*0.9 + step(0.68, h)*0.5;
} else base *= 0.82;
float ao = smoothstep(0., 14., vUV.y + (1.-abs(n.z))*0.) * 0.35 + 0.65;
if (abs(n.z) < 0.5) base *= ao;
@@ -2164,10 +2166,10 @@ W.layers = [
L('holo', 'eyes', 'Holograms', true, 'cube'), L('streams', 'eyes', 'Live streams', false, 'live'),
L('transit', 'ground', 'Transit vehicles', false, 'tram'), L('traffic', 'ground', 'Traffic flow', true, 'car'), L('bikes', 'ground', 'Bike share', false, 'bike'),
L('rail', 'ground', 'Rail', false, 'rail'), L('venues', 'ground', 'Events & venues', true, 'ticket'), L('alpr', 'ground', 'ALPR cameras', false, 'plate'),
- L('radar', 'wx', 'Radar', true, 'radar'), L('clouds', 'wx', 'Clouds', true, 'cloud'), L('lightning', 'wx', 'Lightning', true, 'bolt'),
+ L('radar', 'wx', 'Radar', false, 'radar'), L('clouds', 'wx', 'Clouds', true, 'cloud'), L('lightning', 'wx', 'Lightning', true, 'bolt'),
L('wind', 'wx', 'Wind', false, 'wind'), L('models', 'wx', 'Forecast models', false, 'spaghetti'),
L('dc', 'infra', 'Datacenters', false, 'server'), L('dams', 'infra', 'Dams', false, 'dam'), L('power', 'infra', 'Power plants', false, 'bolt'),
- L('milbase', 'infra', 'Military installations', false, 'shield'), L('gnss', 'infra', 'GNSS interference', true, 'jam'), L('imagery', 'infra', 'Recent satellite imagery', false, 'frame'),
+ L('milbase', 'infra', 'Military installations', false, 'shield'), L('gnss', 'infra', 'GNSS interference', false, 'jam'), L('imagery', 'infra', 'Recent satellite imagery', false, 'frame'),
];
W.layerById = Object.fromEntries(W.layers.map((l) => [l.id, l]));
W.on = (id) => !!W.layerById[id]?.on;
@@ -2440,7 +2442,7 @@ W.updateDynamic = function () {
GE.SHIPS.forEach((s, i) => {
const p = W._shipCache[i]; const tank = s.kind === 'tanker' || s.kind === 'LNG';
if (!showAis && !tank) return;
- const ak = clamp(lerp(0.32, 0.95, smooth(1.2, 0.08, W.lastRange ?? 1)), 0.3, 1);
+ const ak = clamp(lerp(0.16, 0.95, smooth(1.4, 0.08, W.lastRange ?? 1)), 0.16, 1);
const col = showTk && tank ? [1, 0.7, 0.35, ak] : s.queue ? [0.5, 1, 0.9, ak] : [0.22, 0.88, 0.78, ak * 0.95];
pushSpr(a, geo.vec(p.lat, p.lon, 0.03), col, (showTk && tank ? 10 : 8.5), 4, p.hdg, -1e9, 1e9, 0, i, 0.35);
});
@@ -2536,6 +2538,7 @@ W.project = function (view, p) { // world unit coords → css px {x,y,z,vis}
/* ---------- render ---------- */
W.quality = { scale: 1, steps: 12, bloom: true, grain: true };
+const LOD_MIN = { radar: 0.12 };
const LOD = { cctv: 0.07, street: 0.03, alpr: 0.035, bikes: 0.04, streams: 0.4, signed: 0.6, venues: 0.9, power: 0.7, dc: 1.6, dams: 1.6, milbase: 1.6, airports: 1.3, ports: 1.4, imagery: 1.6, fishing: 2.2, radar: 1.6 };
W.render = function (view, chain, outFb, opts = {}) {
const gl = GL.gl, PR = GL.progs;
@@ -2634,7 +2637,7 @@ W.render = function (view, chain, outFb, opts = {}) {
// alpha pass (smoke, AQ, radar, GNSS, cone)
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE);
common(SP); gl.uniform1f(SP.u.uPass, 1);
- for (const id in W.static) if (W.on(id) && range < (LOD[id] || 99)) for (const s of W.static[id]) if (s.kind === 'sprite' && s.pass === 'alpha') { gl.bindVertexArray(s.vao); gl.drawArrays(gl.POINTS, 0, s.count); }
+ for (const id in W.static) if (W.on(id) && range < (LOD[id] || 99) && range > (LOD_MIN[id] || 0)) for (const s of W.static[id]) if (s.kind === 'sprite' && s.pass === 'alpha') { gl.bindVertexArray(s.vao); gl.drawArrays(gl.POINTS, 0, s.count); }
if (W.alphaVao && W.alphaCount) { gl.bindVertexArray(W.alphaVao); gl.drawArrays(gl.POINTS, 0, W.alphaCount); }
gl.disable(gl.BLEND); gl.disable(gl.DEPTH_TEST); gl.depthMask(true);
gl.bindVertexArray(null);
@@ -2934,7 +2937,7 @@ SC.draw = function (sc, view, { sun, t, eye, opts }) {
const clear = (opts.lens || GE.world.lens) === 'clear';
gl.uniform3fv(P.u.uSunCol, clear ? [2.2, 2.2, 2.2] : tr.map((x) => x * k * (opts.nightForce ? 0.03 : 1)));
const amb = smooth(-0.25, 0.5, sunL[2]);
- gl.uniform3fv(P.u.uSkyCol, clear ? [1.2, 1.25, 1.35] : [0.03 * 20 / Math.PI * 1.6 * amb + 0.014, 0.045 * 20 / Math.PI * 1.6 * amb + 0.02, 0.085 * 20 / Math.PI * 1.6 * amb + 0.04]);
+ gl.uniform3fv(P.u.uSkyCol, clear ? [1.2, 1.25, 1.35] : [0.03 * 20 / Math.PI * 0.9 * amb + 0.014, 0.045 * 20 / Math.PI * 0.9 * amb + 0.02, 0.085 * 20 / Math.PI * 0.9 * amb + 0.04]);
// fog colour: inscatter along the horizon in the camera's look direction
const fwd = v3.scale(view.back, -1); const fh = v3.norm(v3.madd(fwd, e.up, -v3.dot(fwd, e.up))); const ro = v3.madd(o, e.up, 0.0003);
let fog = atmoJS(ro, fh, 0.012, sd, 8); fog = fog.map((x) => x * 0.8 + 0.0015);
@@ -3195,7 +3198,7 @@ add({
id: 'cyclone', short: 'Typhoon Halcyon', fam: 'haz', kind: 'cyclone', section: 'now', live: true, aspect: 1.25, ageS: 120, watchers: 48200,
title: 'Typhoon Halcyon tracks toward Luzon Strait', place: 'Philippine Sea', lat: 16.2, lon: 128.8,
camera: { lat: 15.2, lon: 127.6, range: 0.42, heading: -0.25, tilt: 0.42 }, thumbCam: { lat: 16.6, lon: 128.4, range: 0.3, heading: -0.2, tilt: 0.36 },
- layers: ['cyclones', 'radar', 'lightning', 'clouds', 'models', 'ais', 'flights'], source: 'Advisory feed (illustrative)',
+ layers: ['cyclones', 'lightning', 'clouds', 'models', 'ais', 'flights'], source: 'Advisory feed (illustrative)',
metric: () => { const c = GE.CYCLONE.at(GE.world.offsetH); return [`${Math.round(c.wind)}km/h`, `${Math.round(c.p)} hPa · moving WNW 19 km/h`]; },
metrics: () => { const c = GE.CYCLONE.at(GE.world.offsetH); return [{ v: Math.round(c.wind), u: 'km/h', l: 'Max sustained', s: 'Advisory · 2 min' }, { v: Math.round(c.p), u: 'hPa', l: 'Central pressure', s: 'Advisory · 2 min' }, { v: 610, u: 'km', l: 'To Luzon Strait', s: 'Computed · now' }]; },
accessory: () => { const c = GE.CYCLONE.at(GE.world.offsetH); return `${Math.round(c.wind)} km/h · ${Math.round(c.p)} hPa · updated 2 min ago`; },
@@ -3263,7 +3266,7 @@ add({
add({
id: 'novosel', short: 'Fort Novosel circuits', fam: 'sky', kind: 'heli', section: 'always', live: true, aspect: 1.5, ageS: 15, watchers: 3100, ride: true,
title: 'Fort Novosel helicopter school — jump into the chopper', place: 'Cairns Army Airfield, Alabama', lat: 31.276, lon: -85.713,
- camera: { lat: 31.268, lon: -85.705, range: 0.0019, heading: -0.6, tilt: 1.12 }, layers: ['helis', 'flights', 'ga', 'traffic'], source: 'ADS-B / MLAT', time: dayReplay(31.276, -85.713, 15.2),
+ camera: { lat: 31.2705, lon: -85.7075, range: 0.0011, heading: -0.65, tilt: 1.15 }, layers: ['helis', 'flights', 'ga', 'traffic'], source: 'ADS-B / MLAT', time: dayReplay(31.276, -85.713, 15.2),
metric: () => [`${GE.HELI_CIRCUITS.filter((h) => h.field).length}in circuits`, 'Cairns + 3 stagefields · 500 ft AGL'],
metrics: () => [{ v: GE.HELI_CIRCUITS.filter((h) => h.field).length, u: '', l: 'Helicopters in circuits', s: 'ADS-B · 15 s' }, { v: 500, u: 'ft', l: 'Pattern altitude', s: 'Observed' }, { v: 5.5, u: 'min', l: 'Circuit time', s: 'Derived' }],
brief: { lede: 'Student pilots are flying rectangular traffic patterns at Cairns and three stagefields: upwind, crosswind, downwind, base, final — over and over. Tap Ride to sit in the left seat of one of them.', series: [{ label: 'Helicopters aloft', unit: '', data: [2, 4, 9, 14, 17, 19, 19, 18, 19, 17, 19, 19], src: 'ADS-B / MLAT · hourly · 15 s', fmt: (v) => v }, { label: 'Groundspeed, HAWK 21', unit: 'kt', data: Array.from({ length: 40 }, (_, i) => 70 + 12 * Math.sin(i / 3.2) + (i % 10 > 7 ? -30 : 0)), src: 'ADS-B · 1 s · 15 s', fmt: (v) => Math.round(v) }], sources: [['ADS-B / MLAT', '15 s', 'live']] },
@@ -3431,8 +3434,8 @@ APP.minimize = function (on) {
};
APP.showAcc = () => !!APP.following && (APP.tab === 'now' || APP.tab === 'threads' || APP.tab === 'you' || (APP.isWide() && APP.tab === 'globe')) && !APP.mode;
APP.updateChrome = function () {
- const ride = APP.mode === 'ride', sit = APP.mode === 'situation';
- $('#tabwrap').classList.toggle('hidden', ride || (sit && !APP.isWide()) || APP.intro);
+ const ride = APP.mode === 'ride', sit = APP.mode === 'situation', wsm = APP.mode === 'workspace';
+ $('#tabwrap').classList.toggle('hidden', ride || ((sit || wsm) && !APP.isWide()) || APP.intro);
$('#accHost').classList.toggle('hidden', !APP.showAcc() || APP._mini || APP.intro);
$('#back').classList.toggle('on', sit);
$('#sitbtns').classList.toggle('on', sit);
@@ -3734,12 +3737,12 @@ SH.open = function (id, o = {}) {
if (o.ride && s.ride) setTimeout(() => GE.ride.start({ kind: 'heli', id: 0 }), 650);
APP.updateChrome();
};
-SH.close = function (silent) {
+SH.close = function (silent, keepTime) {
if (!SH.id) return; const id = SH.id; const W = GE.world;
const el = sheetEl(); el.classList.remove('drag', 'wopen'); el.style.transform = APP.isWide() ? '' : 'translateY(100%)';
SH.id = null; W.focus = null; GE.setExtras && GE.setExtras(null);
if (SH._savedLayers) { W.layers.forEach((l, i) => (l.on = SH._savedLayers[i])); SH._savedLayers = null; bus.emit('layers', W.layers); }
- W.setWindow(null); W.setTime(null); W.auroraK = 0.85;
+ if (!keepTime) { W.setWindow(null); W.setTime(null); } W.auroraK = 0.85;
APP.setMode('');
if (silent) return;
const fromNow = !APP.isWide() && GE.now && $(`#v-now .card[data-id="${id}"]`);
@@ -4129,7 +4132,7 @@ const CHAT_JET = [
];
RIDE.start = function (p) {
const W = GE.world;
- if (APP.mode === 'situation') { GE.sheet.close(true); }
+ if (APP.mode === 'situation') { GE.sheet.close(true, true); }
RIDE.p = p; RIDE.on = true; RIDE.yaw = 0; RIDE.pitch = 0; RIDE.zoom = 1;
if (APP.tab !== 'globe') { APP.tab = 'globe'; $('#app').dataset.tab = 'globe'; $$('.pane .view').forEach((v) => v.classList.remove('on')); }
APP.setMode('ride');
@@ -4185,7 +4188,7 @@ RIDE.frame = function (view) {
g += ``;
g += `
${esc(T.place)} · ${esc(T.date)}
Concept · illustrative data. Witness posts, handles and claims are fictional.
${esc(T.place)} · ${esc(T.date)}
Concept · illustrative data. Witness posts, handles and claims are fictional.