// layout.js — phone layouts: 'portrait' (narrow: the panel becomes a bottom sheet) or 'landscape' (short: a narrow
// side panel); '' = the desktop layout. Both phone layouts fold the toolbar into a ☰ menu.
export const NARROW = 700, SHORT = 500, SHORT_MAX_W = 1000;
export function compactMode(w, h) {
if (w <= NARROW) return 'portrait';
if (h <= SHORT && w <= SHORT_MAX_W) return 'landscape';
return '';
}
// The screen part the panel covers, for sampling which tiles are visible: a side panel takes a strip on the right,
// a bottom sheet one at the bottom. rect: the panel's bounding box; null or collapsed: none.
export function freeArea(w, h, rect) {
if (!rect || rect.width <= 0 || rect.height <= 0) return { w, h };
if (rect.width >= w * 0.8) return { w, h: Math.max(64, Math.min(h, rect.top)) }; // bottom sheet
return { w: Math.max(64, Math.min(w, rect.left)), h }; // right-hand panel
}
export function applyMode(body, mode, prev) { // → true when the layout just turned compact
body.classList.toggle('compact', !!mode);
body.classList.toggle('portrait', mode === 'portrait');
body.classList.toggle('landscape', mode === 'landscape');
if (!mode) body.classList.remove('menu-open');
return !!mode && !prev;
}
// Whole-planet layer textures: phones and tablets get at most 4096 px (an 8192 one with mipmaps is ≈ 170 MB of GPU
// memory; mobile browsers lose the WebGL context long before desktops). Deep zoom shows tiles either way.
export const MOBILE_TEXTURE = 4096;
export function textureCap(gpuMax, touch = globalThis.matchMedia?.('(pointer: coarse)').matches,
w = globalThis.innerWidth, h = globalThis.innerHeight) {
return touch || compactMode(w, h) ? Math.min(gpuMax, MOBILE_TEXTURE) : gpuMax;
}