diff --git a/ui/index.html b/ui/index.html index d68ab95..b22c7ed 100644 --- a/ui/index.html +++ b/ui/index.html @@ -43,10 +43,10 @@ box-shadow: 0 1px 0 rgba(255,255,255,.04), 0 6px 18px rgba(0,0,0,.35); } .brand { display: flex; align-items: center; gap: 11px; color: var(--bright); text-decoration: none; } .brand svg { width: 30px; height: 30px; } - .brand b { font-weight: 700; font-size: 15px; letter-spacing: 2.5px; } + .brand b { font-weight: 700; font-size: 16px; letter-spacing: -.1px; } nav { display: flex; gap: 4px; height: 100%; } nav a { display: flex; align-items: center; padding: 0 13px; height: 100%; color: var(--text); text-decoration: none; - font-weight: 500; font-size: 15px; letter-spacing: 1.2px; text-transform: uppercase; + font-weight: 500; font-size: 15px; border-bottom: 3px solid transparent; transition: color .15s; } nav a:hover { color: var(--bright); } nav a.on { color: var(--blue); border-bottom-color: var(--blue); } @@ -158,7 +158,7 @@ .panel { background: linear-gradient(180deg, rgba(42,47,56,.72) 0%, rgba(30,35,41,.9) 100%); border-radius: 4px; padding: 18px; box-shadow: 0 8px 24px rgba(0,0,0,.25); min-width: 0; } .shelf-head { display: flex; align-items: baseline; gap: 12px; margin: 0 0 14px; } - .shelf-head h2 { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--text); } + .shelf-head h2 { margin: 0; font-size: 17px; font-weight: 600; color: var(--bright); } .shelf-head .count { color: var(--muted); font-size: 13px; } .shelf-head .spacer { flex: 1; } .sub { color: var(--muted); font-size: 12.5px; } @@ -328,7 +328,7 @@ /* ---- bottom bar (Steam's DOWNLOADS strip) ---- */ .bottombar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; height: calc(42px + env(safe-area-inset-bottom)); display: flex; align-items: center; gap: 14px; padding: 0 calc(28px + env(safe-area-inset-right)) env(safe-area-inset-bottom) calc(28px + env(safe-area-inset-left)); background: rgba(23,29,37,.96); box-shadow: 0 -1px 0 rgba(255,255,255,.04); cursor: pointer; } - .bottombar .label { font-size: 12px; font-weight: 700; letter-spacing: 1.6px; color: var(--muted); } + .bottombar .label { font-size: 13px; font-weight: 600; color: var(--muted); } .bottombar .jobs { display: inline-flex; align-items: center; gap: 8px; color: var(--link); font-size: 12.5px; } .bottombar .jobs .spinner { width: 13px; height: 13px; border-width: 2px; } .bottombar .last { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-size: 13px; } @@ -462,12 +462,16 @@ .hdr-end .pill, .hdr-end .devsel { min-width: 0; } .hdr-end .pill { padding: 0 8px; gap: 6px; } .hdr-end .pill > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; } + /* The picker names the headset, so the pill keeps only its status dot: the name shows once. */ + .hdr-end:has(.devsel:not([hidden])) .pill { flex: none; min-width: 0; width: 38px; padding: 0; justify-content: center; } + .hdr-end:has(.devsel:not([hidden])) .pill .pt { display: none; } + .hdr-end .devsel { flex: 1 1 auto; max-width: none; } #reportBtn, #refreshAll { width: 38px; padding: 0; justify-content: center; } nav { position: fixed; left: 0; right: 0; bottom: 0; z-index: 25; gap: 0; height: calc(58px + env(safe-area-inset-bottom)); padding: 0 env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); background: rgba(23,29,37,.97); backdrop-filter: blur(12px); box-shadow: 0 -1px 0 rgba(255,255,255,.07); } - nav a { flex: 1; flex-direction: column; justify-content: center; gap: 3px; padding: 0; font-size: 10.5px; - letter-spacing: .5px; border-bottom: 0; color: var(--muted); } + nav a { flex: 1; flex-direction: column; justify-content: center; gap: 3px; padding: 0; font-size: 11px; + border-bottom: 0; color: var(--muted); } nav a.on { border-bottom: 0; } nav svg { display: block; width: 23px; height: 23px; } .bottombar, .drawer { display: none; } @@ -650,7 +654,7 @@ .lib-menu button.danger { color:#ff9c8a; } .lib-empty { grid-column:1/-1; text-align:center; padding:48px 20px; border:1px dashed #ffffff1c; border-radius:12px; color:#a8b5c2; } .lib-empty h2 { color:var(--bright); text-transform:none; letter-spacing:-.3px; font-size:20px; margin:0 0 8px; } - .lib-section { font-size:13px; text-transform:uppercase; letter-spacing:1.6px; color:var(--muted); margin:0 0 14px; font-weight:700; } + .lib-section { font-size:17px; color:var(--bright); margin:0 0 14px; font-weight:600; } .lib-manage { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,360px),1fr)); gap:18px; align-items:start; } .store-empty { display:flex; flex-direction:column; align-items:center; text-align:center; padding:58px 20px 70px; } .store-empty svg { width:110px; height:90px; color:var(--link); margin-bottom:14px; } @@ -855,7 +859,7 @@ .store-heading h1 { font-size:21px; } .store-heading p { display:block; max-width:none; } .store-search { min-height:48px; } - .workspace-heading #sourcesOpen { min-height:44px; } + #sourcesOpen { min-height:44px; } #nav a { min-width:0; } .drawer.open { display:block; bottom:calc(58px + env(safe-area-inset-bottom)); } } @@ -937,7 +941,7 @@ - FRAME CONTROL + Frame Control Apps1 @@ -1220,7 +1224,7 @@ Made for your FrameAppsVR experiences, Android apps and desktop apps.+ Add / Install InstalledBrowseLinux apps - Find something for your headset, then install from its app page.Manage sourcesReport an APK + Find something for your headset, then install from its app page.Report an APK @@ -1229,6 +1233,7 @@ Only apps that fit the Frame Show phone-only apps SourceAll sources + Manage sources @@ -1243,7 +1248,7 @@ ← All toolsToolsChoose a task for your Frame. -Content & filesSend to FrameAdd files, APKs or your own gamesMedia playerPlay your own videos and mediaLibrary artworkManage artwork and image sourcesLinux appsInstall and manage desktop appsPlay & controlCapture & LiveSee and control the headset viewKeyboard & trackpadType and point in desktop appsPanel switcherBring an open panel into viewVR toolsPerformance HUD and VR utilitiesFamily & comfortSession reminders and breaksMac in the headsetShare Mac windows and displaysYour FrameConnection, display & preferences →AssistantOpen assistant & AI agents →Use your own model endpoint or review a proposed MCP action. +Content & filesSend to FrameAdd files, APKs or your own gamesMedia playerPlay your own videos and mediaLinux appsInstall and manage desktop appsPlay & controlCapture & LiveSee and control the headset viewKeyboard & trackpadType and point in desktop appsPanel switcherBring an open panel into viewVR toolsPerformance HUD and VR utilitiesFamily & comfortSession reminders and breaksMac in the headsetShare Mac windows and displaysYour FrameConnection, display & preferences →AssistantOpen assistant & AI agents →Use your own model endpoint or review a proposed MCP action. VR comfort and performanceWaiting for the Frame @@ -1559,7 +1564,7 @@ Close activity log - ACTIVITY + Activity Ready Show ▴ @@ -2167,7 +2172,7 @@ function render(s) { ${esc(g.name)} ${gb(g.size)} - ▶ PLAY + ▶ Play `).join("") : `No games installed.`; // Tall library art, falling back to the wide header, then to the name card. @@ -3383,14 +3388,17 @@ async function loadTitles() { ${esc(t.id)} ${esc(t.runtime_label)}${t.target ? " · " + esc(t.target) : ""} - ${t.art_missing ? `Add artwork` : ""} - ▶ - Remove + Play + ⋯ + ${t.art_missing ? `Add artworkIts Steam library tile has none yet` : ""} + Remove…Deletes the game and its files + `).join("") : `None yet.`; } $("titleList").onclick = async e => { const b = e.target.closest("[data-title]"); if (!b) return; const id = b.dataset.id; + b.closest(".lib-more")?.removeAttribute("open"); if (b.dataset.title === "remove") { if (!confirm(`Remove ${id} and its files from the Frame?`)) return; await act(`Remove ${id}`, () => api("/api/titles", { action: "remove", id }), b); @@ -3476,7 +3484,7 @@ function gameButtons(id, name, free) { const open = `Store on Frame`; if (d && d.appid === id) return `${d.paused ? "Paused" : "Downloading"} ${d.percent ?? 0}%`; if (g && g.installed) return `Installed` + - `▶ PLAY`; + `▶ Play`; if (g) return `Install on Frame`; return `${free ? "Get" : "Buy"} on Steam ↗${open}`; }
VR experiences, Android apps and desktop apps.
Find something for your headset, then install from its app page.
Choose a task for your Frame.
Use your own model endpoint or review a proposed MCP action.