Wait for each frame while the world timeline plays, and quiet the bar

Play no longer runs ahead of the data. The world clock gains a wait, which
holds continuous play where it is while a layer loads what the time needs,
and a gate, which keeps play from passing a time a layer has yet to load.
Weather gates play at its next frame and waits there until the frame shows,
so every frame is seen however fast play runs; it waits no more than eight
seconds on a frame that never comes, and takes a wait only when its frames
change. Play pressed while a frame loads waits for it too. A scrub still
drops what loads and moves on.

The bar loses its long date and the dates at its ends: the time rides in a
bubble over the handle, which pulses while play waits, and the bar runs
left to right in every language. Play starts at real time.
This commit is contained in:
Sameh Khamis committed 2026-11-02 08:03:46 -08:00
1 parent d04e304502
commit 056b3b58c6
9 files changed
+357 -40

No files matched your search

+45 -23
View File
@@ -5,8 +5,9 @@
--world-timeline-lift: 0px;
}
/* The bar and the time's bubble over its handle. */
body:has(#world-timeline) {
--world-timeline-lift: 50px;
--world-timeline-lift: 66px;
}
/* Clean view, recording and the cockpit put the dock away; the bar goes too. */
@@ -22,7 +23,10 @@ body.cockpit-mode #world-timeline {
display: none;
}
/* Time runs left to right in every language, so the handle, the fill, the
ticks and the bubble agree under a right-to-left page too. */
#world-timeline {
direction: ltr;
position: fixed;
bottom: 2vh;
left: 50%;
@@ -81,21 +85,43 @@ body.cockpit-mode #world-timeline {
flex: none;
}
/* The time rides over the handle. It slides across itself as the handle
crosses the track (its start at the handle at the track's start, its end at
the end), so however wide its date it stays within the track. */
#world-timeline .world-timeline-time {
overflow: hidden;
font-family: var(--font-mono);
font-size: 13px;
font-variant-numeric: tabular-nums;
text-overflow: ellipsis;
white-space: nowrap;
}
#world-timeline .world-timeline-edge {
flex: none;
color: var(--text-secondary);
--inset: 0px;
position: absolute;
bottom: calc(100% + 6px);
left: calc(var(--inset) + (100% - var(--inset)) * var(--at));
padding: 2px 8px;
border: 1px solid rgba(0, 212, 255, 0.4);
border-radius: 6px;
background: var(--glass-bg);
color: var(--text-primary);
font-family: var(--font-mono);
font-size: 11px;
font-variant-numeric: tabular-nums;
white-space: nowrap;
transform: translateX(calc(var(--at) * -100%));
pointer-events: none;
}
/* Playing, held while a layer loads the time's data. */
#world-timeline .world-timeline-time.is-buffering {
animation: world-timeline-buffering 1s ease-in-out infinite alternate;
}
@keyframes world-timeline-buffering {
to {
opacity: 0.45;
}
}
@media (prefers-reduced-motion: reduce) {
#world-timeline .world-timeline-time.is-buffering {
animation: none;
opacity: 0.6;
}
}
/* The track: ticks for each launch or frame, the elapsed fill, and a native
@@ -194,7 +220,7 @@ body.cockpit-mode #world-timeline {
}
/* On phones the bar sits just above the tab bar, under the voice dock, with
the track on a row of its own beneath play, the time and live. */
the track and the speed on a row of their own beneath play and live. */
body.mobile-shell:has(#world-timeline) {
--world-timeline-lift: 80px;
}
@@ -206,8 +232,9 @@ body.mobile-shell #world-timeline {
height: auto;
}
/* The bubble rises into the first row, clear of play on its left. */
body.mobile-shell #world-timeline .world-timeline-time {
flex: 1 1 0;
--inset: 48px;
}
/* The speed sits on the track's row, a full-size target beside it. */
@@ -216,17 +243,12 @@ body.mobile-shell #world-timeline .world-timeline-track {
flex: 1 1 calc(100% - 96px);
}
body.mobile-shell #world-timeline .world-timeline-live {
margin-inline-start: auto;
}
body.mobile-shell #world-timeline .world-timeline-speed {
order: 2;
height: 32px;
}
@media (max-width: 640px) {
#world-timeline .world-timeline-edge {
display: none;
}
#world-timeline .world-timeline-time {
font-size: 11px;
}
}