Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@ The background is your actual sky, computed in the browser:
- **Controls**: the `▶︎ 24h` chip plays the whole day as a time-lapse;
the `sky:` chip pins day or night (persisted in localStorage) for
anyone who'd rather not read on a sunset. The status line and the
browser's own chrome follow along: every repaint rewrites a
`theme-color` meta tag with the horizon's computed chip color, so
mobile Safari's toolbar tints to match the sky instead of keeping
whatever it sampled at load. In the dev console,
`__skyAt('2026-07-16T20:30')` previews any moment.
browser's own chrome follow along: every repaint rewrites a pair of
`theme-color` meta tags (one per light/dark color scheme — iOS Safari
ignores a bare one in dark mode and shows grey chrome) with the
horizon's computed chip color, so mobile Safari's toolbar tints to
match the sky instead of keeping whatever it sampled at load. In the
dev console, `__skyAt('2026-07-16T20:30')` previews any moment.

The page paints immediately with the fallback sky, then refines once
the geo lookup resolves, and re-renders every minute.
Expand Down
16 changes: 12 additions & 4 deletions src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@ const ogImage = new URL('/og.png', Astro.site);
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content={description} />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<!-- Tints mobile browser chrome (Safari's toolbar) to match the sky.
Starts at the midnight chip fallback; sky.ts rewrites it on every
render so the tint tracks day/night, including manual switches. -->
<meta name="theme-color" content="oklch(23.43% 0.067 272.85deg)" />
<!-- Tints mobile browser chrome (Safari's toolbar) to match the sky;
sky.ts rewrites both on every render so the tint tracks
day/night, including manual switches. Two media-gated metas, not
one: iOS Safari treats a bare theme-color as a light-mode
suggestion and falls back to its own neutral grey chrome in dark
mode unless a dark-scheme variant exists. Content stays plain
hex/rgb — Safari's theme-color parser rejects oklch(), and a
rejected value also lands on the default grey. The fallback is
the pre-render midnight chip (the hex twin of
--color-chip-bg-fallback). -->
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#141a3d" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#141a3d" />
<title>{title}</title>

<!-- Link previews (LinkedIn, Slack, iMessage, X): without these a
Expand Down
9 changes: 6 additions & 3 deletions src/scripts/sky.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,9 +530,12 @@ function render(place: Place, mode: Mode, at = new Date(), demo = false) {
}

// Mobile browser chrome (Safari's toolbar tint) follows the horizon's
// settled chip color. Without this, Safari samples the page once at
// load and keeps that tint after a manual day/night switch (issue #60).
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', css(chip.bg));
// settled chip color. Both metas — Safari picks the one matching the
// device's light/dark scheme and ignores the other, so each must carry
// the current sky (issue #60).
for (const meta of document.querySelectorAll('meta[name="theme-color"]')) {
meta.setAttribute('content', css(chip.bg));
}

// The stars come out as the sun drops below civil twilight.
const starOpacity = altDeg <= -12 ? 1 : altDeg >= -6 ? 0 : (-altDeg - 6) / 6;
Expand Down
7 changes: 7 additions & 0 deletions src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ body {
min-height: 100dvh;
color: var(--ink);
background: linear-gradient(180deg, var(--sky-top), var(--sky-bottom));

/* The shorthand above resets background-color to transparent; give it
the sky's ground color explicitly. Mobile Safari derives its chrome
and overscroll tint from a real background-color when it distrusts
(or lacks) a theme-color — a transparent body reads as white/grey
there, which is what a night sky must never fade into. */
background-color: var(--sky-bottom);
transition:
--sky-top 1.6s ease,
--sky-bottom 1.6s ease,
Expand Down
Loading