mirror of
https://github.com/MichaelScottsman/LiquidAss-Frame.git
synced 2026-10-24 21:01:18 +02:00
Squeezed by the bar's animating width, Steam's label marquee started mid-open and stayed on (its 24 px of scroll padding then never fitted). Labels keep their own width while the bar slides (flex-shrink 0, the bar's edge clips them meanwhile) and Steam's 160 px cap goes. Verified: open 281 px with no clipped label, collapsed 76 px as before. Seen in a headset-view grab.
1303 lines
57 KiB
CSS
1303 lines
57 KiB
CSS
/* Glass Shell, area "shell" (package C1a, Phase 2): the window and its
|
|
chrome on every main route, the tab-bar ornament (frame.menu), the
|
|
bottom ornament contract (#Footer).
|
|
Concept: docs/phase2/concepts/window-nav.md (WN) §3, §8.4; PLAN §1.2,
|
|
§1.3, §1.9-§1.11. Evidence: docs/phase2/wp/C1a.md.
|
|
Wrapped as html.lgs-on { ... } by the bundler ("&" is html.lgs-on).
|
|
|
|
T1 only here. Rules keyed on attributes or classes that C1a's runtime
|
|
(device/rt/20-shell.js, flag wp.c1a) sets are inert until it runs:
|
|
html.lgs-hdr-108 / html.lgs-hdr-40 CQ1 outcome (none = fallback)
|
|
%{BasicUiRoot}[data-lgs-glass] route glass mode (none = window)
|
|
%{BasicUiRoot}[data-lgs-route] route key
|
|
%{BasicUiRoot}[data-lgs-search] capsule | nested | circle
|
|
#Footer[data-lgs-orn="capsule"|"quiet"] ornament material by content
|
|
#Footer[data-lgs-orn-fixed] area-registered fixed slots
|
|
#Footer[data-lgs-band="off"] flag quietBacking = "off"
|
|
#Footer [data-lgs-btn="<enum>"] member tags (OK, CANCEL, ...)
|
|
[data-lgs-exempt="E-BACK"] Back shown as a circle (T2
|
|
sets aria-label = stock text)
|
|
Shared values other areas read (WN §3.2, C1a's interface table):
|
|
--lgs-hdr-pad page-root top padding: 68px fallback, 0 with lgs-hdr-108
|
|
--lgs-guard-top 124px, --lgs-guard-bottom 596px (window y, VP P-23:
|
|
16 px above the ornament capsule's top, 612)
|
|
--lgs-c1a-tint the window tint on %{BasicUiRoot}; the name is frozen
|
|
(C3b's CC-M sets it transparent, REQ C3b->C1a)
|
|
Tokens: contracts/tokens.md (P4). Private values are --lgs-c1a-*.
|
|
No outlines anywhere: edges come from P4's E3 hook and the material. */
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* 0. Interface values */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
& {
|
|
--lgs-hdr-pad: 68px;
|
|
--lgs-guard-top: 124px;
|
|
--lgs-guard-bottom: 596px;
|
|
/* the tab bar's pitch (popup px) until the daemon writes the live one
|
|
(WN §3.3.2): 52 is the floor and fits the panel at every r >= 0.863 */
|
|
--lgs-c1a-tab-p: var(--lgs-tab-pitch, 52px);
|
|
}
|
|
&.lgs-hdr-108 {
|
|
--lgs-hdr-pad: 0px;
|
|
}
|
|
/* CQ1 (WN §3.2, AT-2): the runtime tries the 108 px header only behind the
|
|
flag hdr108 (html.lgs-hdr-try for two frames) and keeps it as
|
|
lgs-hdr-108 only if Steam's header box follows the variable */
|
|
&:is(.lgs-hdr-try, .lgs-hdr-108) %{BasicUiRoot} {
|
|
--basicui-header-height: 108px !important;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* 1. Window glass by route mode (PLAN §1.2, WN §3.1, §8.4) */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/* The glass height follows the route's mode, never focus. No attribute
|
|
(runtime off) = window. --lgs-c1a-gh is read by the tint, the edge and
|
|
the content clip below. */
|
|
%{BasicUiRoot} {
|
|
--lgs-c1a-gh: var(--lgs-glass-h);
|
|
/* the bottom ornament straddles the glass edge centred, as visionOS
|
|
attaches a bottom toolbar: Steam's legend row (y 628-712) is lifted
|
|
16 px to y 612-696 (44 px on the glass, 40 below it, clear of
|
|
SteamVR's frame controls and their tooltips); page content ends 8 px
|
|
above the capsule (y 604), so nothing runs under it */
|
|
--lgs-c1a-orn-lift: 16px;
|
|
--lgs-c1a-cut: calc(var(--lgs-ornament-y, 628px) - var(--lgs-c1a-orn-lift) - 8px);
|
|
/* the smoky tint (WN §8.4) as the root's own background, sized to the
|
|
glass, so it sits under every page and the audit's contrast model
|
|
(ancestor backgrounds over the room) sees it; the margin stays clear */
|
|
/* P4's window tint: .60-.84 by the dial, .94 in High Contrast (FD-6,
|
|
G-A11Y; REQ P4->C1a) */
|
|
--lgs-c1a-tint: var(--lgs-mat-window-tint);
|
|
--lgs-c1a-r: var(--lgs-r-window);
|
|
/* the toolbar plates' edge on windowless routes (CSS-only look): E4/E5,
|
|
the lit top lip, a soft contact shadow; never a closed line */
|
|
--lgs-c1a-plate-shade: var(--lgs-mat-liquid-shade), inset 0 1.5px 1.5px -1px rgb(255 255 255 / .26), 0 4px 14px rgb(0 0 0 / .30);
|
|
/* four tiles: the body, the bottom band between the corners, and the two
|
|
rounded bottom corners at the glass edge (the root's own radius rounds
|
|
the 720 box, not the 656 glass) */
|
|
background:
|
|
linear-gradient(var(--lgs-c1a-tint), var(--lgs-c1a-tint)) 0 0 / 100% max(0px, calc(var(--lgs-c1a-gh) - var(--lgs-c1a-r))) no-repeat,
|
|
linear-gradient(var(--lgs-c1a-tint), var(--lgs-c1a-tint)) var(--lgs-c1a-r) max(0px, calc(var(--lgs-c1a-gh) - var(--lgs-c1a-r))) / calc(100% - 2 * var(--lgs-c1a-r)) min(var(--lgs-c1a-r), var(--lgs-c1a-gh)) no-repeat,
|
|
radial-gradient(circle var(--lgs-c1a-r) at 100% 0, var(--lgs-c1a-tint) calc(var(--lgs-c1a-r) - .75px), rgb(20 22 30 / 0) var(--lgs-c1a-r)) 0 max(0px, calc(var(--lgs-c1a-gh) - var(--lgs-c1a-r))) / var(--lgs-c1a-r) min(var(--lgs-c1a-r), var(--lgs-c1a-gh)) no-repeat,
|
|
radial-gradient(circle var(--lgs-c1a-r) at 0 0, var(--lgs-c1a-tint) calc(var(--lgs-c1a-r) - .75px), rgb(20 22 30 / 0) var(--lgs-c1a-r)) 100% max(0px, calc(var(--lgs-c1a-gh) - var(--lgs-c1a-r))) / var(--lgs-c1a-r) min(var(--lgs-c1a-r), var(--lgs-c1a-gh)) no-repeat;
|
|
border-radius: var(--lgs-r-window);
|
|
/* E3 arcs from P4's edge hook on ::before (z 20000, above content) */
|
|
--lgs-edge: window;
|
|
}
|
|
%{BasicUiRoot}[data-lgs-glass="window-full"] {
|
|
--lgs-c1a-gh: var(--lgs-glass-h-full);
|
|
}
|
|
%{BasicUiRoot}[data-lgs-glass="windowless"],
|
|
%{BasicUiRoot}:has(> %{MainNavMenuMainSplit} > %{BasicHome}%{PopupBody>TransparentBackground}) {
|
|
--lgs-c1a-gh: 0px;
|
|
--lgs-edge: none;
|
|
}
|
|
|
|
/* the edge hook's ring ends where the glass ends (656 or 720) */
|
|
%{BasicUiRoot}::before {
|
|
bottom: calc(100% - var(--lgs-c1a-gh));
|
|
}
|
|
|
|
/* the window's top sheen (white .08 -> 0 over 30 %) and dark inner edge,
|
|
over the tint and under every page (z -1 in the root's own stacking
|
|
context) */
|
|
%{BasicUiRoot}::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: var(--lgs-c1a-gh);
|
|
border-radius: inherit;
|
|
background: linear-gradient(180deg, rgb(255 255 255 / .08) 0, rgb(255 255 255 / 0) 30%);
|
|
box-shadow: var(--lgs-mat-window-shade);
|
|
pointer-events: none;
|
|
z-index: -1;
|
|
}
|
|
%{BasicUiRoot}[data-lgs-glass="windowless"]::after,
|
|
%{BasicUiRoot}:has(> %{MainNavMenuMainSplit} > %{BasicHome}%{PopupBody>TransparentBackground})::after {
|
|
content: none;
|
|
}
|
|
|
|
/* Backdrop root just inside the glass, so blurred controls (ornament,
|
|
sheets) frost page content, never the window tint twice. A rendering
|
|
hint only: no layout, no containing block, z-order unchanged. */
|
|
%{MainNavMenuMainSplit} {
|
|
will-change: opacity;
|
|
}
|
|
|
|
/* The page's clip: on `window` and `hero` routes content ends 8 px above
|
|
the ornament capsule (y 604, --lgs-c1a-cut), so it never runs under the
|
|
capsule's upper half or below the glass edge into the room. The band
|
|
604-656 is clear window glass the capsule straddles. Hit testing below
|
|
612 is the ornament's. */
|
|
%{BasicUiRoot}:not([data-lgs-glass="window-full"], [data-lgs-glass="windowless"]) > %{MainNavMenuMainSplit} > %{BasicHome}:not(%{PopupBody>TransparentBackground}) {
|
|
clip-path: inset(0 0 calc(100% - var(--lgs-c1a-cut)) 0);
|
|
}
|
|
|
|
/* Every layer that repaints Steam's opaque gradient (or black) over the
|
|
window goes clear, so the glass shows on every route. Page roots that
|
|
areas own are cleared by those areas (LAB). */
|
|
%{BasicHome}%{OpaqueBackground},
|
|
%{BasicHome}%{TrueBlackBackground},
|
|
%{BasicUiRoot}%{PopupBody>BlackBackground},
|
|
%{GamepadLibrary},
|
|
%{DownloadsPage},
|
|
%{OverflowHidden>GamepadPage}%{DialogBackground},
|
|
%{ContentManagement},
|
|
%{TopLevelTransitionSwitch},
|
|
%{ContentWrapper}%{TopLevelTransition},
|
|
%{AbsoluteDiv} {
|
|
background: none;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* 2. The toolbar row (#header, WN §3.2, PLAN §1.9) */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/* Fallback (no lgs-hdr-108): the header stays 40 px in layout and its
|
|
controls overflow into a 68 px band below; page roots add
|
|
var(--lgs-hdr-pad) (each area pads its own), the scroll guard keeps
|
|
focus clear, and C1c pads modals to 108 (22-presentations.css). With
|
|
lgs-hdr-108 the header is 108 tall and the same positions hold. */
|
|
|
|
/* Steam's header band (its ::before: 50 % black + 100 px blur) becomes the
|
|
scroll edge: a 124 px band of black .30 -> 0, blurred, fading out;
|
|
its opacity stays bound to Steam's --gamepadui-header-background-opacity */
|
|
#header%{Profile>Header}::before {
|
|
bottom: auto;
|
|
height: var(--lgs-scroll-band-h);
|
|
background: var(--lgs-scroll-band-top);
|
|
backdrop-filter: blur(12px);
|
|
-webkit-mask-image: linear-gradient(180deg, #000 40%, transparent);
|
|
mask-image: linear-gradient(180deg, #000 40%, transparent);
|
|
box-shadow: none;
|
|
}
|
|
/* windowless routes (Home, folders, /invites, CC-M) have no window and no
|
|
scroller under the row, so there is no scroll edge to draw: the band
|
|
would only blur the page's own top-row plates (REQ C2a->C1a #10) */
|
|
%{BasicUiRoot}[data-lgs-glass="windowless"] #header%{Profile>Header}::before {
|
|
background: none;
|
|
backdrop-filter: none;
|
|
}
|
|
|
|
/* Back: an 80 x 80 hit box at (14, 14), its 60 px glass control at
|
|
(24, 24) (VP P-60). T1 keeps Steam's "Back" text beside the chevron
|
|
(a 60 px capsule); with T2's E-BACK tag (aria-label = the stock text)
|
|
the label collapses and the control is the 60 px circle. */
|
|
#header %{BackContainer} {
|
|
position: absolute;
|
|
left: 14px;
|
|
top: 14px;
|
|
height: var(--lgs-hit);
|
|
min-width: var(--lgs-hit);
|
|
box-sizing: border-box;
|
|
padding: 0 10px;
|
|
justify-content: center;
|
|
isolation: isolate;
|
|
color: var(--lgs-text-1);
|
|
pointer-events: auto;
|
|
}
|
|
#header %{BackContainer}::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 10px;
|
|
z-index: -1;
|
|
border-radius: var(--lgs-r-capsule);
|
|
background: var(--lgs-raised-bg);
|
|
box-shadow: var(--lgs-raised-shadow);
|
|
pointer-events: none;
|
|
transition: background var(--lgs-d-hover-in, 294ms) var(--lgs-ease-b0, ease-out);
|
|
}
|
|
/* laser hover: + white .08 (Steam's ::after is its divider, so the light
|
|
is drawn on the control's own fill) */
|
|
&:not(.lgs-input-pad) #header %{BackContainer}:hover::before {
|
|
background: linear-gradient(rgb(255 255 255 / var(--lgs-hover-add)), rgb(255 255 255 / var(--lgs-hover-add))), var(--lgs-raised-bg);
|
|
}
|
|
#header %{BackContainer}:active::before {
|
|
background: linear-gradient(rgb(255 255 255 / calc(var(--lgs-hover-add) + var(--lgs-press-add))), rgb(255 255 255 / calc(var(--lgs-hover-add) + var(--lgs-press-add)))), var(--lgs-raised-bg);
|
|
}
|
|
/* Steam's divider between Back and search: the gap replaces it */
|
|
#header %{BackContainer}:not(:last-child)::after {
|
|
background: transparent;
|
|
}
|
|
#header %{BackContainer} %{ArrowBack} {
|
|
width: 28px;
|
|
height: 28px;
|
|
margin: 0;
|
|
flex: none;
|
|
}
|
|
#header %{BackContainer>BackButton} {
|
|
padding: 0 14px 0 8px;
|
|
font: var(--lgs-type-callout);
|
|
letter-spacing: 0;
|
|
text-transform: none;
|
|
color: inherit;
|
|
}
|
|
/* T2: the circle (E-BACK) */
|
|
#header %{BackContainer}[data-lgs-exempt="E-BACK"] {
|
|
width: var(--lgs-hit);
|
|
padding: 0;
|
|
}
|
|
#header %{BackContainer}[data-lgs-exempt="E-BACK"] %{BackContainer>BackButton} {
|
|
width: 0;
|
|
padding: 0;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
}
|
|
/* the Back reveal (T2): after 0.6 s of attention the circle grows into a
|
|
capsule naming the page Back returns to (WN §3.2). The box takes the
|
|
text's width at once (no layout animation, LAB) and the chevron keeps
|
|
its place; the glass grows out of the circle with P5's clip morph on
|
|
`snappy`; the Large Title leaves first (150 ms) and the label comes in
|
|
after it on `fade`, so the two never overlap. Leaving: the label goes at
|
|
once and the glass slides back into the circle on `snappy` (T2, Web
|
|
Animations). Reduce Motion: lgs-morph is P5's plain fade (P-56) */
|
|
#header %{BackContainer}[data-lgs-exempt="E-BACK"] {
|
|
width: auto;
|
|
min-width: var(--lgs-hit);
|
|
}
|
|
#header %{BackContainer} > .lgs-back-reveal {
|
|
display: block;
|
|
max-width: 0;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
opacity: 0;
|
|
font: var(--lgs-type-callout);
|
|
font-weight: 600;
|
|
letter-spacing: 0;
|
|
color: var(--lgs-text-1);
|
|
transition: opacity var(--lgs-motion-fade, 441ms ease);
|
|
}
|
|
#header %{BackContainer}[data-lgs-reveal] > .lgs-back-reveal {
|
|
max-width: 320px;
|
|
padding-left: 4px;
|
|
padding-right: 26px;
|
|
opacity: 1;
|
|
transition: none;
|
|
/* an animation, not a transition: the label node is new on the first
|
|
reveal, and a new node never transitions */
|
|
animation: lgs-fade-in var(--lgs-motion-fade, 441ms ease) var(--lgs-d-page-out, 150ms) backwards;
|
|
}
|
|
#header %{BackContainer}[data-lgs-reveal]::before {
|
|
--sx: 0px;
|
|
--sy: 0px;
|
|
--sw: 60px;
|
|
--sh: 60px;
|
|
--sr: 30px;
|
|
--lgs-morph-r: 30px;
|
|
animation: lgs-morph var(--lgs-motion-snappy, 488ms ease) backwards;
|
|
}
|
|
/* the chevron stays where the circle centred it (80 - 28) / 2 = 26 */
|
|
#header %{BackContainer}[data-lgs-reveal] {
|
|
justify-content: flex-start;
|
|
padding-left: 26px;
|
|
}
|
|
/* the Large Title steps back while the reveal names the way back: out in
|
|
150 ms (before the label comes in), back on `fade` */
|
|
#header > .lgs-title {
|
|
transition: opacity var(--lgs-motion-fade, 441ms ease);
|
|
}
|
|
#header[data-lgs-reveal] > .lgs-title {
|
|
opacity: 0;
|
|
transition: opacity var(--lgs-motion-page-out, 150ms linear);
|
|
}
|
|
/* section roots (T2 route map): borderless, chevron white .70 */
|
|
%{BasicUiRoot}[data-lgs-back="root"] #header %{BackContainer}::before {
|
|
background: none;
|
|
box-shadow: none;
|
|
}
|
|
%{BasicUiRoot}[data-lgs-back="root"] #header %{BackContainer} {
|
|
color: var(--lgs-text-2);
|
|
}
|
|
%{BasicUiRoot} #header %{BackContainer}:is([data-lgs-reveal], [data-lgs-unreveal])::before {
|
|
background: var(--lgs-raised-bg);
|
|
box-shadow: var(--lgs-raised-shadow);
|
|
}
|
|
%{BasicUiRoot} #header %{BackContainer}[data-lgs-reveal] {
|
|
color: var(--lgs-text-1);
|
|
}
|
|
/* hero routes: clear glass over the art (black .32 + 10 px blur) */
|
|
%{BasicUiRoot}[data-lgs-glass="hero"] #header %{BackContainer}::before {
|
|
background: rgb(0 0 0 / .32);
|
|
backdrop-filter: blur(10px);
|
|
box-shadow: var(--lgs-mat-clear-shade);
|
|
}
|
|
/* windowless routes (Home, folders, /invites; WN §3.2): no window behind
|
|
the row, so Back is a plate over the room in CSS-only mode (P4's plate:
|
|
black .58 under white .16 -> .04, the E4/E5 dark edge, the lit top lip
|
|
and a soft contact shadow), also as a section root; glassd's liquid
|
|
plate shell-back takes its place in native mode (§4c). REQ C2a-R2->C1a */
|
|
%{BasicUiRoot}[data-lgs-glass="windowless"] #header %{BackContainer}::before,
|
|
%{BasicUiRoot}[data-lgs-glass="windowless"][data-lgs-back] #header %{BackContainer}::before {
|
|
background: var(--lgs-mat-plate-bg);
|
|
box-shadow: var(--lgs-c1a-plate-shade);
|
|
}
|
|
%{BasicUiRoot}[data-lgs-glass="windowless"] #header %{BackContainer} {
|
|
color: var(--lgs-text-1);
|
|
}
|
|
&:not(.lgs-input-pad) %{BasicUiRoot}[data-lgs-glass="windowless"] #header %{BackContainer}:hover::before {
|
|
background: linear-gradient(rgb(255 255 255 / var(--lgs-hover-add)), rgb(255 255 255 / var(--lgs-hover-add))), var(--lgs-mat-plate-bg);
|
|
}
|
|
%{BasicUiRoot}[data-lgs-glass="windowless"] #header %{BackContainer}:active::before {
|
|
background: linear-gradient(rgb(255 255 255 / calc(var(--lgs-hover-add) + var(--lgs-press-add))), rgb(255 255 255 / calc(var(--lgs-hover-add) + var(--lgs-press-add)))), var(--lgs-mat-plate-bg);
|
|
}
|
|
|
|
/* Search field: one container, three variants (PLAN §1.9). The capsule
|
|
(default, section roots): 520 x 64 centred at x 640, y 54, in a
|
|
536 x 80 hit box; recessed (black .30 + inset shadow); no microphone. */
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} {
|
|
--lgs-c1a-sw: var(--lgs-search-w);
|
|
position: absolute;
|
|
top: 14px;
|
|
left: calc(640px - var(--lgs-c1a-sw) / 2 - 8px);
|
|
width: calc(var(--lgs-c1a-sw) + 16px);
|
|
height: var(--lgs-hit);
|
|
flex: none;
|
|
box-sizing: border-box;
|
|
padding: 0;
|
|
pointer-events: auto;
|
|
}
|
|
%{BasicUiRoot}[data-lgs-search="nested"] #header %{SearchAndTitleContainer}%{ShowingSearch} {
|
|
--lgs-c1a-sw: var(--lgs-search-w-nested);
|
|
}
|
|
/* settings routes (SET §3.4 fallback, REQ C6a->C1a): the capsule centres
|
|
over the detail pane (x 840: visible 580-1100), clear of the 400 px
|
|
sidebar, until the circle variant ships (searchCircle) */
|
|
%{BasicUiRoot}[data-lgs-route="settings"][data-lgs-search="capsule"] #header %{SearchAndTitleContainer}%{ShowingSearch} {
|
|
left: calc(840px - var(--lgs-c1a-sw) / 2 - 8px);
|
|
}
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchFieldBackground},
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchFieldBackground}%{WhiteBackground} {
|
|
top: 8px;
|
|
bottom: 8px;
|
|
left: 8px;
|
|
right: 8px;
|
|
height: auto;
|
|
width: auto;
|
|
border-radius: var(--lgs-r-capsule);
|
|
background: var(--lgs-fill-thick);
|
|
box-shadow: var(--lgs-recessed-shadow);
|
|
transition: box-shadow var(--lgs-d-hover-in, 294ms) var(--lgs-ease-b0, ease-out);
|
|
}
|
|
/* laser hover: + white .08 on the well */
|
|
&:not(.lgs-input-pad) #header %{SearchAndTitleContainer}%{ShowingSearch}:hover %{SearchFieldBackground} {
|
|
background: linear-gradient(rgb(255 255 255 / var(--lgs-hover-add)), rgb(255 255 255 / var(--lgs-hover-add))), var(--lgs-fill-thick);
|
|
}
|
|
/* focus: the system's only ring (VP P-17), in both input modes, each by
|
|
its own signal (P-01/P-02: a stale .gpfocuswithin never rings under the
|
|
laser; the laser's ring is the typing caret's DOM focus) */
|
|
&:not(.lgs-input-laser) #header %{SearchAndTitleContainer}%{ShowingSearch}.gpfocuswithin %{SearchFieldBackground},
|
|
&:not(.lgs-input-pad) #header %{SearchAndTitleContainer}%{ShowingSearch}:focus-within %{SearchFieldBackground} {
|
|
box-shadow: var(--lgs-recessed-shadow), var(--lgs-field-focus);
|
|
}
|
|
/* windowless routes: the field is a plate over the room (WN §3.2; glassd's
|
|
shell-search plate in native mode, §4c), not a well over nothing */
|
|
%{BasicUiRoot}[data-lgs-glass="windowless"] #header %{SearchAndTitleContainer}%{ShowingSearch} :is(%{SearchFieldBackground}, %{SearchFieldBackground}%{WhiteBackground}) {
|
|
background: var(--lgs-mat-plate-bg);
|
|
box-shadow: var(--lgs-c1a-plate-shade);
|
|
}
|
|
&:not(.lgs-input-pad) %{BasicUiRoot}[data-lgs-glass="windowless"] #header %{SearchAndTitleContainer}%{ShowingSearch}:hover %{SearchFieldBackground} {
|
|
background: linear-gradient(rgb(255 255 255 / var(--lgs-hover-add)), rgb(255 255 255 / var(--lgs-hover-add))), var(--lgs-mat-plate-bg);
|
|
}
|
|
&:not(.lgs-input-laser) %{BasicUiRoot}[data-lgs-glass="windowless"] #header %{SearchAndTitleContainer}%{ShowingSearch}.gpfocuswithin %{SearchFieldBackground},
|
|
&:not(.lgs-input-pad) %{BasicUiRoot}[data-lgs-glass="windowless"] #header %{SearchAndTitleContainer}%{ShowingSearch}:focus-within %{SearchFieldBackground} {
|
|
box-shadow: var(--lgs-c1a-plate-shade), var(--lgs-field-focus);
|
|
}
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchIconLeft},
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchIconLeft}%{WhiteBackground} {
|
|
top: 27px;
|
|
bottom: auto;
|
|
left: 28px;
|
|
width: var(--lgs-symbol);
|
|
height: var(--lgs-symbol);
|
|
color: var(--lgs-text-2);
|
|
}
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchIconRight},
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchIconRight}%{WhiteBackground} {
|
|
top: 29px;
|
|
bottom: auto;
|
|
color: var(--lgs-text-2);
|
|
}
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchBox},
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchBox}%{WhiteBackground} {
|
|
height: 100%;
|
|
padding: 0 18px 0 62px;
|
|
font: var(--lgs-type-body);
|
|
letter-spacing: 0;
|
|
color: var(--lgs-text-1);
|
|
caret-color: var(--lgs-text-1);
|
|
text-shadow: none;
|
|
}
|
|
#header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchBox}::placeholder {
|
|
color: var(--lgs-text-2);
|
|
font-style: normal;
|
|
}
|
|
/* the clear button: a 44 px mini circle (E-MINI) */
|
|
#header %{SearchAndTitleContainer} %{SearchBox}::-webkit-search-cancel-button {
|
|
-webkit-appearance: none;
|
|
width: var(--lgs-btn-sm);
|
|
height: var(--lgs-btn-sm);
|
|
border-radius: 50%;
|
|
background-color: rgb(255 255 255 / .16);
|
|
box-shadow: none;
|
|
}
|
|
&:not(.lgs-input-pad) #header %{SearchAndTitleContainer} %{SearchBox}::-webkit-search-cancel-button:hover {
|
|
background-color: rgb(255 255 255 / calc(.16 + var(--lgs-hover-add)));
|
|
}
|
|
/* the circle variant (Home, hero routes, Settings, /account, ...): a
|
|
60 px magnifier circle in an 80 x 80 box at (1186, 14) */
|
|
%{BasicUiRoot}[data-lgs-search="circle"] #header %{SearchAndTitleContainer}%{ShowingSearch} {
|
|
left: auto;
|
|
right: 14px;
|
|
width: var(--lgs-hit);
|
|
padding: 0;
|
|
}
|
|
%{BasicUiRoot}[data-lgs-search="circle"] #header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchFieldBackground} {
|
|
inset: 10px;
|
|
background: var(--lgs-raised-bg);
|
|
box-shadow: var(--lgs-raised-shadow);
|
|
}
|
|
%{BasicUiRoot}[data-lgs-search="circle"] #header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchIconLeft} {
|
|
left: 27px;
|
|
}
|
|
%{BasicUiRoot}[data-lgs-search="circle"][data-lgs-glass="hero"] #header %{SearchAndTitleContainer}%{ShowingSearch} %{SearchFieldBackground} {
|
|
background: rgb(0 0 0 / .32);
|
|
backdrop-filter: blur(10px);
|
|
box-shadow: var(--lgs-mat-clear-shade);
|
|
}
|
|
|
|
/* Title mode (calibration, device support, ...): Title 2 centred on the
|
|
toolbar row, as Steam replaces search with it (H5) */
|
|
#header %{SearchAndTitleContainer}%{ShowingTitle} {
|
|
position: absolute;
|
|
top: 14px;
|
|
left: 120px;
|
|
right: 120px;
|
|
width: auto;
|
|
height: var(--lgs-hit);
|
|
padding: 0;
|
|
justify-content: center;
|
|
}
|
|
#header %{SearchAndTitleContainer}%{ShowingTitle} > div {
|
|
font: var(--lgs-type-title2);
|
|
letter-spacing: 0;
|
|
color: var(--lgs-text-1);
|
|
text-shadow: none;
|
|
}
|
|
|
|
/* Large Title (T2 node, aria-hidden): x 100, centred on the row */
|
|
#header > .lgs-title {
|
|
position: absolute;
|
|
left: 100px;
|
|
top: 14px;
|
|
height: var(--lgs-hit);
|
|
display: flex;
|
|
align-items: center;
|
|
font: var(--lgs-type-large);
|
|
letter-spacing: var(--lgs-track-large);
|
|
color: var(--lgs-text-1);
|
|
white-space: nowrap;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Account alert (#header_profile, only with active support alerts):
|
|
a 60 px circle top right, 24 px inset */
|
|
#header %{HeaderItem} {
|
|
position: absolute;
|
|
right: 14px;
|
|
top: 14px;
|
|
width: var(--lgs-hit);
|
|
height: var(--lgs-hit);
|
|
border-radius: 50%;
|
|
justify-content: center;
|
|
color: var(--lgs-text-1);
|
|
pointer-events: auto;
|
|
}
|
|
|
|
/* The header's own box takes no clicks in the fallback band; its
|
|
controls do (inventory shell §3). Steam's header is already
|
|
pointer-events none except its children; nothing changes here. */
|
|
|
|
/* High contrast: a solid band again */
|
|
@media (prefers-contrast: more) {
|
|
#header%{Profile>Header}::before {
|
|
background: var(--lgs-mat-thick-bg);
|
|
backdrop-filter: none;
|
|
-webkit-mask-image: none;
|
|
mask-image: none;
|
|
}
|
|
}
|
|
|
|
/* Scroll guard (VP P-23, WN §3.2): focused items stay below the toolbar
|
|
row. Steam's generic vertical scrollers start at the header's bottom,
|
|
so their top padding is the guard minus the header. Areas apply the
|
|
same variables to their own scrollers (and the bottom bound). */
|
|
%{ScrollPanel}%{ScrollY} {
|
|
scroll-padding-top: calc(var(--lgs-guard-top) - var(--basicui-header-height, 40px));
|
|
/* and they end at the footer's top (628), so 16 px keeps focus above 612 */
|
|
scroll-padding-bottom: calc(720px - var(--gamepadui-current-footer-height, 92px) - var(--lgs-guard-bottom));
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* 3. The bottom ornament (#Footer, WN §3.4, PLAN §1.10) */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/* Only the main window's footer (the floating footer and the Quick
|
|
Access footer reuse #Footer; C3a styles the floating one). */
|
|
|
|
/* The strip dissolves; 8 px under the capsule makes Steam's measured
|
|
footer 92 px, so pages and modals end at y 628 by Steam's own layout. */
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:not(%{FloatingVRFooter}, %{QuickAccessFooter}) {
|
|
background: none;
|
|
backdrop-filter: none;
|
|
border-image: none;
|
|
border-top: 0;
|
|
padding-bottom: 8px;
|
|
/* the capsule's E3 edge (P4's hook on ::before, placed below) */
|
|
--lgs-edge: liquid;
|
|
/* the capsule's glass: liquid over the page (y 628-656), tinted over the
|
|
room below (also its leaving ghost, below) */
|
|
--lgs-c1a-orn-bg:
|
|
linear-gradient(180deg, rgb(255 255 255 / .12), rgb(255 255 255 / .03) 55%),
|
|
linear-gradient(180deg, rgb(28 30 40 / .30) 0, rgb(28 30 40 / .30) 22px,
|
|
rgb(28 30 40 / calc(.58 + var(--lgs-dial) * .24)) 40px);
|
|
--lgs-c1a-orn-shade: var(--lgs-mat-liquid-shade), 0 7px 22px rgb(0 0 0 / .28);
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:not(%{FloatingVRFooter}, %{QuickAccessFooter}) %{FooterLegend} {
|
|
height: var(--lgs-ornament);
|
|
padding: 0;
|
|
justify-content: center;
|
|
align-items: center;
|
|
/* no gap: the members' hit boxes abut (VP P-07); the 4 px between their
|
|
visible pills is a 2 px share of each member's own box */
|
|
gap: 0;
|
|
/* the lift (section 1): the row moves up, Steam's measured footer stays
|
|
92 px (the margins cancel), so pages still end where Steam puts them */
|
|
margin-top: calc(-1 * var(--lgs-c1a-orn-lift, 0px));
|
|
margin-bottom: var(--lgs-c1a-orn-lift, 0px);
|
|
}
|
|
/* Steam's flex spacer would push the legends right; the capsule is
|
|
centred (it is empty and takes no clicks) */
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{FooterLegend} > %{PopupBody>Spacer} {
|
|
flex: 0 0 0px;
|
|
margin: 0;
|
|
}
|
|
|
|
/* Members: 60 px capsules inside an 84 px hit row whose boxes abut along
|
|
the row (VP P-07: the light is inset 12 px top and bottom and 2 px at
|
|
each side, so neighbouring pills stay 4 px apart), label first (22
|
|
Semibold, mixed case), the glyph badge trailing like a menu's keyboard
|
|
shortcut. */
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend} {
|
|
height: var(--lgs-ornament);
|
|
box-sizing: border-box;
|
|
padding: 0 calc(var(--lgs-btn-pad) + 2px);
|
|
border-radius: var(--lgs-r-capsule);
|
|
background: none !important;
|
|
isolation: isolate;
|
|
color: var(--lgs-text-1);
|
|
--lgs-ill: raised;
|
|
--lgs-ill-inset: 12px 2px;
|
|
--lgs-ill-r: var(--lgs-r-capsule);
|
|
--lgs-ill-z: -1;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend} %{ActionButtonLabel},
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend} %{CompatFooterDescription} {
|
|
margin: 0;
|
|
font-family: var(--lgs-font);
|
|
font-size: var(--lgs-fs-callout);
|
|
font-weight: 600;
|
|
line-height: 1.3;
|
|
letter-spacing: 0;
|
|
text-transform: none;
|
|
color: inherit;
|
|
text-shadow: none;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend} %{ActionButtonLegend>ActionButtonGlyph} {
|
|
order: 1;
|
|
margin-left: 10px;
|
|
width: var(--lgs-glyph);
|
|
height: var(--lgs-glyph);
|
|
flex: none;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
/* Steam's own glyph image as the 30 px badge (VP P-26, P-27): a white
|
|
.16 disc with the letter at white .70, behind the label in weight.
|
|
The image is a light disc with a dark letter: inverted and screened,
|
|
its disc vanishes and its letter turns light over the badge's disc. */
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend} %{ActionButtonLegend>ActionButtonGlyph} {
|
|
border-radius: 50%;
|
|
background: rgb(255 255 255 / .16);
|
|
/* Steam's wide glyphs (the ≡ pill) stay inside the disc (review R2 m8) */
|
|
overflow: hidden;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend} %{FooterGlyphSize} {
|
|
width: var(--lgs-glyph);
|
|
height: var(--lgs-glyph);
|
|
object-fit: contain;
|
|
filter: invert(1);
|
|
mix-blend-mode: screen;
|
|
opacity: .70;
|
|
}
|
|
/* T2 (data-lgs-glyph, --lgs-c1a-glyph = the image's own URL): Steam's glyph
|
|
is a white disc (the menu glyph a white pill) with the letter cut out,
|
|
so the letter is drawn as the image's own background (white .70) seen
|
|
through a mask of those holes: the full box minus the glyph, cut to a
|
|
circle inside the disc's edge. No blend mode: an inverted opaque disc
|
|
screened over the translucent capsule came out as an opaque dark disc
|
|
with a light ring (review R2 m8); now only the letter lands on the .16
|
|
badge, as WN draws it, for whatever glyph set Steam shows */
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend} %{FooterGlyphSize}[data-lgs-glyph] {
|
|
filter: none;
|
|
mix-blend-mode: normal;
|
|
opacity: 1;
|
|
background: rgb(255 255 255 / .70);
|
|
-webkit-mask-image: radial-gradient(circle closest-side, #000 84%, transparent 90%), linear-gradient(#000 0 0), var(--lgs-c1a-glyph);
|
|
mask-image: radial-gradient(circle closest-side, #000 84%, transparent 90%), linear-gradient(#000 0 0), var(--lgs-c1a-glyph);
|
|
-webkit-mask-size: 100% 100%;
|
|
mask-size: 100% 100%;
|
|
-webkit-mask-position: center;
|
|
mask-position: center;
|
|
-webkit-mask-repeat: no-repeat;
|
|
mask-repeat: no-repeat;
|
|
-webkit-mask-composite: source-in, xor;
|
|
mask-composite: intersect, exclude;
|
|
}
|
|
/* the menu glyph: keep only the middle of its pill (the bars), drawn 1.5x
|
|
so the bars read at the letters' size inside the 30 px badge */
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend} %{FooterGlyphSize}%{*PillShapedIcon}[data-lgs-glyph] {
|
|
-webkit-mask-image: linear-gradient(#000 0 0), linear-gradient(#000 0 0), var(--lgs-c1a-glyph);
|
|
mask-image: linear-gradient(#000 0 0), linear-gradient(#000 0 0), var(--lgs-c1a-glyph);
|
|
-webkit-mask-size: 50% 34%, 100% 100%, 100% 100%;
|
|
mask-size: 50% 34%, 100% 100%, 100% 100%;
|
|
scale: 1.5;
|
|
}
|
|
/* laser mode: glyph badges collapse (no width, no paint); the legend, its
|
|
label and its click target stay (no function hidden) */
|
|
&[data-lgs-vr-mode="laser"] %{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend} %{ActionButtonLegend>ActionButtonGlyph} {
|
|
width: 0;
|
|
margin: 0;
|
|
overflow: hidden;
|
|
background: none;
|
|
}
|
|
/* A and B: quiet trailing members (T2 tags the button enum) */
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend}:is([data-lgs-btn="OK"], [data-lgs-btn="CANCEL"]) {
|
|
color: var(--lgs-text-2);
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{ActionButtonLegend}:is([data-lgs-btn="OK"], [data-lgs-btn="CANCEL"]) :is(%{ActionButtonLabel}, %{CompatFooterDescription}) {
|
|
font-weight: 500;
|
|
}
|
|
/* the Options member (T2, WN §3.4.2 slot 2): Steam's legend look; the
|
|
target's name trails as a quieter decorative suffix; disabled = .38,
|
|
no hover or press (P4 keys them off aria-disabled), no dispatch */
|
|
%{BasicUiRoot} #Footer%{BasicFooter} .lgs-opt[data-lgs-t2] {
|
|
cursor: default;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter} .lgs-opt[data-lgs-t2][aria-disabled="true"] {
|
|
opacity: .55;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter} .lgs-opt[data-lgs-t2] .lgs-opt-glyph {
|
|
flex: none;
|
|
width: 22px;
|
|
height: 22px;
|
|
margin-right: 10px;
|
|
fill: currentColor;
|
|
opacity: .70;
|
|
}
|
|
&:not([data-lgs-vr-mode="laser"]) %{BasicUiRoot} #Footer%{BasicFooter} .lgs-opt[data-lgs-t2] .lgs-opt-glyph {
|
|
display: none;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter} .lgs-opt[data-lgs-t2] .lgs-opt-name {
|
|
margin-left: .3em;
|
|
display: inline-block;
|
|
max-width: 260px;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
vertical-align: bottom;
|
|
font-weight: 500;
|
|
color: var(--lgs-text-2);
|
|
}
|
|
/* 14 px between the member groups' pills, inside the first quiet member's
|
|
own box (its light starts 12 px in), so the hit boxes still abut; an
|
|
area's fixed slots place their members themselves */
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:not([data-lgs-orn-fixed]) %{ActionButtonLegend}:not([data-lgs-btn="OK"], [data-lgs-btn="CANCEL"]) + %{ActionButtonLegend}:is([data-lgs-btn="OK"], [data-lgs-btn="CANCEL"]) {
|
|
padding-left: calc(var(--lgs-btn-pad) + 12px);
|
|
--lgs-ill-inset: 12px 2px 12px 12px;
|
|
}
|
|
/* compact members (T2 sets it when the members would pass 960 px) */
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn-compact] %{ActionButtonLegend} {
|
|
padding: 0 18px;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn-compact] %{ActionButtonLegend} :is(%{ActionButtonLabel}, %{CompatFooterDescription}) {
|
|
font-size: var(--lgs-fs-subhead);
|
|
}
|
|
/* while an alert or sheet is open (C1c's html.lgs-modal), the members
|
|
that act on the page beneath recede under black .35 (still clickable) */
|
|
&.lgs-modal %{BasicUiRoot} #Footer%{BasicFooter} [data-lgs-t2] {
|
|
filter: brightness(.65);
|
|
}
|
|
|
|
/* The capsule: anchored to the first and last member, so it hugs them in
|
|
any language and mode (without T2), or at the rect T2 writes
|
|
(--lgs-orn-x / --lgs-orn-w: measured union or an area's fixed slots).
|
|
y 628-712, radius 42, padding 0 12; liquid glass that frosts the page
|
|
above the glass edge and is tinted over the room below it (WN §8.4). */
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{FooterLegend} > :nth-child(1 of %{ActionButtonLegend}) {
|
|
anchor-name: --lgs-orn-first;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{FooterLegend} > :nth-last-child(1 of %{ActionButtonLegend}) {
|
|
anchor-name: --lgs-orn-last;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter} %{FooterLegend} > :nth-child(1 of %{ActionButtonLegend}):nth-last-child(1 of %{ActionButtonLegend}) {
|
|
anchor-name: --lgs-orn-first, --lgs-orn-last;
|
|
}
|
|
/* 12 px of capsule padding outside the first and last pill (their boxes
|
|
reach 2 px past their pills) */
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:not(%{FloatingVRFooter}, %{QuickAccessFooter})::before,
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:not(%{FloatingVRFooter}, %{QuickAccessFooter})::after {
|
|
top: anchor(--lgs-orn-first top, 0px);
|
|
bottom: anchor(--lgs-orn-first bottom, 8px);
|
|
left: calc(anchor(--lgs-orn-first left, 100%) - 10px);
|
|
right: calc(anchor(--lgs-orn-last right, 0px) - 10px);
|
|
border-radius: var(--lgs-r-capsule);
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:not(%{FloatingVRFooter}, %{QuickAccessFooter})::after {
|
|
content: "";
|
|
position: absolute;
|
|
z-index: -1;
|
|
pointer-events: none;
|
|
/* liquid over the page (y 628-656), tinted over the room below */
|
|
background: var(--lgs-c1a-orn-bg);
|
|
backdrop-filter: var(--lgs-mat-liquid-blur);
|
|
box-shadow: var(--lgs-c1a-orn-shade);
|
|
}
|
|
/* Motion (WN §7, PLAN §1.5; P5's keyframes and tokens). The capsule's
|
|
glass materializes in (lgs-mat-glass-in, 250 ms) whenever the legend
|
|
becomes a capsule; when it becomes quiet, the capsule's glass
|
|
dematerializes at its old rect (lgs-mat-glass-out, 350 ms, the ghost
|
|
on ::before below) while the quiet legend's dim band fades in over the
|
|
same 350 ms. A member Steam adds fades its label in on `fade`; the
|
|
labels already there never move by animation. A width change of the
|
|
capsule slides its ends on `snappy` (T2: Web Animations on ::before and
|
|
::after, device/rt/20-shell.js). Reduce Motion: P5's keyframes are
|
|
opacity only and the ends do not slide. */
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn="capsule"]:not(%{FloatingVRFooter}, %{QuickAccessFooter})::after {
|
|
--lgs-maxside: 960; /* the widest ornament: a swell of 12 px or less, under P-53's 1.5 % */
|
|
animation: lgs-mat-glass-in var(--lgs-motion-mat-in, 250ms linear) backwards;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn="quiet"]:not(%{FloatingVRFooter}, %{QuickAccessFooter})::after {
|
|
animation: lgs-fade-in var(--lgs-d-mat-out, 350ms) var(--lgs-ease-fade, ease-out) backwards;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:not(%{FloatingVRFooter}, %{QuickAccessFooter}) %{ActionButtonLegend} :is(%{ActionButtonLabel}, %{CompatFooterDescription}) {
|
|
animation: lgs-fade-in var(--lgs-motion-fade, 441ms ease-out) backwards;
|
|
}
|
|
/* T2's measured or fixed rect */
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn-fixed]:not(%{FloatingVRFooter})::before,
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn-fixed]:not(%{FloatingVRFooter})::after,
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn-measured]:not(%{FloatingVRFooter})::before,
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn-measured]:not(%{FloatingVRFooter})::after {
|
|
left: var(--lgs-orn-x);
|
|
right: auto;
|
|
width: var(--lgs-orn-w);
|
|
top: calc(-1 * var(--lgs-c1a-orn-lift, 0px));
|
|
bottom: calc(8px + var(--lgs-c1a-orn-lift, 0px));
|
|
}
|
|
/* Native glass (T2 node .lgs-orn-plate, device/rt/20-shell.js): the
|
|
capsule's rect for P6's reporter, the liquid plate shell-ornament and
|
|
the data-lgs-nopop box (PLAN §1.7 rule 1). It paints nothing. */
|
|
%{BasicUiRoot} #Footer%{BasicFooter} > .lgs-orn-plate {
|
|
position: absolute;
|
|
top: anchor(--lgs-orn-first top, 0px);
|
|
bottom: anchor(--lgs-orn-first bottom, 8px);
|
|
left: calc(anchor(--lgs-orn-first left, 100%) - 10px);
|
|
right: calc(anchor(--lgs-orn-last right, 0px) - 10px);
|
|
border-radius: var(--lgs-r-capsule);
|
|
pointer-events: none;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:is([data-lgs-orn-fixed], [data-lgs-orn-measured]) > .lgs-orn-plate {
|
|
left: var(--lgs-orn-x);
|
|
right: auto;
|
|
width: var(--lgs-orn-w);
|
|
top: calc(-1 * var(--lgs-c1a-orn-lift, 0px));
|
|
bottom: calc(8px + var(--lgs-c1a-orn-lift, 0px));
|
|
}
|
|
|
|
/* Quiet legend (only A and B, T2's data-lgs-orn="quiet"): no capsule
|
|
material, the members keep 60 px and their place */
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn="quiet"] {
|
|
--lgs-edge: none;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn="quiet"]::after {
|
|
background: none;
|
|
backdrop-filter: none;
|
|
box-shadow: none;
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn="quiet"] %{ActionButtonLegend} {
|
|
color: var(--lgs-text-2);
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn="quiet"] %{ActionButtonLegend} :is(%{ActionButtonLabel}, %{CompatFooterDescription}) {
|
|
font-weight: 500;
|
|
}
|
|
/* ... and on `window` routes, where it sits in the margin over the room,
|
|
one dim band behind it (flag quietBacking, WN §3.4.1, O3): black .62,
|
|
60 px, blurred edges, not glass (no blur of the room, no rim, no
|
|
slab); labels white .82 with the on-room shadow (VP P-39, P-41) */
|
|
%{BasicUiRoot}:not([data-lgs-glass="window-full"]) #Footer%{BasicFooter}[data-lgs-orn="quiet"]:not([data-lgs-band="off"])::after {
|
|
top: calc(anchor(--lgs-orn-first top, 0px) + 12px);
|
|
bottom: calc(anchor(--lgs-orn-first bottom, 8px) + 12px);
|
|
left: calc(anchor(--lgs-orn-first left, 100%) - 8px);
|
|
right: calc(anchor(--lgs-orn-last right, 0px) - 8px);
|
|
background: rgb(0 0 0 / .62);
|
|
filter: blur(7px);
|
|
}
|
|
%{BasicUiRoot}:not([data-lgs-glass="window-full"]) #Footer%{BasicFooter}[data-lgs-orn="quiet"]:not([data-lgs-band="off"]) %{ActionButtonLegend} {
|
|
color: rgb(255 255 255 / .82);
|
|
text-shadow: var(--lgs-text-room-shadow);
|
|
}
|
|
/* capsule -> quiet (T2 sets data-lgs-orn-leave for 600 ms with the old
|
|
rect in --lgs-orn-gl / --lgs-orn-gr): the capsule's glass leaves as P5's
|
|
dematerialize (held while nothing else moves, then dissolved, 350 ms);
|
|
at rest it is opacity 0. ::before is free in the quiet legend (no E3
|
|
hook there). Native mode: glassd fades its own plate, so no ghost. */
|
|
&:not(.lgs-native) %{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn="quiet"][data-lgs-orn-leave]:not(%{FloatingVRFooter}, %{QuickAccessFooter})::before {
|
|
content: "";
|
|
position: absolute;
|
|
z-index: -1;
|
|
top: calc(-1 * var(--lgs-c1a-orn-lift, 0px));
|
|
bottom: calc(8px + var(--lgs-c1a-orn-lift, 0px));
|
|
left: var(--lgs-orn-gl, 50%);
|
|
right: var(--lgs-orn-gr, 50%);
|
|
width: auto;
|
|
border-radius: var(--lgs-r-capsule);
|
|
background: var(--lgs-c1a-orn-bg);
|
|
backdrop-filter: var(--lgs-mat-liquid-blur);
|
|
box-shadow: var(--lgs-c1a-orn-shade);
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
--lgs-maxside: 960; /* the widest ornament: a swell of 12 px or less, under P-53's 1.5 % */
|
|
animation: lgs-mat-glass-out var(--lgs-motion-mat-out, 350ms ease-out);
|
|
}
|
|
|
|
/* Native glass: once glassd draws the ornament plate (acked), the plate
|
|
is the capsule's glass on both sides of the window edge. The CSS tint's
|
|
two tones (light over the page, dark over the room) would split it in
|
|
half at the edge, so the capsule keeps one even scrim (white labels
|
|
stay legible), no drop shadow of its own (the plate's contact shadow)
|
|
and no in-page frost (nothing runs under it any more). */
|
|
&.lgs-native %{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn="capsule"]:has(> .lgs-orn-plate:is([data-lgs-plate-ack], :root[data-lgs-plates] [data-lgs-plate]:not([data-lgs-plate-css]))):not(%{FloatingVRFooter}, %{QuickAccessFooter}) {
|
|
--lgs-c1a-orn-bg: linear-gradient(var(--lgs-scrim), var(--lgs-scrim));
|
|
--lgs-c1a-orn-shade: 0 0 0 0 transparent;
|
|
}
|
|
&.lgs-native %{BasicUiRoot} #Footer%{BasicFooter}[data-lgs-orn="capsule"]:has(> .lgs-orn-plate:is([data-lgs-plate-ack], :root[data-lgs-plates] [data-lgs-plate]:not([data-lgs-plate-css]))):not(%{FloatingVRFooter}, %{QuickAccessFooter})::after {
|
|
backdrop-filter: none;
|
|
}
|
|
|
|
@media (prefers-contrast: more) {
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:not(%{FloatingVRFooter}, %{QuickAccessFooter}) {
|
|
--lgs-c1a-orn-bg: var(--lgs-mat-liquid-bg);
|
|
}
|
|
%{BasicUiRoot} #Footer%{BasicFooter}:not(%{FloatingVRFooter}, %{QuickAccessFooter})::after {
|
|
backdrop-filter: none;
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* 4. The tab-bar ornament (frame.menu, WN §3.3) */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/* Steam's frame menu, restyled as two glass capsules of circles: the six
|
|
sections, then the system (Console, Settings, [Help], VR Settings, a
|
|
10 px gap, Power). Built from Steam's component variables and the
|
|
rows' backgrounds; the width only as below (measured, so it animates). Specific to
|
|
%{Variant_FrameMenu}, so the bar's tab menus (C3a) are untouched. */
|
|
%{DashboardMenu}%{Variant_FrameMenu} {
|
|
--lgs-c1a-tab-d: calc(var(--lgs-c1a-tab-p) - 8px);
|
|
--lgs-c1a-tab-fill: rgb(28 30 40 / calc(.67 + var(--lgs-dial) * .22));
|
|
--menu-background: transparent;
|
|
--menu-item-height: calc(var(--lgs-c1a-tab-p) - 6px);
|
|
--menu-icon-size: calc(var(--lgs-c1a-tab-d) * .52);
|
|
--menu-font-size: var(--lgs-fs-callout);
|
|
/* the capsules' corner radius: collapsed, half the column (a capsule of
|
|
circles); expanded, a 30 px rounded rectangle (a capsule radius on the
|
|
wide panel made it an oval blob). The native cover reads the same
|
|
radius from .lgs-tabcap (theme/layers/20-shell.json) */
|
|
--lgs-c1a-tab-r: 30px;
|
|
background: none;
|
|
box-shadow: none;
|
|
border-radius: 0;
|
|
/* rule 1 of WN §3.3.2 (T2): a transparent band under the bar centres
|
|
its capsules on the glass instead of the panel */
|
|
padding-bottom: var(--lgs-tab-place, 0px);
|
|
}
|
|
/* collapsed, the capsule is the circle plus 12 px at each side (WN
|
|
§3.3.1): only the value of Steam's collapsed width (54) changes. Steam's
|
|
width transition (300 ms ease) is retimed, timing properties only (WN
|
|
§7): out to the labels on `snappy`, back to the circles on `fade`.
|
|
Expanded, Steam leaves the width `auto`, which Chromium 126 cannot
|
|
interpolate: the menu jumped open in one frame (and the native glass
|
|
followed a report later). The runtime measures the expanded width the
|
|
labels need (--lgs-c1a-tab-wx on the frame-menu root, device/rt/
|
|
20-shell.js) and it is set here, so the width really animates; the
|
|
content is the same as at `auto` (overflow stays Steam's hidden). */
|
|
%{DashboardMenu}%{Variant_FrameMenu} {
|
|
width: var(--lgs-c1a-tab-wx, auto);
|
|
transition-duration: var(--lgs-d-snappy, 488ms);
|
|
transition-timing-function: var(--lgs-ease-snappy, ease);
|
|
}
|
|
/* A label keeps its own width while the bar slides open (the bar's edge
|
|
clips it meanwhile): squeezed by the animating width, Steam's marquee
|
|
started on "Steam Settings" and "Friends & Chat" mid-open and stayed on,
|
|
their ends scrolling and faded out in the open bar. Steam's 160 px cap
|
|
goes too; the open bar is as wide as its labels need (the measure above) */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>ItemLabel} {
|
|
max-width: none;
|
|
flex-shrink: 0;
|
|
}
|
|
/* native: the motion starts a moment after Steam's toggle, so glassd (told
|
|
the end shape and the start time by the reporter, cover.morph in
|
|
theme/layers/20-shell.json) moves the capsules' glass on the same spring
|
|
from the first frame instead of catching up. Invisible next to Steam's
|
|
own 500 ms hover delay */
|
|
&.lgs-native %{DashboardMenu}%{Variant_FrameMenu} {
|
|
transition-delay: var(--lgs-native-lead, 70ms);
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu}%{DashboardMenu>Collapsed} {
|
|
--lgs-c1a-tab-r: calc(var(--lgs-c1a-tab-d) / 2 + 12px);
|
|
width: calc(var(--lgs-c1a-tab-d) + 24px);
|
|
transition-duration: var(--lgs-d-fade, 441ms);
|
|
transition-timing-function: var(--lgs-ease-fade, ease);
|
|
}
|
|
/* each row paints its slice of its capsule (rows are contiguous) */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>ItemOuter},
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{SectionGap} {
|
|
background: var(--lgs-c1a-tab-fill);
|
|
border-color: transparent !important;
|
|
/* Steam rounds its group ends by 6 px; the capsule ends below decide */
|
|
border-radius: 0 !important;
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{SectionGap} {
|
|
height: 10px;
|
|
margin: 0;
|
|
width: 100%;
|
|
}
|
|
/* capsule ends: the first row of each group, the last row of each group
|
|
(radius = half the collapsed width, so the circles sit concentric in
|
|
the ends; the 6 px padding is the row's) */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>ItemOuter}:nth-child(1 of %{DashboardMenu>ItemOuter}),
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>ItemOuter}:nth-child(7 of %{DashboardMenu>ItemOuter}) {
|
|
padding-top: 6px;
|
|
border-top-left-radius: var(--lgs-c1a-tab-r) !important;
|
|
border-top-right-radius: var(--lgs-c1a-tab-r) !important;
|
|
background: linear-gradient(180deg, rgb(255 255 255 / .08), rgb(255 255 255 / 0) 60%), var(--lgs-c1a-tab-fill);
|
|
box-shadow: var(--lgs-raised-shadow);
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>ItemOuter}:nth-child(6 of %{DashboardMenu>ItemOuter}),
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>ItemOuter}:nth-last-child(1 of %{DashboardMenu>ItemOuter}) {
|
|
padding-bottom: 6px;
|
|
border-bottom-left-radius: var(--lgs-c1a-tab-r) !important;
|
|
border-bottom-right-radius: var(--lgs-c1a-tab-r) !important;
|
|
}
|
|
/* 10 popup px between the two capsules */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>ItemOuter}:nth-child(7 of %{DashboardMenu>ItemOuter}) {
|
|
margin-top: 10px;
|
|
}
|
|
/* Native glass (T2 nodes .lgs-tabcap, device/rt/20-shell.js): the two
|
|
capsules' rects, the frame.menu cover elements of
|
|
theme/layers/20-shell.json (liquid, PLAN §1.6). They paint nothing.
|
|
Rows: the first and last of a group are p + 6, the others p; 10 px
|
|
between the groups; the band under the bar is the root's padding. */
|
|
%{DashboardMenu}%{Variant_FrameMenu} > .lgs-tabcap {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
border-radius: var(--lgs-c1a-tab-r);
|
|
pointer-events: none;
|
|
/* each capsule's E3 edge (WN §8.1: arc + lobe; P4's hook on ::before),
|
|
whole-capsule, so the rows' slices never draw a ring of their own.
|
|
The hook's conic light is centred on the box: on an 82 px wide, 400 px
|
|
tall capsule most of the upper sides fall in the key light's bright
|
|
sector (measured dL 164 down the left side, twice the window's top
|
|
arc), which reads as a line; .45 of dimming brings the brightest part
|
|
to the window rim's level */
|
|
--lgs-edge: liquid;
|
|
--lgs-edge-dim: .45;
|
|
}
|
|
&.lgs-native %{DashboardMenu}%{Variant_FrameMenu} > .lgs-tabcap[data-lgs-cover] {
|
|
--lgs-edge: none;
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} > .lgs-tabcap[data-lgs-tabcap="1"] {
|
|
top: 0;
|
|
height: calc(6 * var(--lgs-c1a-tab-p) + 12px);
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} > .lgs-tabcap[data-lgs-tabcap="2"] {
|
|
top: calc(6 * var(--lgs-c1a-tab-p) + 22px);
|
|
bottom: var(--lgs-tab-place, 0px);
|
|
}
|
|
|
|
/* rows: the item never paints a fill of its own (Steam: hover 20 %
|
|
white, focus keyframes); light comes from P4's nav hook on the item */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item} {
|
|
background: transparent !important;
|
|
--lgs-ill: nav;
|
|
/* expanded: the pill ends 10 px inside the 30 px panel (the end rows'
|
|
6 px padding + 4 px), so its 20 px corners are concentric */
|
|
--lgs-ill-inset: 4px 10px;
|
|
--lgs-ill-r: calc(var(--lgs-c1a-tab-r) - 10px);
|
|
}
|
|
/* collapsed: the pill ends 12 px inside the capsule (concentric with its
|
|
ends) */
|
|
%{DashboardMenu}%{Variant_FrameMenu}%{DashboardMenu>Collapsed} %{DashboardMenu>Item} {
|
|
--lgs-ill-inset: 4px 12px;
|
|
--lgs-ill-r: var(--lgs-r-capsule);
|
|
}
|
|
/* without C1a's runtime (no .lgs-tabcap) the native cover is the menu's
|
|
own box: give it the panel's corners so it is never a square slab
|
|
(REQ P7->C1a) */
|
|
%{DashboardMenu}%{Variant_FrameMenu}:not(:has(> .lgs-tabcap)) {
|
|
border-radius: var(--lgs-c1a-tab-r);
|
|
}
|
|
/* tabs never scale on focus or selection (VP P-05, PLAN §1.4). Steam
|
|
zooms the focused and the current item 1.1x with its own transform;
|
|
that value stays Steam's, the independent `scale` (LAB) takes it back
|
|
to 1, and Steam's transform transition is set to 0 s (timing only) so
|
|
the two never drift apart mid-way */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item} {
|
|
transition-duration: 0s;
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item}%{DashboardMenu>Active},
|
|
&:not(.lgs-input-laser) %{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item}.gpfocus {
|
|
scale: calc(1 / 1.1);
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>ItemOuter}::before {
|
|
content: none;
|
|
}
|
|
/* glyphs white .70 at rest, labels 22 Medium white .96 (expanded) */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item} %{DashboardMenu>ItemIcon} {
|
|
position: relative;
|
|
color: var(--lgs-text-2) !important;
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item} %{DashboardMenu>ItemLabel} {
|
|
font-weight: 500;
|
|
letter-spacing: 0;
|
|
color: var(--lgs-text-1) !important;
|
|
text-shadow: none;
|
|
}
|
|
/* the current route: the navigation selection drawn as a circle behind
|
|
the glyph (white .18 + its specular arc), glyph white, label Semibold;
|
|
never a pill, so it never shares a shape with focus. Every item carries
|
|
the circle, clear at rest, so a selection change cross-fades (the old
|
|
circle out, the new one in) on `fade` (WN §7, T1) */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item} %{DashboardMenu>ItemIcon} {
|
|
isolation: isolate;
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item} %{DashboardMenu>ItemIcon}::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
width: var(--lgs-c1a-tab-d);
|
|
height: var(--lgs-c1a-tab-d);
|
|
translate: -50% -50%;
|
|
border-radius: 50%;
|
|
background-color: rgb(255 255 255 / 0);
|
|
box-shadow: inset 0 1.5px 1.5px -1px rgb(255 255 255 / 0);
|
|
z-index: -1;
|
|
pointer-events: none;
|
|
transition: background-color var(--lgs-motion-fade, 441ms ease), box-shadow var(--lgs-motion-fade, 441ms ease);
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item}%{DashboardMenu>Active} %{DashboardMenu>ItemIcon}::before {
|
|
background-color: var(--lgs-fill-nav);
|
|
box-shadow: var(--lgs-sel-arc);
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item}%{DashboardMenu>Active} %{DashboardMenu>ItemIcon} {
|
|
color: var(--lgs-text-1) !important;
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item}%{DashboardMenu>Active} %{DashboardMenu>ItemLabel} {
|
|
font-weight: var(--lgs-nav-weight);
|
|
color: var(--lgs-text-1) !important;
|
|
background: none;
|
|
-webkit-background-clip: border-box;
|
|
background-clip: border-box;
|
|
}
|
|
/* gamepad focus: the pill across icon and label (P4's nav hook adds the
|
|
uniform light, the spot and the arc); glyph and label at full white */
|
|
&:not(.lgs-input-laser) %{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item}.gpfocus :is(%{DashboardMenu>ItemIcon}, %{DashboardMenu>ItemLabel}) {
|
|
color: var(--lgs-text-1) !important;
|
|
}
|
|
&:not(.lgs-input-laser) %{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item}.gpfocus %{DashboardMenu>ItemLabel} {
|
|
font-weight: var(--lgs-nav-weight);
|
|
}
|
|
/* blocked items stay dim */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Blocked} :is(%{DashboardMenu>ItemIcon}, %{DashboardMenu>ItemLabel}) {
|
|
color: var(--lgs-text-disabled) !important;
|
|
}
|
|
/* Steam's blue route dot: the circle replaces it */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>ActiveDot} {
|
|
background: transparent;
|
|
}
|
|
/* the source of an open menu (Power while it is open, T2): white */
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item}[data-lgs-open] %{DashboardMenu>ItemIcon}::before {
|
|
background-color: var(--lgs-selected-fill);
|
|
box-shadow: none;
|
|
}
|
|
%{DashboardMenu}%{Variant_FrameMenu} %{DashboardMenu>Item}[data-lgs-open] %{DashboardMenu>ItemIcon} {
|
|
color: var(--lgs-text-on-selected) !important;
|
|
}
|
|
/* during a modal (T2 class on the frame-menu document): black .35 */
|
|
&.lgs-modal %{DashboardMenu}%{Variant_FrameMenu} {
|
|
filter: brightness(.65);
|
|
}
|
|
|
|
@media (prefers-contrast: more) {
|
|
%{DashboardMenu}%{Variant_FrameMenu} {
|
|
--lgs-c1a-tab-fill: rgb(11 13 16 / .94);
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* 4a. The More circle (T2 node from device/rt/20-more.js; WN §3.4.4, */
|
|
/* PLAN §1.11): 60 px visible in an 80 px hit, clear material over */
|
|
/* content (black .38 + 10 px blur), white while its menu is open */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
.lgs-more {
|
|
position: fixed;
|
|
left: 0;
|
|
top: 0;
|
|
width: var(--lgs-more-hit);
|
|
height: var(--lgs-more-hit);
|
|
display: grid;
|
|
place-items: center;
|
|
z-index: 6900;
|
|
isolation: isolate;
|
|
visibility: hidden;
|
|
pointer-events: none;
|
|
/* hidden only once materialize-out has run */
|
|
transition: visibility 0s linear var(--lgs-d-mat-out, 350ms);
|
|
}
|
|
.lgs-more.lgs-more-show {
|
|
visibility: visible;
|
|
pointer-events: auto;
|
|
transition: none;
|
|
}
|
|
.lgs-more::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: calc((var(--lgs-more-hit) - var(--lgs-more)) / 2);
|
|
z-index: -1;
|
|
border-radius: 50%;
|
|
background: rgb(0 0 0 / .38);
|
|
backdrop-filter: blur(10px);
|
|
box-shadow: var(--lgs-mat-clear-shade);
|
|
transition: background-color var(--lgs-d-hover-in, 294ms) var(--lgs-ease-b0, ease-out);
|
|
--lgs-maxside: 60;
|
|
}
|
|
/* materialize (WN §7, PLAN §1.5): P5's glass channel on the circle and
|
|
the content channel on the glyph; in 250 ms, out 350 ms (the glass held
|
|
while the glyph goes). The rest state of a hidden circle is opacity 0,
|
|
so the exit needs no fill and nothing stays applied (MO R11) */
|
|
.lgs-more.lgs-more-show::before {
|
|
animation: lgs-mat-glass-in var(--lgs-motion-mat-in, 250ms linear) backwards;
|
|
}
|
|
.lgs-more.lgs-more-show svg {
|
|
animation: lgs-mat-content-in var(--lgs-motion-mat-in, 250ms linear) backwards;
|
|
}
|
|
.lgs-more:not(.lgs-more-show)::before {
|
|
opacity: 0;
|
|
animation: lgs-mat-glass-out var(--lgs-motion-mat-out, 350ms ease-out);
|
|
}
|
|
.lgs-more:not(.lgs-more-show) svg {
|
|
opacity: 0;
|
|
animation: lgs-mat-content-out var(--lgs-d-mat-out, 350ms) linear;
|
|
}
|
|
.lgs-more[data-lgs-inglass]::before {
|
|
backdrop-filter: none;
|
|
}
|
|
&:not(.lgs-input-pad) .lgs-more:hover::before {
|
|
background-color: rgb(40 40 40 / .46);
|
|
}
|
|
.lgs-more svg {
|
|
width: var(--lgs-symbol);
|
|
height: var(--lgs-symbol);
|
|
fill: var(--lgs-text-1);
|
|
}
|
|
.lgs-more.lgs-more-open::before {
|
|
background: var(--lgs-selected-fill);
|
|
backdrop-filter: none;
|
|
}
|
|
.lgs-more.lgs-more-open svg {
|
|
fill: var(--lgs-text-on-selected);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* 4b. The pointer proxy (T2 node from device/rt/20-pointer.js, native */
|
|
/* mode only; WN §3.6, PLAN §1.11, S16) */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/* a 16 px ring (2.5 px white .95) with a 6 px white core, a soft dark
|
|
halo (blurred, never a hard line: P-43, review R2 m12) and a soft glow:
|
|
readable on bright art and dark glass. Not glass and not a control; it
|
|
never takes the pointer. */
|
|
.lgs-pointer {
|
|
position: fixed;
|
|
left: -8px;
|
|
top: -8px;
|
|
width: 16px;
|
|
height: 16px;
|
|
border-radius: 50%;
|
|
pointer-events: none;
|
|
contain: strict;
|
|
z-index: 2147483647;
|
|
opacity: 0;
|
|
background: radial-gradient(circle, rgb(255 255 255 / .95) 0 3px, rgb(255 255 255 / 0) 3.5px);
|
|
box-shadow: inset 0 0 0 2.5px rgb(255 255 255 / .95), 0 0 3px 1px rgb(0 0 0 / .50), 0 0 8px 2px rgb(255 255 255 / .35);
|
|
}
|
|
.lgs-pointer.lgs-pointer-on {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* 4c. Native mode (html.lgs-native; P6's acks, PLAN §1.6): where */
|
|
/* glassd draws the shell's glass, the CSS stops painting it. */
|
|
/* Anything not acknowledged keeps its CSS glass. */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/* the ornament: glassd's liquid plate is the capsule (tint, frost and
|
|
crescent), so the CSS capsule and its E3 hook go; labels, badges and
|
|
the members' hover and focus light stay */
|
|
&.lgs-native %{BasicUiRoot} #Footer%{BasicFooter}:has(> .lgs-orn-plate:is([data-lgs-plate-ack], :root[data-lgs-plates] [data-lgs-plate]:not([data-lgs-plate-css]))) {
|
|
--lgs-edge: none;
|
|
}
|
|
&.lgs-native %{BasicUiRoot} #Footer%{BasicFooter}:has(> .lgs-orn-plate:is([data-lgs-plate-ack], :root[data-lgs-plates] [data-lgs-plate]:not([data-lgs-plate-css])))::after {
|
|
background: none;
|
|
backdrop-filter: none;
|
|
box-shadow: none;
|
|
}
|
|
/* toolbar plates on windowless routes: the plate is the control's glass.
|
|
P6's ack rule clears --lgs-mat-plate-bg, so the CSS plate fill goes in
|
|
every state and only the hover and press adds (and the field's focus
|
|
ring) stay over glassd's plate (review R2 m6); the edge and shadow go */
|
|
&.lgs-native %{BasicUiRoot} #header :is([data-lgs-plate-ack], :root[data-lgs-plates] [data-lgs-plate]:not([data-lgs-plate-css])) {
|
|
--lgs-c1a-plate-shade: 0 0 0 0 transparent;
|
|
}
|
|
/* the tab bar: glassd's liquid cover is the two capsules; the rows'
|
|
slices stop painting, the selection circle, focus pill and labels stay */
|
|
&.lgs-native %{DashboardMenu}%{Variant_FrameMenu}:has(> .lgs-tabcap[data-lgs-cover]) {
|
|
--lgs-c1a-tab-fill: transparent;
|
|
}
|
|
&.lgs-native %{DashboardMenu}%{Variant_FrameMenu}:has(> .lgs-tabcap[data-lgs-cover]) :is(%{DashboardMenu>ItemOuter}, %{SectionGap}) {
|
|
background: none;
|
|
box-shadow: none;
|
|
}
|
|
|
|
/* 5. (the app-details overlay scrim moved to C1c's 22-presentations.css
|
|
§7 on 2026-10-07, PLAN §6 two-step move) */
|
|
|
|
/* 6. (the search route moved to C1b's 21-search.css on 2026-10-07, PLAN §6
|
|
two-step move, REQ C1b->C1a #9) */
|