Fix rail rendering under the Android status bar

targetSdk 36 (Android 15+) forces edge-to-edge, so the fixed-position
top rail was drawing behind the status bar clock/battery icons on a
real device (title and DARK/LIGHT toggle both obscured) — invisible on
desktop since there's no inset there. Add env(safe-area-inset-top) via
a --rail-h variable used everywhere the rail's height was hardcoded as
42px, plus viewport-fit=cover so the inset actually gets populated.

Verified on a physical Galaxy Z Fold over adb.
This commit is contained in:
Dongubak
2026-08-23 15:11:05 +09:00
parent 31cfed7023
commit 2f570681eb
+10 -6
View File
@@ -2,7 +2,7 @@
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<!-- user-scalable=no: the canvas has its own pinch-to-zoom (OrbitControls) —
letting the OS page-zoom fight it over the same two-finger gesture is worse
than losing native page zoom, which this app has no text layout to need anyway. -->
@@ -22,6 +22,9 @@ try {
Hierarchy comes from hairlines, scale and space alone.
The only color in the app is marker identity (viewport + its legend). ── */
:root{
/* rail height + the device's own status-bar/notch inset (0 on desktop) —
every fixed element anchored below the rail must offset by this, not 42px */
--rail-h:calc(42px + env(safe-area-inset-top));
--bg:#0a0b0c; /* viewport ground, neutral near-black */
--panel:#0c0d0f;
--line:rgba(255,255,255,0.10);
@@ -64,9 +67,10 @@ try {
/* ── Top rail: identity, session telemetry ── */
#rail{
position:fixed; top:0; left:0; right:0; height:42px; z-index:11;
position:fixed; top:0; left:0; right:0; height:var(--rail-h); z-index:11;
padding-top:env(safe-area-inset-top); /* status bar/notch — the 42px content stays below it */
background:var(--panel); border-bottom:1px solid var(--line);
display:flex; align-items:center; justify-content:space-between; padding:0 16px; gap:16px;
display:flex; align-items:center; justify-content:space-between; padding-left:16px; padding-right:16px; gap:16px;
}
#rail .mark{ display:flex; align-items:baseline; gap:11px; min-width:0; }
/* drawer toggle — only shown under the small-screen media query below */
@@ -103,7 +107,7 @@ try {
/* ── Docked instrument column ── */
#panel{
position:fixed; top:42px; left:0; bottom:0; z-index:10; width:284px;
position:fixed; top:var(--rail-h); left:0; bottom:0; z-index:10; width:284px;
background:var(--panel); border-right:1px solid var(--line);
display:flex; flex-direction:column; overflow-y:auto;
}
@@ -236,7 +240,7 @@ try {
#loading.empty .load-live{ display:none; }
#loading.empty .prompt{ display:flex; pointer-events:auto; }
/* the "no cloud yet" state must not block the dashboard — you can go live without a file */
#loading.empty{ top:42px; left:284px; background:transparent; pointer-events:none; }
#loading.empty{ top:var(--rail-h); left:284px; background:transparent; pointer-events:none; }
#loading .glyph{ font-size:10px; color:var(--faint); letter-spacing:0.5em; text-indent:0.5em; }
/* ── drag & drop overlay ── */
@@ -259,7 +263,7 @@ try {
}
#panel.open{ transform:translateX(0); }
#panelBackdrop{
display:block; position:fixed; top:42px; left:0; right:0; bottom:0; z-index:9;
display:block; position:fixed; top:var(--rail-h); left:0; right:0; bottom:0; z-index:9;
background:var(--overlay); opacity:0; pointer-events:none; transition:opacity .18s ease;
}
#panelBackdrop.show{ opacity:1; pointer-events:auto; }