mirror of
https://github.com/MichaelScottsman/LiquidAss-Frame.git
synced 2026-10-18 21:01:12 +02:00
353 lines
32 KiB
CSS
353 lines
32 KiB
CSS
/* Glass Shell Phase 2 concept "window-nav" (the shell): shared styles for the window-nav-*.html
|
|
* mockups and for every area mockup that draws the shell's chrome. Builds on kit.css (DESIGN2
|
|
* tokens). Every number is a size or rule from docs/phase2/concepts/window-nav.md; numbers are
|
|
* main-window CSS px unless a block says "popup px" (frame.menu, x1.10 in the view) or
|
|
* "systemui px" (frame controls, x0.75). Revision 3 (PLAN §1 conformance): state values from
|
|
* PLAN §1.4 (focus + .28 with a .16 spot in the upper third; laser hover + .08 and a .12 spot;
|
|
* navigation hover = the spot only; navigation selection .18 + arc + Semibold), the ornament's
|
|
* quiet legend and gamepad-only glyph badges (§1.10), the 60 / 80 More circle inside its host
|
|
* (§1.11), quiet frame controls (VP P-70), text on coloured fills dark (CC §7).
|
|
* Session 2 (2026-10-07): the shell's own states (tab bar, ornament members, frame controls, More
|
|
* circle) use P4's theme model: + .28 (`--lgs-focus-add`) with normal alpha compositing (P4-D5);
|
|
* kit.css still blends with plus-lighter until P4's kit parity (FD-3). C1c's presentation recipe
|
|
* (menus, alerts, sheets; REQ C1c->C1a) replaces revision 2's blocks. New: the library's fixed
|
|
* ornament slots (data-slots), the quiet legend's dim band on `window` routes (flag quietBacking),
|
|
* the page members' recede during alerts and sheets, the More circle without blur inside glass. */
|
|
|
|
/* ------------------------------------------------------------------ edges (WN §8.2, critique 4)
|
|
kit.css draws the E3 specular ring as a conic arc PLUS a full-width linear top layer. On wide
|
|
slabs (ornament, Power menu, window) that linear layer became a uniform 2 px line about +100 L
|
|
across the whole top: an outline. The shell replaces it with a light-dependent highlight: a
|
|
radial lobe centred at 26 % of the width under the key light (above, 20 deg left), fading to
|
|
nothing by 78 % of the width and down the sides. With the conic arc this gives "a band near the
|
|
top-left plus a faint top edge" (DESIGN2 §6.2 R3) and never a line of constant brightness. */
|
|
.lgk-view .lgk-glass::before {
|
|
background:
|
|
conic-gradient(from var(--lg-light),
|
|
rgb(255 255 255 / calc(.62 * var(--rim, 1))) 0deg,
|
|
rgb(255 255 255 / calc(.20 * var(--rim, 1))) 38deg,
|
|
transparent 72deg, transparent 148deg,
|
|
rgb(255 255 255 / calc(.16 * var(--rim, 1))) 180deg,
|
|
transparent 214deg, transparent 288deg,
|
|
rgb(255 255 255 / calc(.22 * var(--rim, 1))) 322deg,
|
|
rgb(255 255 255 / calc(.62 * var(--rim, 1))) 360deg),
|
|
radial-gradient(70% 120% at 26% 0%, rgb(255 255 255 / calc(.18 * var(--rim, 1))) 0, rgb(255 255 255 / calc(.06 * var(--rim, 1))) 46%, transparent 75%);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ state values (PLAN §1.4)
|
|
The gamepad focus add is P4's token `--lgs-focus-add` (.28 today, contracts/tokens.md; tuned once in
|
|
.28-.32 from G-FOCUS), drawn with normal alpha compositing as the theme does (P4-D5). On the tab
|
|
bar's glass (L ~95) .28 measures focus - rest +35 L and focus - current-route circle +7.6 L
|
|
(PLAN-1a-2 fails); .32 measures +42.5 and +15.1 (passes). The shell's mockups use .32, the top of
|
|
§1.4's range, pending P4's one-time tuning (REQ C1a->P4; window-nav.md §13.1). */
|
|
.lgk-view { --wn-focus-add: .32; --wn-focus-spot: .16; }
|
|
/* glass tone under text: L 70-90 (PLAN §1.6, D2 §6.3). kit.css aims liquid glass at luma .38 (~97 L) and
|
|
its top sheen adds more, so over a bright room the tab bar and the ornament measured L 128-140 (above
|
|
the 55-110 range). The shell's liquid glass that carries labels aims at .30 (~77 L), as home-apps.css
|
|
does for its cards; glassd's tone mapping does the same on the device. */
|
|
.lgk-view :is(.wn-tabcap, .wn-orn.lgk-glass, .wn-framecap) { --lgk-target-luma: .30; }
|
|
/* kit.js clamps its adaptation at x0.42, so over the brightest parts of the room (the curtain, L ~235) the
|
|
liquid glass still lands near L 110-120. glassd's tone mapping keeps glass L 55-110 and 70-90 under text
|
|
(GM v2, PLAN §1.6), and the CSS-only tier is the panel tint (L ~75). The shell's liquid glass with labels
|
|
therefore carries a dark tone layer that holds it in the 70-90 band in the mockups. */
|
|
.lgk-view:not([data-tier="t1"]) :is(.wn-tabcap, .wn-orn.lgk-glass) {
|
|
background: linear-gradient(180deg, rgb(255 255 255 / .10), rgb(255 255 255 / .02) 55%), rgb(16 18 24 / .30); }
|
|
|
|
/* ------------------------------------------------------------------ window glass */
|
|
/* The route's glass mode decides the height (WN §3.1.1, PLAN §1.2): `window` ends at 656 (a
|
|
64 px ornament margin: the ornament 628-712 overlaps the glass by 28 and keeps 8 + 19 px clear
|
|
of SteamVR's window-bar row); `window-full` (.full) uses the full 720. Never follows focus. */
|
|
.wn-win { left: 0; top: 0; width: 1280px; height: 656px; overflow: hidden; }
|
|
.wn-win.full { height: 720px; }
|
|
.wn-win.dimmed::after {
|
|
content: ""; position: absolute; inset: 0; border-radius: inherit; background: rgb(0 0 0 / .35); z-index: 5; pointer-events: none; }
|
|
|
|
/* scroll edge under the toolbar row: dimming dominates over dark content (DESIGN2 §6.7) */
|
|
.wn-edge-top { position: absolute; left: 0; right: 0; top: 0; height: 124px; pointer-events: none; z-index: 2;
|
|
background: linear-gradient(180deg, rgb(0 0 0 / .30), rgb(0 0 0 / .12) 55%, transparent); }
|
|
.wn-fade-bottom { -webkit-mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 110px), rgb(0 0 0 / .2) calc(100% - 30px), transparent 100%);
|
|
mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 110px), rgb(0 0 0 / .2) calc(100% - 30px), transparent 100%); }
|
|
|
|
/* ------------------------------------------------------------------ toolbar row (#header) */
|
|
.wn-toolbar { position: absolute; left: 0; top: 0; width: 1280px; height: 108px; z-index: 4; }
|
|
.wn-back { position: absolute !important; left: 24px; top: 24px; }
|
|
.wn-back.root { background: transparent; color: var(--lg-text-2); }
|
|
.wn-back > .lgk-i { --is: 28px; }
|
|
.wn-back.grown { width: auto !important; padding: 0 22px 0 16px; gap: 6px; font: 500 20px/1 var(--lg-font); }
|
|
.wn-title { position: absolute; left: 100px; top: 25px; white-space: nowrap; }
|
|
.wn-title.centered { left: 0; right: 0; top: 36px; text-align: center; }
|
|
.wn-search { position: absolute !important; top: 22px; width: 520px; left: 380px; }
|
|
.wn-search.wide { width: 640px; left: 320px; }
|
|
.wn-search .typed { flex: 1; font: 500 24px/1 var(--lg-font); color: var(--lg-text-1); white-space: nowrap; }
|
|
.wn-search .caret { display: inline-block; width: 2px; height: 28px; margin-left: 2px; vertical-align: -6px; background: #fff; border-radius: 1px; }
|
|
.wn-search .clear { --s: 44px; background: rgb(255 255 255 / .16) !important; color: var(--lg-text-1) !important; }
|
|
.wn-search .clear .lgk-i { --is: 20px; }
|
|
.wn-search.dim, .wn-back.dim, .wn-title.dim { opacity: .45; }
|
|
.wn-icon-circle { position: absolute !important; top: 24px; right: 24px; }
|
|
/* library routes, laser mode: Steam's Sort & Filter, the toolbar's trailing group (PLAN §1.10, R2-2; C2c):
|
|
one 60 px capsule, right edge 24 px inside the glass, >= 20 px clear of the search capsule (x 900) */
|
|
.wn-trail { position: absolute; top: 24px; right: 24px; height: 60px; display: flex; align-items: center; gap: 0;
|
|
padding: 0 6px; border-radius: 30px; box-sizing: border-box;
|
|
background: linear-gradient(180deg, rgb(255 255 255 / .06), rgb(255 255 255 / 0) 60%), rgb(255 255 255 / .10);
|
|
box-shadow: inset 0 1.5px 1.5px -1px rgb(255 255 255 / .22), 0 1px 2px rgb(0 0 0 / .10); }
|
|
.wn-trail-b { display: inline-flex; align-items: center; gap: 8px; height: 48px; padding: 0 14px; border-radius: 24px;
|
|
font: 600 20px/1 var(--lg-font); color: var(--lg-text-1); white-space: nowrap; }
|
|
.wn-trail-b .lgk-i { --is: 22px; color: var(--lg-text-2); }
|
|
.wn-trail.dim { opacity: .45; }
|
|
|
|
/* ------------------------------------------------------------------ bottom ornament (#Footer): the ornament contract (WN §3.4, PLAN §1.10)
|
|
One capsule, y 628-712, centred, width fit-content <= 960. Members in this order:
|
|
[Steam's laser-mode Sort/Filter buttons] [action legends, label first, controller glyph trailing
|
|
(gamepad mode only)] [area slot: one segmented control] [nav legends A/B: quiet, in both modes].
|
|
Material by content: only A and B present -> the quiet legend (.wn-orn.quiet: no capsule glass,
|
|
items keep 60 px and their place). Over 960 px -> compact members (20 px labels, 16 px padding). */
|
|
.wn-orn { left: 50%; translate: -50% 0; top: 628px; gap: 4px; padding: 0 12px; max-width: 960px; }
|
|
.wn-orn.quiet { position: absolute; display: flex; align-items: center; height: 84px; box-sizing: border-box; z-index: 6; }
|
|
.wn-leg { position: relative; display: inline-flex; align-items: center; gap: 12px; height: 60px; padding: 0 14px 0 22px;
|
|
border-radius: 999px; font: 600 22px/1 var(--lg-font); color: var(--lg-text-1); white-space: nowrap; }
|
|
.wn-leg .lgk-glyph { width: 30px; height: 30px; font: 700 16px/1 var(--lg-font); background: rgb(255 255 255 / .16); color: var(--lg-text-2); }
|
|
.wn-leg .tgt { margin-left: -4px; color: var(--lg-text-2); font-weight: 500; max-width: 230px; overflow: hidden; text-overflow: ellipsis; }
|
|
.wn-leg.nav { color: var(--lg-text-2); font-weight: 500; }
|
|
.wn-orn.mode-laser .wn-leg.nav { padding: 0 22px; } /* labels only: no trailing badge */
|
|
.wn-leg.is-disabled { opacity: .38; }
|
|
.wn-orn.compact .wn-leg { font-size: 20px; padding: 0 12px 0 16px; gap: 10px; }
|
|
.wn-orn.compact .wn-leg.sf, .wn-orn.compact.mode-laser .wn-leg.nav { padding: 0 16px; }
|
|
.wn-orn.quiet .wn-leg { padding: 0 22px; }
|
|
/* the quiet legend (only A and B): no capsule material. Inside the glass (`window-full`, .in-glass):
|
|
labels Medium white .70 (PLAN §1.10). In the ornament margin of a `window` route the labels sit on
|
|
the room, where white .70 measures ~1.1 : 1 over a bright room (C1b, C1c), so they sit on the
|
|
dim band (flag quietBacking, default "window"; WN §3.4.1, O3): one soft black .62 band, 60 px
|
|
tall, its edges blurred, 10 px beyond the members; no rim, no sheen, no backdrop-filter, no slab.
|
|
It darkens the room like a shadow; it is not glass. Labels white .82 with the on-room shadow.
|
|
.bare = quietBacking "off" (PLAN §1.10's bare labels, kept for comparison). */
|
|
.wn-orn.quiet:not(.in-glass):not(.bare)::before { content: ""; position: absolute; left: 2px; right: 2px; top: 12px; bottom: 12px; border-radius: 30px;
|
|
background: rgb(0 0 0 / .62); filter: blur(7px); pointer-events: none; z-index: -1; }
|
|
.wn-orn.quiet:not(.in-glass):not(.bare) { isolation: isolate; } /* static .wn-orn.quiet markup in area mockups gets the band too */
|
|
.wn-orn.quiet:not(.in-glass):not(.bare) .wn-leg { color: rgb(255 255 255 / .82); text-shadow: 0 1px 2px rgb(0 0 0 / .45); }
|
|
.wn-orn.quiet.bare:not(.in-glass) .wn-leg { text-shadow: 0 1px 3px rgb(0 0 0 / .55), 0 0 12px rgb(0 0 0 / .35); }
|
|
/* fixed slots (the library's 300 · 130 · 156 · 134 · 120 inside an 880 px capsule; shell.ornamentSlots):
|
|
uniform 4 px gaps, no group spacers, each member exactly its slot, its content centred; the slot's
|
|
hit box takes its 2 px share of each gap (P-07). No name suffix on the Options member. */
|
|
.wn-orn.fixed { gap: 4px; padding: 0 12px; max-width: none; }
|
|
.wn-orn.fixed .wn-leg { box-sizing: border-box; justify-content: center; gap: 10px; padding: 0 12px; flex: none; }
|
|
.wn-orn.fixed .wn-leg .val { overflow: hidden; text-overflow: ellipsis; }
|
|
/* while an alert or sheet is open (C1c's html.lgs-modal): the members that act on the page beneath
|
|
recede under the tab bar's black .35 layer and stay clickable; A, B and the dialog's legends stay lit */
|
|
.wn-orn.modal .wn-leg:not(.nav)::after { opacity: 1; background: rgb(0 0 0 / .35); }
|
|
.wn-leg.sf { padding: 0 24px 0 18px; gap: 10px; } /* Steam's %{SortAndFilterButton}, and the T2 Options member */
|
|
.wn-leg.sf > .lgk-i { --is: 24px; color: var(--lg-text-2); }
|
|
.wn-leg.sf .val { color: var(--lg-text-1); }
|
|
.wn-orn .gsep { width: 14px; flex: none; }
|
|
/* CSS-only tier (WN §8.4): the page cannot see the room, so the ornament cannot frost it. Over the
|
|
window (its top 28 px) the window's own tint is beneath; outside the window: tint .70 + edges. */
|
|
.lgk-view[data-tier="t1"] .wn-orn.lgk-glass { -webkit-backdrop-filter: none; backdrop-filter: none;
|
|
background: linear-gradient(180deg, rgb(255 255 255 / .06), rgb(255 255 255 / 0) 40%), linear-gradient(180deg, rgb(28 30 40 / .50) 0 28px, rgb(28 30 40 / .70) 28px); }
|
|
.wn-leg.is-open { background: var(--lg-fill-selected); color: var(--lg-text-on-selected); }
|
|
.wn-leg.is-open .lgk-glyph, .wn-leg.is-open > .lgk-i, .wn-leg.is-open .tgt { background: rgb(13 14 18 / .12); color: rgb(13 14 18 / .7); }
|
|
.wn-leg.is-open > .lgk-i { background: transparent; }
|
|
.wn-leg.is-open .val { color: var(--lg-text-on-selected); }
|
|
.wn-menu-glyph { position: relative; }
|
|
.wn-menu-glyph::before { content: ""; width: 13px; height: 2.4px; border-radius: 2px; background: currentColor;
|
|
box-shadow: 0 -4.6px 0 currentColor, 0 4.6px 0 currentColor; }
|
|
.wn-leg::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
|
|
opacity: 0;
|
|
background: radial-gradient(circle at var(--hx, 50%) var(--hy, 30%), rgb(255 255 255 / var(--spot, .12)) 0, rgb(255 255 255 / 0) var(--spot-r, 75%)), rgb(255 255 255 / var(--lift, 0)); }
|
|
.wn-leg.is-hover::after { opacity: 1; --lift: .08; --spot: .12; }
|
|
.wn-leg.is-focus::after { opacity: 1; --lift: var(--wn-focus-add); --spot: var(--wn-focus-spot); --hx: 50% !important; --hy: 28% !important; }
|
|
.wn-leg.is-focus::before { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; padding: 1.5px;
|
|
background: conic-gradient(from var(--lg-light), rgb(255 255 255 / .8) 0deg, rgb(255 255 255 / .22) 40deg, transparent 75deg, transparent 145deg, rgb(255 255 255 / .2) 180deg, transparent 215deg, transparent 285deg, rgb(255 255 255 / .22) 320deg, rgb(255 255 255 / .8) 360deg);
|
|
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; }
|
|
.wn-orn .lgk-seg { height: 60px; }
|
|
.wn-orn .lgk-seg > * { padding: 0 20px; }
|
|
|
|
/* ------------------------------------------------------------------ tab-bar ornament (frame.menu, popup px; WN §3.3)
|
|
Pitch p and circle d come from the live sizing rule (WN §3.3.2). On this device (Console on,
|
|
developer mode, r = 1): p 58, d 50, two capsules (6 sections; Console, Steam Settings,
|
|
VR Settings, a 10 px section gap, Power). PLAN §1.4: the current route = the navigation
|
|
selection (.18 + its specular top arc + Semibold label) drawn as a circle only; laser hover =
|
|
the light spot only (navigation rows add no fill); gamepad focus = a pill spanning icon and
|
|
label at + .28 with a .16 spot in the upper third and its own arc; the two never share a shape. */
|
|
.wn-tabbar { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; --p: 58px; --d: 50px; }
|
|
.wn-tabcap { position: relative !important; display: flex; flex-direction: column; padding: 6px 12px; width: calc(var(--d) + 24px);
|
|
--r: calc((var(--d) + 24px) / 2); box-sizing: border-box; }
|
|
.wn-tabbar.expanded .wn-tabcap { width: 272px; }
|
|
.wn-tab { position: relative; display: flex; align-items: center; height: var(--p); color: var(--lg-text-2); flex: none; }
|
|
.wn-tab.secgap { margin-top: 10px; }
|
|
.wn-tab > .ic { position: relative; z-index: 1; display: grid; place-items: center; flex: none; width: var(--d); height: var(--d); border-radius: 50%; }
|
|
.wn-tab > .ic > .lgk-i { --is: calc(var(--d) * .52); }
|
|
.wn-tab > .lbl { position: relative; z-index: 1; display: none; margin-left: 10px; font: 500 22px/1 var(--lg-font); color: var(--lg-text-1); white-space: nowrap; }
|
|
.wn-tab:is(.is-nav-selected, .is-focus) > .lbl { font-weight: 600; }
|
|
.wn-tabbar.expanded .wn-tab > .lbl { display: block; }
|
|
.wn-tab .wn-badge { position: absolute; left: calc(var(--d) * .66); top: calc((var(--p) - var(--d)) / 2 + 2px); width: 13px; height: 13px; border-radius: 50%;
|
|
background: var(--lg-yellow); box-shadow: 0 0 0 2px rgb(30 30 34 / .5); z-index: 2; }
|
|
/* current route: the navigation selection (.18 + its specular top arc) as a circle behind a
|
|
heavier white glyph; no label pill */
|
|
.wn-tab.is-nav-selected { color: #fff; background: transparent; box-shadow: none; } /* kit's .is-nav-selected fill and arc would paint the whole row: the circle carries them */
|
|
.wn-tab.is-nav-selected > .ic { background: rgb(255 255 255 / .18); }
|
|
.wn-tab.is-nav-selected > .ic::before { content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none; padding: 1.5px;
|
|
background: conic-gradient(from var(--lg-light), rgb(255 255 255 / .60) 0deg, rgb(255 255 255 / .16) 40deg, transparent 75deg, transparent 285deg, rgb(255 255 255 / .16) 320deg, rgb(255 255 255 / .60) 360deg);
|
|
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; }
|
|
.wn-tab.is-nav-selected > .ic > .lgk-i { stroke-width: 2.8; }
|
|
/* laser hover (navigation row: the light spot only, no fill) and gamepad focus (always the expanded pill) */
|
|
.wn-tab::after { content: ""; position: absolute; left: 0; right: 0; top: calc((var(--p) - var(--d)) / 2); height: var(--d); border-radius: 999px;
|
|
pointer-events: none; opacity: 0;
|
|
background: radial-gradient(circle at var(--hx, 22%) var(--hy, 30%), rgb(255 255 255 / var(--spot, .12)) 0, transparent var(--spot-r, 70%)), rgb(255 255 255 / var(--lift, 0)); }
|
|
.wn-tabbar:not(.expanded) .wn-tab::after { right: auto; width: var(--d); }
|
|
.wn-tab.is-hover { color: var(--lg-text-1); }
|
|
.wn-tab.is-hover::after { opacity: 1; --lift: 0; --spot: .12; }
|
|
.wn-tabbar:not(.expanded) .wn-tab.is-hover::after { --hx: 50%; --hy: 40%; }
|
|
.wn-tab.is-focus { color: #fff; }
|
|
.wn-tab.is-focus::after { opacity: 1; --lift: var(--wn-focus-add); --spot: var(--wn-focus-spot); --hx: 50%; --hy: 26%; --spot-r: 85%; }
|
|
/* white labels on a bright focus fill: a soft shadow keeps them legible (contrast note in window-nav.md §13.1) */
|
|
.wn-tab.is-focus > .lbl, .wn-leg.is-focus { text-shadow: 0 1px 2px rgb(0 0 0 / .35); }
|
|
.wn-tab.is-focus::before { content: ""; position: absolute; left: 0; right: 0; top: calc((var(--p) - var(--d)) / 2); height: var(--d); border-radius: 999px; pointer-events: none; padding: 1.5px; z-index: 2;
|
|
background: conic-gradient(from var(--lg-light), rgb(255 255 255 / .85) 0deg, rgb(255 255 255 / .22) 40deg, transparent 75deg, transparent 145deg, rgb(255 255 255 / .22) 180deg, transparent 215deg, transparent 285deg, rgb(255 255 255 / .24) 320deg, rgb(255 255 255 / .85) 360deg);
|
|
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; }
|
|
.wn-tabbar:not(.expanded) .wn-tab.is-focus::before { right: auto; width: var(--d); }
|
|
/* the source of an open menu is white (Power while the Power menu shows) */
|
|
.wn-tab.is-open > .ic { background: var(--lg-fill-selected); color: var(--lg-text-on-selected); }
|
|
|
|
/* a receding ornament darkens (scene-graph tint / CSS scrim); it never fades to transparent */
|
|
.wn-dimmed::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: rgb(0 0 0 / .35); z-index: 4; pointer-events: none; }
|
|
|
|
/* ------------------------------------------------------------------ SteamVR window-bar row (systemui px; WN §3.5)
|
|
The frame controls (keyboard, float, theater, more [, close]) in one panel-glass capsule, sitting
|
|
left of the visionOS window-bar pill (SteamVR's grab handle moved up from under the dashboard bar):
|
|
one row directly under the window instead of two separate strata. */
|
|
.wn-frame { display: flex; align-items: center; gap: 14px; }
|
|
.wn-framecap { position: relative !important; display: flex; align-items: center; gap: 27px; height: 100px; padding: 0 10px; --r: 50px; box-sizing: border-box; }
|
|
/* circles rest quiet (fill .06, glyph .70; with SteamVR's idle dim .6 the glyph reads at .42, VP P-70)
|
|
and become full circles on hover (.14 = rest + .08, and the spot) or gamepad focus (+ .28, arc) */
|
|
.wn-framecap .lgk-btn { --s: 80px; background: rgb(255 255 255 / .06); color: var(--lg-text-2); }
|
|
.wn-framecap .lgk-btn.is-hover { background: rgb(255 255 255 / .14); color: #fff; }
|
|
.wn-framecap .lgk-btn.is-focus { color: #fff; }
|
|
.wn-framecap .lgk-btn::after { mix-blend-mode: normal; }
|
|
.wn-framecap .lgk-btn .lgk-i { --is: 36px; }
|
|
.wn-framecap .sep { width: 10px; }
|
|
.wn-framecap .lgk-btn.danger:is(.is-focus, .is-hover) { background: var(--lg-tint-danger) !important; color: #fff; }
|
|
.wn-framecap .lgk-btn.is-hover::after { --lift: 0; --spot: .12; }
|
|
.wn-framecap .lgk-btn.is-focus::after { --lift: var(--wn-focus-add); --spot: var(--wn-focus-spot); --hx: 50%; --hy: 28%; }
|
|
.wn-tip { position: absolute; white-space: nowrap; padding: 0 30px; height: 60px; display: flex; align-items: center;
|
|
font: 600 30px/1 var(--lg-font); --r: 30px; }
|
|
/* the visionOS window bar = SteamVR's grab handle: 467 x 32 grab px (140 x 9.6 mm) -> 183 x 12.5 view px */
|
|
.wn-pill { position: absolute; width: 183px; height: 12.5px; border-radius: 7px; background: rgb(255 255 255 / .46);
|
|
box-shadow: 0 1px 4px rgb(0 0 0 / .28), inset 0 1px 1px rgb(255 255 255 / .5); }
|
|
.wn-pill.hover { background: rgb(255 255 255 / .92); width: 198px; }
|
|
|
|
/* ------------------------------------------------------------------ dashboard bar (bar px, x1.20; system concept owns its content) */
|
|
.wn-bar { display: flex; gap: 16px; }
|
|
.wn-barcap { position: relative !important; height: 80px; gap: 8px; padding: 0 8px; --r: 40px; }
|
|
.wn-barcap .lgk-btn { --s: 64px; }
|
|
|
|
/* ------------------------------------------------------------------ the pointer proxy (T2, WN §3.6; native mode only, PLAN §1.11)
|
|
Drawn by the shell inside Steam's own DOM at the laser's hit point, so it is part of the texture
|
|
that every base crop and popped crop shows, whatever SteamVR does with its own dot. In CSS-only
|
|
mode it is not drawn (SteamVR's own dot shows): T1 mockups omit it. */
|
|
/* a 16 px ring with a 6 px core: where SteamVR's own dot also shows, the ring reads as its halo */
|
|
.wn-proxy { position: absolute; width: 16px; height: 16px; margin: -8px 0 0 -8px; border-radius: 50%; box-sizing: border-box; z-index: 52; pointer-events: none;
|
|
border: 2.5px solid rgb(255 255 255 / .95);
|
|
background: radial-gradient(circle, #fff 0 3px, transparent 3.5px);
|
|
box-shadow: 0 0 0 1.5px rgb(0 0 0 / .30), inset 0 0 0 1px rgb(0 0 0 / .18), 0 0 14px 4px rgb(255 255 255 / .40); }
|
|
|
|
/* ------------------------------------------------------------------ the item "More" circle (T2 helper owned by the shell, WN §3.4.4, PLAN §1.11)
|
|
60 px visible inside its host (cards: top right, inset 10; rows: trailing, inset 24) with an
|
|
80 px hit (transparent padding, not drawn); the clear material over content: black .38 + 10 px
|
|
blur; white .94 with a dark glyph while its menu is open. It rides its host's depth. */
|
|
.wn-more { position: absolute; width: 60px; height: 60px; display: grid; place-items: center; border-radius: 50%; z-index: 6; box-sizing: border-box;
|
|
color: #fff; background: rgb(0 0 0 / .38); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
|
|
box-shadow: inset 0 1.5px 1.5px -1px rgb(255 255 255 / .22), 0 2px 8px rgb(0 0 0 / .22); }
|
|
.wn-more .lgk-i { --is: 26px; }
|
|
.wn-more::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
|
|
background: radial-gradient(circle at var(--hx, 40%) var(--hy, 35%), rgb(255 255 255 / .12) 0, transparent 75%), rgb(255 255 255 / .08); }
|
|
.wn-more.is-hover::after { opacity: 1; }
|
|
.wn-more.is-open { background: var(--lg-fill-selected) !important; color: var(--lg-text-on-selected); -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
|
|
/* inside another glass container (the search sheet, a sheet): the fill only, no blur (no glass in glass, VP P-45) */
|
|
.wn-more.in-glass { -webkit-backdrop-filter: none; backdrop-filter: none; }
|
|
|
|
/* ------------------------------------------------------------------ menus, alerts and sheets: C1c's presentation recipe
|
|
(WN §5.1-§5.4, PLAN §1.4, §1.7, §1.8, §1.12; the `c1c-recipe` block of window-nav-menu.html, adopted here on
|
|
REQ C1c->C1a so area mockups that draw .wn-menu / .wn-alert / .wn-sheet get the same values). C1c owns the look;
|
|
change it there first. Focus on a white or coloured fill uses P4's --lgs-white-glow value (contracts/tokens.md). */
|
|
.lgk-view { --wn-dark: #0d0e12; --wn-red: rgb(255 66 69 / .92); --wn-white-glow: 0 0 22px 8px rgb(255 255 255 / .55); }
|
|
/* slab and rows (E-MENU) */
|
|
.wn-menu { padding: 8px; display: flex; flex-direction: column; gap: 6px; box-sizing: border-box; --r: 32px; }
|
|
.wn-menu .lgk-row { height: 72px; border-radius: 24px; padding: 0 22px 0 16px; gap: 16px; font: 500 24px/1.2 var(--lg-font); flex: none; }
|
|
.wn-menu.compact { gap: 4px; }
|
|
.wn-menu.compact .lgk-row { height: 60px; border-radius: 22px; } /* 60 visible on a 64 px pitch */
|
|
.wn-menu .lgk-row .lead { width: 28px; display: grid; place-items: center; --is: 26px; flex: none; color: var(--lg-text-1); } /* symbol (actions) or check (values) */
|
|
.wn-menu .lgk-row .lead.check .lgk-i { --is: 24px; stroke-width: 3; }
|
|
.wn-menu .lgk-row .trail .lgk-i { --is: 22px; }
|
|
.wn-menu .sep, .wn-menu .gap { height: 6px; flex: none; } /* Steam's separator = space, no line */
|
|
.wn-menu .hdr { display: flex; align-items: center; box-sizing: border-box; height: 40px; padding: 4px 20px 0; font: 700 22px/1 var(--lg-font); color: var(--lg-text-2); flex: none; }
|
|
.wn-menu .ihdr { display: flex; align-items: flex-end; box-sizing: border-box; height: 26px; padding: 0 0 4px 18px; font: 600 19px/1 var(--lg-font); color: var(--lg-text-3); flex: none; }
|
|
/* legacy: a trailing check (revision 2). C1c's rule is the leading .lead.check; kept only so area mockups not yet moved still render */
|
|
.wn-menu .lgk-row .chk { margin-left: auto; --is: 24px; color: var(--lg-text-1); }
|
|
/* Steam's Cancel item: a 56 px quiet capsule (PLAN §1.12, HA-11) */
|
|
.wn-menu .cancel { align-self: center; flex: none; --s: 56px; padding: 0 44px; margin-top: 6px; background: rgb(255 255 255 / .08);
|
|
color: var(--lg-text-2); font: 500 22px/1 var(--lg-font); }
|
|
.wn-menu .cols2 { display: grid; grid-template-columns: 1fr 1fr; grid-auto-flow: column; gap: 6px 8px; }
|
|
.wn-menu .cols2 .lgk-row { min-width: 0; }
|
|
.wn-menu .cols2 .lgk-row .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
/* states (PLAN §1.4): laser hover = + .08 and a .12 spot at the pointer, no arc; gamepad focus = + .28 uniform,
|
|
a static .16 spot in the upper third, the control's own arc x1.5 */
|
|
:is(.wn-menu, .wn-alert, .wn-sheet) :is(.lgk-row, .lgk-btn).is-hover::after { opacity: 1; --lift: .08; --spot: .12; }
|
|
:is(.wn-menu, .wn-alert, .wn-sheet) :is(.lgk-row, .lgk-btn).is-focus::after { opacity: 1; --lift: .28; --spot: .16; --hx: 50%; --hy: 16%; }
|
|
:is(.wn-menu, .wn-alert, .wn-sheet) :is(.lgk-row, .lgk-btn).is-focus::before {
|
|
background: conic-gradient(from var(--lg-light), rgb(255 255 255 / .9) 0deg, rgb(255 255 255 / .3) 40deg, transparent 75deg, transparent 145deg,
|
|
rgb(255 255 255 / .3) 180deg, transparent 215deg, transparent 285deg, rgb(255 255 255 / .3) 320deg, rgb(255 255 255 / .9) 360deg); }
|
|
/* tones (WN §5.1.2 + CC §7: text on a coloured fill is dark; white only on blue) */
|
|
.wn-menu .lgk-row.primary, .wn-menu .lgk-row.primary.play { background: linear-gradient(180deg, rgb(255 255 255 / .16), rgb(255 255 255 / 0) 60%), var(--lg-tint-play); color: var(--wn-dark); font-weight: 600; }
|
|
.wn-menu .lgk-row.primary.install { background: linear-gradient(180deg, rgb(255 255 255 / .16), rgb(255 255 255 / 0) 60%), var(--lg-tint-primary); color: #fff; font-weight: 500; }
|
|
.wn-menu .lgk-row.primary .lead { color: var(--wn-dark); }
|
|
.wn-menu .lgk-row.primary.install .lead { color: #fff; }
|
|
.wn-menu .lgk-row.danger { color: var(--lg-red); font-weight: 600; } /* <= 2 destructive rows: red label */
|
|
.wn-menu .lgk-row:is(.danger, .danger-glyph) .lead { color: var(--lg-red); } /* > 2 (Power): red glyph, white label */
|
|
.wn-menu .lgk-row:is(.danger, .danger-glyph).is-focus { background: linear-gradient(180deg, rgb(255 255 255 / .14), rgb(255 255 255 / 0) 60%), var(--wn-red);
|
|
color: var(--wn-dark); font-weight: 600; }
|
|
.wn-menu .lgk-row:is(.danger, .danger-glyph).is-focus .lead { color: var(--wn-dark); }
|
|
.wn-menu .lgk-row:is(.danger, .danger-glyph, .primary).is-focus::after { --lift: .04; --spot: .10; }
|
|
/* focus on a white or coloured fill: a blurred outer glow, never a ring (P-16) */
|
|
:is(.wn-menu, .wn-alert, .wn-sheet) .is-focus:is(.primary, .danger, .danger-glyph, .is-selected, .red) { box-shadow: var(--wn-white-glow); }
|
|
/* source card while its menu is open (PLAN §1.7): 0 mm with a CSS glow, unless it was the gamepad-focused card */
|
|
.lgk-view .src-glow { box-shadow: 0 10px 28px rgb(0 0 0 / .42), 0 0 26px 3px rgb(255 255 255 / .20) !important; }
|
|
/* alerts and sheets (WN §5.3, §5.4; PLAN §1.12): alerts 640 wide, centred on the glass; sheets <= 960 */
|
|
.wn-alert { width: 640px; padding: 36px 36px 28px; --r: 44px; box-sizing: border-box; }
|
|
.wn-alert .t { font: 700 28px/1.25 var(--lg-font); letter-spacing: -.01em; }
|
|
.wn-alert .b { margin-top: 12px; font: 500 22px/1.36 var(--lg-font); color: var(--lg-text-2); }
|
|
.wn-alert .btns { display: flex; gap: 16px; margin-top: 30px; }
|
|
.wn-alert .btns .lgk-btn { flex: 1; --s: 60px; }
|
|
:is(.wn-alert, .wn-sheet) .lgk-btn.red { background: linear-gradient(180deg, rgb(255 255 255 / .16), rgb(255 255 255 / 0) 55%), var(--wn-red); color: var(--wn-dark); }
|
|
.wn-sheet { --r: 44px; box-sizing: border-box; }
|
|
|
|
/* ------------------------------------------------------------------ search sheet (WN §4) */
|
|
.wn-snap { position: absolute; inset: 0; pointer-events: none; } /* the context snapshot: inert decorative clone */
|
|
.wn-ssheet { --r: 44px; box-sizing: border-box; }
|
|
.wn-ssheet .sh { position: absolute; left: 40px; font: 700 26px/1 var(--lg-font); letter-spacing: -.01em; }
|
|
|
|
/* ------------------------------------------------------------------ keyboard (Steam VR keyboard, keyboard px x0.74) */
|
|
.wn-kb { position: relative !important; width: 854px; padding: 8px; --r: 30px; box-sizing: border-box; }
|
|
.wn-kb .echo { display: flex; align-items: center; gap: 12px; height: 46px; margin: 0 4px 6px; padding: 0 22px; border-radius: 26px;
|
|
background: rgb(0 0 0 / .30); box-shadow: inset 0 2px 5px rgb(0 0 0 / .26); font: 500 26px/1 var(--lg-font); }
|
|
.wn-kb .echo .lbl { color: var(--lg-text-2); font-size: 22px; font-weight: 600; }
|
|
.wn-kb .echo .ph { color: rgb(255 255 255 / .5); }
|
|
.wn-kb .row { display: flex; gap: 6px; margin-top: 6px; }
|
|
.wn-kb .k { flex: 1; height: 42px; border-radius: 11px; background: rgb(255 255 255 / .13); display: grid; place-items: center;
|
|
font: 500 21px/1 var(--lg-font); color: var(--lg-text-1); }
|
|
.wn-kb .k.w15 { flex: 1.5; } .wn-kb .k.w2 { flex: 2; } .wn-kb .k.w6 { flex: 6.4; }
|
|
.wn-kb .k.dark { background: rgb(255 255 255 / .06); color: var(--lg-text-2); font-size: 18px; font-weight: 600; }
|
|
.wn-kb .k.enter { background: var(--lg-tint-primary); color: #fff; font-size: 18px; font-weight: 700; }
|
|
.wn-kb .k.hot { background: #fff; color: #0d0e12; }
|
|
|
|
/* ------------------------------------------------------------------ toast (notifications quad, popup px) */
|
|
.wn-toast { position: relative !important; width: 320px; height: 76px; --r: 30px; display: flex; align-items: center; gap: 14px; padding: 0 18px 0 14px; box-sizing: border-box; }
|
|
.wn-toast .ic { width: 48px; height: 48px; border-radius: 50%; flex: none; display: grid; place-items: center; color: #fff; --is: 26px;
|
|
box-shadow: inset 0 1px 1px rgb(255 255 255 / .35); }
|
|
.wn-toast .tt { font: 600 20px/1.3 var(--lg-font); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.wn-toast .bd { font: 500 18px/1.3 var(--lg-font); color: var(--lg-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
|
|
/* ------------------------------------------------------------------ figure captions (outside the scene) */
|
|
.wn-cap { position: absolute; z-index: 60; font: 600 18px/1.3 var(--lg-font); color: #fff; padding: 8px 14px; border-radius: 12px;
|
|
background: rgb(0 0 0 / .55); }
|
|
.wn-cap b { font-weight: 700; }
|
|
.wn-cap .m { font-weight: 500; color: rgb(255 255 255 / .75); }
|