Files
marcandClaude Opus 5 00b1d4469f feat(honeybar): the HoneyOS bar, loaded at runtime
A strip along the top that leads to the other apps of the same system. It is
served by HoneyOS; InkNote only says where to find it, through
INKNOTE_HONEYBAR_ORIGIN. Empty means no bar and no change at all.

The origin is served by the API rather than built into the page, because an
image is pulled ready-made and a service worker keeps whole responses: anything
frozen into index.html would outlive the setting.

Layout follows the bar through --honeybar-h. The body has overflow:hidden, so
the surplus height would not have scrolled but been cut off at the bottom; and
#root padded itself around the notch that the bar now covers, which would have
counted that gap twice.

Unit 263/263, all fourteen browser suites green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 11:07:43 +02:00

70 lines
4.1 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<meta name="theme-color" content="#0d1117" media="(prefers-color-scheme: dark)" />
<meta name="theme-color" content="#f6f8fa" media="(prefers-color-scheme: light)" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="InkNote" />
<meta name="description" content="Write & draw — notes that sync everywhere" />
<meta name="mobile-web-app-capable" content="yes" />
<!-- `use-credentials` because the manifest is otherwise fetched with
credentials omitted, cookies and all. Behind an authenticating reverse
proxy that request comes back as the proxy's login page, the browser
reads it as an invalid manifest, and no install is ever offered — while
the app itself works perfectly, because its own requests do carry the
cookie. Harmless without a proxy. -->
<link rel="manifest" href="./manifest.json" crossorigin="use-credentials" />
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="192x192" href="./icon-192.png" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>✏️</text></svg>" />
<title>InkNote</title>
<script>
/* Catch the browser's install offer before anything else runs.
*
* `beforeinstallprompt` is fired once, early — usually before React has
* mounted — and is never fired again. Listening for it from inside a
* component meant it was simply missed, and the install button never
* appeared however correctly the site was served. It is stashed here, at
* the top of the document, and the app picks it up when it is ready. */
window.__inknoteInstallPrompt = null;
window.addEventListener("beforeinstallprompt", function (e) {
e.preventDefault();
window.__inknoteInstallPrompt = e;
window.dispatchEvent(new Event("inknote:installable"));
});
</script>
<style>
body { margin: 0; padding: 0; overflow: hidden; overscroll-behavior: none; }
/* --honeybar-h is set by the HoneyOS bar while it is on the page, and is
0 when it is not. The bar sits above the app and pushes it down, so the
app has that much less room; body has overflow:hidden, which means the
difference would not scroll but simply be cut off at the bottom.
It also covers the notch itself, so the padding above must give way —
otherwise the gap is counted twice. max() keeps that from going
negative when there is no bar. */
#root {
box-sizing: border-box;
padding: max(0px, calc(env(safe-area-inset-top) - var(--honeybar-h, 0px)))
env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
height: calc(100vh - var(--honeybar-h, 0px));
}
#splash { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 16px; background: #0d1117; z-index: 9999; transition: opacity 0.3s; }
#splash.hide { opacity: 0; pointer-events: none; }
#splash .logo { width: 64px; height: 64px; border-radius: 18px; background: linear-gradient(135deg, #388bfd, #a855f7); display: flex; align-items: center; justify-content: center; font-size: 32px; animation: pulse 1.5s infinite; }
#splash .text { color: #e6edf3; font-family: Georgia, serif; font-size: 22px; font-weight: 700; }
@keyframes pulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.05); } }
</style>
</head>
<body>
<div id="splash">
<div class="logo">✏️</div>
<div class="text">InkNote</div>
</div>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>