/* 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); overscroll-behavior:none; -webkit-text-size-adjust:100%} body{overscroll-behavior:none} 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; 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); position:relative; z-index:30; /* its menu opens over the stage */ padding-top:max(8px, env(safe-area-inset-top)); flex-wrap:nowrap; min-width:0; } .bar > *{flex-shrink:0} .bar .badge{flex-shrink:1; min-width:0} .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} /* a field the UI focused by itself (a screen opened with it): the phone shows its keyboard only for a tap, so this is the tap (app.js "phone keyboard") */ #kb-pill{position:absolute; left:50%; bottom:72px; transform:translateX(-50%); z-index:5; display:inline-flex; align-items:center; gap:8px; line-height:1.2; padding:10px 18px; border-radius:999px; box-shadow:0 6px 20px rgba(0,0,0,.45)} #kb-pill[hidden]{display:none} #kb-pill svg{width:20px; height:20px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round} #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} /* a narrower window: the bar stays one row (labels shorten, the brand name goes first) */ @media (max-width:720px){ .wide{display:none} .brand span{display:none} .bar{gap:8px} } @media (max-width:420px){ .btn{height:34px; padding:0 10px; font-size:13px} .btn.icon{width:34px} #btn-reset{display:none} /* the More menu has it too */ } /* ---- a phone or tablet, or a tall window: the canvas IS the screen (app.js "fill") ---- One slim bar row, then the canvas edge to edge; the safe areas (notch, home indicator, rounded corners on a phone on its side) stay clear. */ body.fill{height:100vh; height:100dvh; min-height:0; overflow:hidden} body.fill .bar{min-height:0; gap:8px; padding-top:max(6px, env(safe-area-inset-top)); padding-bottom:6px} body.fill #stage{flex:1 1 auto; padding:0; align-items:flex-start; overflow:hidden; padding-left:env(safe-area-inset-left); padding-right:env(safe-area-inset-right); padding-bottom:env(safe-area-inset-bottom)} body.fill #frame{border-radius:0; box-shadow:none; transition:transform .18s ease-out} body.fill #screen{border-radius:0} body.fill .hint{display:none} /* a phone on its side: every pixel of height counts */ @media (max-height:500px){ body.fill .bar{padding-top:max(4px, env(safe-area-inset-top)); padding-bottom:4px} body.fill .btn{height:30px; font-size:13px} body.fill .btn.icon{width:30px} body.fill .brand img{width:26px; height:17px} } body.fill #toast{top:calc(env(safe-area-inset-top) + 58px)} body.fill .link-help{position:fixed; z-index:25; left:max(8px, env(safe-area-inset-left)); right:max(8px, env(safe-area-inset-right)); bottom:calc(env(safe-area-inset-bottom) + 72px); margin:0; background:linear-gradient(var(--warn-bg), var(--warn-bg)), var(--solid)} .rotate-hint{display:none} @media (max-width:560px){ :root{--bar-h:auto} .wide{display:none} #stage{align-items:flex-start; flex:0 0 auto} .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:"..."} } /* ---- the node link ---- */ .badge{max-width:46vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap} .badge.wait{background:var(--control); color:var(--mut); box-shadow:inset 0 0 0 1px var(--line)} .badge.up{background:var(--accent-soft); color:var(--cyan); box-shadow:inset 0 0 0 1px rgba(25,214,194,.38)} .badge.bad{background:var(--warn-bg); color:var(--warn); box-shadow:inset 0 0 0 1px var(--warn-line)} .link-help{display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin:10px auto 0; max-width:900px; padding:10px 14px; border-radius:12px; background:var(--warn-bg); box-shadow:inset 0 0 0 1px var(--warn-line); color:var(--ink2); font-size:14px; line-height:1.45} .link-help[hidden]{display:none} .link-help p{flex:1 1 320px; margin:0; min-width:0} dialog#connect-dlg{ width:min(460px, calc(100vw - 2*var(--gutter))); padding:22px; border:0; border-radius:18px; background:var(--solid); color:var(--ink); box-shadow:inset 0 0 0 1px var(--line), var(--shadow); } dialog#connect-dlg::backdrop{background:rgba(0,0,0,.6)} #connect-dlg h2{margin:0 0 6px; font-size:19px} #connect-dlg .lead{margin:0 0 16px; color:var(--mut); font-size:14px; line-height:1.45} #connect-dlg .choices{display:flex; flex-direction:column; gap:10px} #connect-dlg .choice{ display:flex; flex-direction:column; align-items:flex-start; gap:3px; width:100%; padding:12px 14px; border:0; border-radius:12px; text-align:left; cursor:pointer; background:var(--control); color:var(--ink); box-shadow:inset 0 0 0 1px var(--line); font:inherit; } #connect-dlg .choice[hidden]{display:none} #connect-dlg .choice.wifi{cursor:default} #connect-dlg button.choice:hover{background:var(--control-hi)} #connect-dlg .choice strong{font-size:15px} #connect-dlg .choice span{color:var(--dim); font-size:13px} #connect-dlg .row{display:flex; gap:8px; width:100%; margin-top:8px} #connect-dlg input{ flex:1; min-width:0; height:36px; padding:0 12px; border:0; border-radius:10px; background:var(--bg); color:var(--ink); box-shadow:inset 0 0 0 1px var(--line); font:inherit; font-size:14px; } #connect-dlg input:focus{outline:none; box-shadow:inset 0 0 0 1px var(--teal)} #connect-dlg .note{margin:14px 0 0; color:var(--mut); font-size:13px; line-height:1.45} #connect-dlg .note .link-line{display:block; margin-top:6px} #connect-dlg .note a{color:var(--cyan)} #connect-dlg .actions{display:flex; justify-content:flex-end; margin-top:16px} /* the hidden field the phone's own keyboard types into (app.js "phone keyboard") */ #ime{position:fixed; left:0; top:0; width:1px; height:1px; opacity:0; border:0; padding:0; margin:0; font-size:16px; resize:none; background:transparent; color:transparent; caret-color:transparent; z-index:-1} /* the bar's "More" menu: browser backup / restore */ .more{position:relative} .btn.icon svg circle{fill:currentColor; stroke:none} .menu{position:absolute; right:0; top:calc(100% + 6px); z-index:20; min-width:260px; padding:6px; background:var(--solid); border:1px solid var(--line); border-radius:12px; box-shadow:0 10px 30px rgba(0,0,0,.5); display:flex; flex-direction:column; gap:2px} .menu[hidden], .menu button[hidden]{display:none} .menu button{all:unset; cursor:pointer; padding:9px 12px; border-radius:8px; color:var(--ink); font:600 14px/1.25 Montserrat, system-ui, sans-serif} .menu button span{display:block; font-weight:500; font-size:12px; opacity:.7; margin-top:2px} .menu button:hover, .menu button:focus-visible{background:var(--control-hi)} #connect-dlg #wifi-handoff{margin-top:10px; width:100%} #connect-dlg #wifi-handoff p{margin:0; color:var(--mut); font-size:13px; line-height:1.45}