mirror of
https://github.com/ALLFATHER-BV/wadamesh.git
synced 2026-11-08 14:08:25 +00:00
pthreads for the UI's background tasks, LVGL + the UI loop on the browser main thread (emscripten_set_main_loop), IDBFS at /data loaded before main() and persisted after writes settle and on hide/pagehide; Reboot persists and reloads. Page shell in the site's Night palette: Demo badge, Connect placeholder, Reset demo data, Fullscreen; canvas scaled with aspect kept, crisp at whole device pixels; pointer = finger, keyboard = CardKB codes. serve.py and nginx-snippet.conf send COOP/COEP; without isolation the page says so. Release -O2 (wasm brotli 1.14 MB), web-debug variant with -g. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
118 lines
5.9 KiB
CSS
118 lines
5.9 KiB
CSS
/* wadamesh in the browser: the page around the device canvas.
|
|
Tokens are the site's Night palette (deploy/site/theme.css), dark only. */
|
|
:root{
|
|
color-scheme:dark;
|
|
--bg:#000400;
|
|
--card:rgba(11,14,16,.74);
|
|
--solid:#0B0E10;
|
|
--ink:#E6EBED; --ink2:#D2D9DD; --mut:#B0BAC0; --dim:#8C979D;
|
|
--line:#1C2428;
|
|
--control:#161D21; --control-hi:#222C31;
|
|
--teal:#15B6A6; --cyan:#19D6C2;
|
|
--accent-fill:#15B6A6; --on-accent:#00120F;
|
|
--accent-soft:rgba(25,214,194,.13);
|
|
--bar:rgba(0,0,0,.5);
|
|
--frame:#16191D; --frame-edge:#2A3036;
|
|
--warn:#F2A33A; --warn-bg:rgba(242,163,58,.13); --warn-line:rgba(242,163,58,.38);
|
|
--bad:#F06A6E;
|
|
--shadow:0 22px 50px -26px rgba(0,0,0,.85);
|
|
--bar-h:56px;
|
|
--gutter:16px;
|
|
}
|
|
*{box-sizing:border-box}
|
|
html,body{margin:0; height:100%}
|
|
html{background:var(--bg)}
|
|
body{
|
|
min-height:100%; display:flex; flex-direction:column;
|
|
color:var(--ink); background:
|
|
radial-gradient(1200px 600px at 20% -10%, rgba(25,214,194,.10), transparent 60%),
|
|
radial-gradient(900px 500px at 90% 110%, rgba(90,169,255,.07), transparent 60%),
|
|
var(--bg);
|
|
font-family:'Montserrat',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif; font-weight:500;
|
|
-webkit-font-smoothing:antialiased;
|
|
}
|
|
::selection{background:rgba(25,214,194,.32)}
|
|
|
|
/* ---- the bar ---- */
|
|
.bar{
|
|
display:flex; align-items:center; gap:10px; flex-wrap:wrap;
|
|
min-height:var(--bar-h); padding:8px var(--gutter);
|
|
padding-left:max(var(--gutter), env(safe-area-inset-left));
|
|
padding-right:max(var(--gutter), env(safe-area-inset-right));
|
|
background:var(--bar); border-bottom:1px solid var(--line);
|
|
-webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
|
|
}
|
|
.brand{display:inline-flex; align-items:center; gap:8px; color:var(--ink); text-decoration:none;
|
|
font-weight:700; letter-spacing:.02em; font-size:17px}
|
|
.brand img{display:block}
|
|
.badge{display:inline-flex; align-items:center; height:24px; padding:0 10px; border-radius:12px;
|
|
background:var(--warn-bg); color:var(--warn); box-shadow:inset 0 0 0 1px var(--warn-line);
|
|
font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase}
|
|
.spacer{flex:1}
|
|
.btn{
|
|
height:36px; padding:0 14px; border:0; border-radius:18px; cursor:pointer;
|
|
background:var(--control); color:var(--ink2); box-shadow:inset 0 0 0 1px var(--line);
|
|
font:inherit; font-size:14px; font-weight:600; white-space:nowrap;
|
|
transition:background .15s, box-shadow .15s, color .15s;
|
|
}
|
|
.btn:hover{background:var(--control-hi)}
|
|
.btn:focus-visible{outline:none; box-shadow:inset 0 0 0 1px var(--teal), 0 0 0 3px var(--accent-soft)}
|
|
.btn.primary{background:var(--accent-fill); color:var(--on-accent); box-shadow:none}
|
|
.btn.primary:hover{background:var(--cyan)}
|
|
.btn.icon{width:36px; padding:0; display:inline-grid; place-items:center}
|
|
.btn.icon svg{width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round}
|
|
.btn[hidden]{display:none}
|
|
|
|
/* ---- the stage: the canvas, scaled by app.js (aspect kept, integer device pixels when it can) ---- */
|
|
#stage{
|
|
flex:1; min-height:0; display:flex; align-items:center; justify-content:center;
|
|
padding:var(--gutter);
|
|
padding-left:max(var(--gutter), env(safe-area-inset-left));
|
|
padding-right:max(var(--gutter), env(safe-area-inset-right));
|
|
}
|
|
#frame{position:relative; line-height:0; border-radius:10px; background:#000;
|
|
box-shadow:0 0 0 1px var(--frame-edge), 0 0 0 7px var(--frame), 0 0 0 8px var(--frame-edge), var(--shadow)}
|
|
#screen{display:block; width:800px; height:480px; border-radius:2px; touch-action:none; outline:none;
|
|
-webkit-user-select:none; user-select:none; -webkit-tap-highlight-color:transparent; cursor:default}
|
|
#screen.crisp{image-rendering:crisp-edges; image-rendering:pixelated} /* integer device-pixel scale: nearest */
|
|
|
|
#overlay{position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center;
|
|
gap:6px; padding:24px; text-align:center; line-height:1.45; background:var(--solid); border-radius:2px}
|
|
#overlay[hidden]{display:none}
|
|
#overlay img{opacity:.95; margin-bottom:8px}
|
|
#status{margin:0; font-size:16px; font-weight:600; color:var(--ink)}
|
|
#overlay .detail{margin:0; max-width:520px; font-size:13px; color:var(--mut)}
|
|
#overlay .detail code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12px; color:var(--ink2)}
|
|
#overlay.busy #status::after{content:""; display:inline-block; width:1.2em; text-align:left;
|
|
animation:dots 1.2s steps(4,end) infinite}
|
|
@keyframes dots{0%{content:""}25%{content:"."}50%{content:".."}75%{content:"..."}}
|
|
#overlay.fatal #status{color:var(--bad)}
|
|
#overlay .btn{margin-top:10px; line-height:normal}
|
|
|
|
.hint{margin:0 auto; padding:0 var(--gutter) 18px; max-width:820px; text-align:center;
|
|
color:var(--dim); font-size:13px; line-height:1.5}
|
|
|
|
#toast{position:fixed; left:50%; top:calc(var(--bar-h) + 12px); transform:translateX(-50%);
|
|
max-width:min(460px, calc(100vw - 32px)); padding:12px 16px; border-radius:12px;
|
|
background:var(--solid); color:var(--ink2); box-shadow:inset 0 0 0 1px var(--line), var(--shadow);
|
|
font-size:14px; line-height:1.45; z-index:10}
|
|
|
|
/* fullscreen: only the device, on black */
|
|
#stage:fullscreen{padding:0; background:#000; align-items:center}
|
|
#stage:-webkit-full-screen{padding:0; background:#000; align-items:center}
|
|
#stage:fullscreen #frame, #stage:-webkit-full-screen #frame{box-shadow:none; border-radius:0}
|
|
|
|
.rotate-hint{display:none}
|
|
@media (max-width:560px){
|
|
:root{--bar-h:auto}
|
|
.wide{display:none}
|
|
#stage{align-items:flex-start; flex:0 0 auto}
|
|
.rotate-hint{display:block; margin:0 auto 10px; padding:0 var(--gutter); text-align:center; color:var(--mut); font-size:13px}
|
|
.bar{gap:8px}
|
|
.brand span{display:none}
|
|
.btn{height:34px; padding:0 12px; font-size:13px}
|
|
.btn.icon{width:34px}
|
|
#frame{border-radius:6px; box-shadow:0 0 0 1px var(--frame-edge), 0 0 0 4px var(--frame), 0 0 0 5px var(--frame-edge)}
|
|
}
|
|
@media (prefers-reduced-motion:reduce){ #overlay.busy #status::after{animation:none; content:"..."} }
|