Files
MichaelScottsman--LiquidAss…/theme/10-primitives.css
T
MichaelScottsman 7ee1310d18 native spikes: scene-graph layering + dmabuf overlays proven
- IVROverlayView reads system overlays (systemui, HeadsetView) but not
  Steam's dmabuf-backed panels
- SteamVR systemui scene graph accepts injected nodes (DOM elements with
  buildNode; submit via module 5723's scheduler): reparent-to-panel +
  panel-anchor + transform + panel shows live crops of Steam's window at
  any 3D offset, and our own dmabuf overlays (needs SetOverlayMouseScale)
- hvgrab: headset-view capture for verification
2026-10-06 22:53:36 -04:00

673 lines
29 KiB
CSS

/* Glass Shell foundation primitives: the generic Steam components every route
and popup reuses (DialogButton family, gamepaddialog field rows, toggles,
sliders, dropdown buttons, text inputs, segmented radios, checkboxes, the
shared gamepad context menu, modal sheets and the floating focus ring).
Owner: foundation ("primitives"). Area files may refine these inside their
own containers; generic changes belong here.
Look only: colours, fills, radii, rims, blur. Never geometry, never the
transforms Steam encodes state in (toggle knob/fill, slider handle/fill,
menu and dialog entrance animations). Focus and selected fills are painted
by Steam keyframes (fill-mode forwards), so those declarations carry
!important. Wrapped as html.lgs-on { ... } by the bundler. */
/* Shorthands used in the comments below:
F = Field, B = Background,
C = Classic (desktop/QAM rows, owned by their area) */
/* ======================================================================
1. Buttons: button.DialogButton + Button
Capsule, fill-2 + inner top rim. One tinted primary action.
====================================================================== */
button.DialogButton%{*GamepadDialogContent>Button} {
border-radius: var(--lgs-r-capsule);
background: var(--lgs-fill-2);
box-shadow: var(--lgs-control-rim);
color: var(--lgs-text-1);
transition: background-color var(--lgs-t-fast) var(--lgs-ease),
box-shadow var(--lgs-t-fast) var(--lgs-ease),
color var(--lgs-t-fast) var(--lgs-ease);
}
/* laser hover */
button.DialogButton%{*GamepadDialogContent>Button}:hover {
background: var(--lgs-hover-fill);
transition: background-color var(--lgs-t-fast) var(--lgs-ease);
}
/* the one tinted action: a dialog's confirm (Primary in the dialog footer
row) is blue at rest, Destructive red; GreenPlay is play green. Steam marks
other buttons Primary too (row actions such as Disconnect): those stay
neutral at rest and take the tint on hover and focus, so a screen keeps a
single tinted capsule. Whole-capsule fill, white label. */
:is(.DialogFooter, %{ModalButtonRow}) button.DialogButton%{*GamepadDialogContent>Button}.Primary {
background: var(--lgs-tint-primary);
color: var(--lgs-text-on-tint);
}
:is(.DialogFooter, %{ModalButtonRow}) button.DialogButton%{*GamepadDialogContent>Button}.Destructive {
background: var(--lgs-tint-danger);
color: var(--lgs-text-on-tint);
}
button.DialogButton%{*GamepadDialogContent>Button}.Primary:hover {
background: var(--lgs-tint-primary);
color: var(--lgs-text-on-tint);
}
:is(.DialogFooter, %{ModalButtonRow}) button.DialogButton%{*GamepadDialogContent>Button}.Primary:hover {
background: var(--lgs-tint-lift), var(--lgs-tint-primary);
}
button.DialogButton%{*GamepadDialogContent>Button}.Destructive:hover {
background: var(--lgs-tint-lift), var(--lgs-tint-danger);
color: var(--lgs-text-on-tint);
}
button.DialogButton.GreenPlay {
background: var(--lgs-tint-play);
color: var(--lgs-text-on-tint);
box-shadow: var(--lgs-control-rim);
}
button.DialogButton.GreenPlay:hover {
background: var(--lgs-tint-lift), var(--lgs-tint-play);
}
/* focus (controller and laser): illuminate from within + bright rim.
!important: Steam's .gpfocus rules are very specific and paint white. */
button.DialogButton%{*GamepadDialogContent>Button}.gpfocus {
background: var(--lgs-focus-fill) !important;
box-shadow: var(--lgs-focus-ring) !important;
color: var(--lgs-text-1) !important;
}
button.DialogButton%{*GamepadDialogContent>Button}.gpfocus.Primary {
background: var(--lgs-tint-lift), var(--lgs-tint-primary) !important;
color: var(--lgs-text-on-tint) !important;
}
button.DialogButton%{*GamepadDialogContent>Button}.gpfocus.Destructive {
background: var(--lgs-tint-lift), var(--lgs-tint-danger) !important;
color: var(--lgs-text-on-tint) !important;
}
button.DialogButton.GreenPlay.gpfocus {
background: var(--lgs-tint-lift), var(--lgs-tint-play) !important;
box-shadow: var(--lgs-focus-ring) !important;
color: var(--lgs-text-on-tint) !important;
}
/* Glyph buttons darken their icon for Steam's white focus; ours is not white */
button.DialogButton%{*GamepadDialogContent>Button}.gpfocus.Glyph {
filter: none;
}
/* pressed (laser click / A held): brighter fill; Steam's own scale stays */
button.DialogButton%{*GamepadDialogContent>Button}:enabled:active {
background: var(--lgs-pressed-fill) !important;
color: var(--lgs-text-1) !important;
}
button.DialogButton%{*GamepadDialogContent>Button}.Primary:enabled:active {
background: var(--lgs-tint-lift), var(--lgs-tint-lift), var(--lgs-tint-primary) !important;
color: var(--lgs-text-on-tint) !important;
}
/* active option shown while focus is elsewhere: pressed-in well */
button.DialogButton%{*GamepadDialogContent>Button}%{*GamepadDialogContent>ActiveAndUnfocused} {
background: var(--lgs-fill-sunken);
box-shadow: var(--lgs-well-shadow);
}
/* disabled: neutral (never tinted) and dimmer; Steam keeps pointer-events */
button.DialogButton%{*GamepadDialogContent>Button}:is(.Disabled, [disabled]),
button.DialogButton%{*GamepadDialogContent>Button}:is(.Disabled, [disabled]):hover {
/* recessed and dim (Steam also darkens disabled buttons); a disabled
confirm is never tinted */
background: var(--lgs-fill-sunken) !important;
color: var(--lgs-text-1) !important;
box-shadow: none;
opacity: var(--lgs-disabled-opacity);
}
button.DialogButton%{*GamepadDialogContent>Button}:is(.Disabled, [disabled]).gpfocus {
background: var(--lgs-fill-3) !important;
}
/* ======================================================================
2. Field rows (Field, non-Classic)
Rows with Background form one grouped card per run of consecutive rows:
fill-1, r-card outer corners, the 6px gap filled, inset hairlines.
Focus = an inner rounded highlight (::after; Steam leaves it unused on
non-Classic rows) so the card stays whole around it.
====================================================================== */
%{*GamepadDialogContent>Field}:not(%{*GamepadDialogContent>Classic}) %{*GamepadDialogContent>FieldLabel} {
color: var(--lgs-text-1);
}
%{*GamepadDialogContent>Field}:not(%{*GamepadDialogContent>Classic}) %{*GamepadDialogContent>FieldDescription} {
color: var(--lgs-text-2);
}
%{*GamepadDialogContent>Field}:not(%{*GamepadDialogContent>Classic}) %{*GamepadDialogContent>LabelFieldValue} {
color: var(--lgs-text-2);
}
%{*GamepadDialogContent>Field}:not(%{*GamepadDialogContent>Classic}) %{*GamepadDialogContent>FieldIcon} {
color: var(--lgs-text-1);
}
/* the grouped card */
%{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background}:not(%{*GamepadDialogContent>Classic}) {
background: var(--lgs-fill-1);
border-radius: 0;
}
/* first row of a run */
:not(%{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background}) + %{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background}:not(%{*GamepadDialogContent>Classic}),
%{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background}:not(%{*GamepadDialogContent>Classic}):first-child {
border-top-left-radius: var(--lgs-r-card);
border-top-right-radius: var(--lgs-r-card);
}
/* last row of a run */
%{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background}:not(%{*GamepadDialogContent>Classic}):not(:has(+ %{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background})) {
border-bottom-left-radius: var(--lgs-r-card);
border-bottom-right-radius: var(--lgs-r-card);
}
/* rows that follow a row: fill the gap above them and draw an inset hairline */
%{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background} + %{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background}:not(%{*GamepadDialogContent>Classic}) {
box-shadow: 0 calc(-1 * var(--lgs-field-gap)) 0 var(--lgs-fill-1);
}
%{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background} + %{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background}:not(%{*GamepadDialogContent>Classic})::before {
content: "";
position: absolute;
inset-inline: 12px 0;
top: calc(-0.5 * var(--lgs-field-gap) - 0.5px);
height: 1px;
background: var(--lgs-separator);
pointer-events: none;
}
/* focused row (row itself or a control inside it). Steam animates the row
background/colour with fill-mode forwards: override with !important. */
%{*GamepadDialogContent>Field}:not(%{*GamepadDialogContent>Classic})%{*GamepadDialogContent>HighlightOnFocus}:is(.gpfocus, .gpfocuswithin) {
background: transparent !important;
color: var(--lgs-text-1) !important;
}
%{*GamepadDialogContent>Field}%{*GamepadDialogContent>Background}:not(%{*GamepadDialogContent>Classic})%{*GamepadDialogContent>HighlightOnFocus}:is(.gpfocus, .gpfocuswithin) {
background: var(--lgs-fill-1) !important;
}
%{*GamepadDialogContent>Field}:not(%{*GamepadDialogContent>Classic})%{*GamepadDialogContent>HighlightOnFocus}:is(.gpfocus, .gpfocuswithin)::after {
content: "";
position: absolute;
inset: 0;
z-index: -1;
border-radius: var(--lgs-r-row);
background: var(--lgs-focus-fill);
box-shadow: var(--lgs-focus-ring);
pointer-events: none;
}
/* when the focus is on a button, dropdown or input inside the row, that
control carries the ring; the row only glows softly around it */
%{*GamepadDialogContent>Field}:not(%{*GamepadDialogContent>Classic})%{*GamepadDialogContent>HighlightOnFocus}.gpfocuswithin:has(:is(button.DialogButton, input, textarea, .DialogCheckbox, .RadioButton).gpfocus)::after {
background: var(--lgs-hover-fill);
box-shadow: none;
}
%{*GamepadDialogContent>Field}:not(%{*GamepadDialogContent>Classic})%{*GamepadDialogContent>HighlightOnFocus}:is(.gpfocus, .gpfocuswithin) %{*GamepadDialogContent>FieldDescription},
%{*GamepadDialogContent>Field}:not(%{*GamepadDialogContent>Classic})%{*GamepadDialogContent>HighlightOnFocus}:is(.gpfocus, .gpfocuswithin) %{*GamepadDialogContent>LabelFieldValue} {
color: var(--lgs-text-1);
}
/* disabled row */
%{*GamepadDialogContent>Field}%{*GamepadDialogContent>Disabled}:not(%{*GamepadDialogContent>Classic}),
%{*GamepadDialogContent>Field}%{*GamepadDialogContent>Disabled}:not(%{*GamepadDialogContent>Classic}) :is(%{*GamepadDialogContent>FieldLabel}, %{*GamepadDialogContent>FieldDescription}, %{*GamepadDialogContent>LabelFieldValue}) {
color: var(--lgs-text-3);
}
/* standalone separator: hairline */
%{*GamepadDialogContent>StandaloneFieldSeparator} {
background: var(--lgs-separator);
}
/* ======================================================================
3. Toggles (Toggle > ToggleRail + ToggleSwitch)
Steam owns ToggleRail::before (the on-fill, positioned by transform) and
Toggle.gpfocus::after (focus halo): recoloured only.
====================================================================== */
%{*GamepadDialogContent>Toggle} {
border-radius: var(--lgs-r-capsule);
}
%{*GamepadDialogContent>Toggle} %{*GamepadDialogContent>ToggleRail} {
background: var(--lgs-fill-3);
box-shadow: var(--lgs-track-depth);
}
%{*GamepadDialogContent>Toggle} %{*GamepadDialogContent>ToggleRail}::before {
background: var(--lgs-toggle-on);
}
%{*GamepadDialogContent>Toggle} %{*GamepadDialogContent>ToggleSwitch} {
background: var(--lgs-knob);
box-shadow: var(--lgs-knob-shadow);
}
/* inside a focused row Steam darkens the rail; keep it a light glass fill */
%{*GamepadDialogContent>Field}.gpfocuswithin %{*GamepadDialogContent>Toggle} %{*GamepadDialogContent>ToggleRail} {
background: var(--lgs-fill-3);
}
/* focused toggle: white rim on the knob, soft halo pill behind */
%{*GamepadDialogContent>Toggle}.gpfocus:not(%{*GamepadDialogContent>Disabled}) %{*GamepadDialogContent>ToggleSwitch} {
border-color: var(--lgs-focus-outline);
}
%{*GamepadDialogContent>Toggle}.gpfocus::after {
background-color: var(--lgs-fill-2);
border-radius: var(--lgs-r-capsule);
}
%{*GamepadDialogContent>Toggle}:not(%{*GamepadDialogContent>Disabled}):hover {
box-shadow: 0 0 0 4px var(--lgs-hover-fill);
border-radius: var(--lgs-r-capsule);
}
%{*GamepadDialogContent>Toggle}%{*GamepadDialogContent>Disabled} {
opacity: var(--lgs-disabled-opacity);
}
%{*GamepadDialogContent>Toggle}%{*GamepadDialogContent>Disabled} %{*GamepadDialogContent>ToggleRail} {
background: var(--lgs-fill-3);
}
%{*GamepadDialogContent>Toggle}%{*GamepadDialogContent>Disabled} %{*GamepadDialogContent>ToggleSwitch} {
background: var(--lgs-knob);
}
/* ======================================================================
4. Sliders (...)
Track fill-3 capsule, white fill (via Steam's --left-track-color), white
knob. Never touch the handle container transform or the inline vars.
====================================================================== */
%{*SliderControlPanelGroup>SliderTrack} {
background-color: var(--lgs-fill-3);
border-radius: var(--lgs-r-capsule);
--left-track-color: var(--lgs-slider-fill);
--default-value-track-color: var(--lgs-slider-fill-2);
box-shadow: var(--lgs-track-depth);
}
%{*SliderControlPanelGroup>SliderTrack}::before {
border-radius: var(--lgs-r-capsule);
}
%{*SliderControlPanelGroup>SliderControlAndNotches}%{*SliderControlPanelGroup>Disabled} %{*SliderControlPanelGroup>SliderTrack}::before {
background-color: var(--lgs-text-disabled);
}
%{*SliderControlPanelGroup>SliderHandle} {
background: var(--lgs-knob);
box-shadow: var(--lgs-knob-shadow);
}
%{*SliderControlPanelGroup>SliderControlAndNotches}:not(%{*SliderControlPanelGroup>Disabled}).gpfocus %{*SliderControlPanelGroup>SliderHandle} {
border-color: var(--lgs-focus-fill);
box-shadow: var(--lgs-knob-shadow), var(--lgs-focus-glow);
}
%{*SliderControlPanelGroup>SliderControlAndNotches}%{*SliderControlPanelGroup>Disabled} %{*SliderControlPanelGroup>SliderHandle} {
background: var(--lgs-text-2);
}
%{*SliderControlPanelGroup>SliderNotchTick} {
background-color: var(--lgs-fill-3);
border-radius: var(--lgs-r-capsule);
}
%{*SliderControlPanelGroup>SliderNotchTick}%{*SliderControlPanelGroup>TickActive} {
background-color: var(--lgs-slider-fill);
}
%{*SliderControlPanelGroup>SliderNotchLabel} {
color: var(--lgs-text-2);
}
%{*SliderControlPanelGroup>DescriptionValue} {
color: var(--lgs-text-2);
}
%{*SliderControlPanelGroup>DefaultValueTick} > svg {
color: var(--lgs-text-3);
}
%{*SliderControlPanelGroup>EditableValue} {
background: var(--lgs-well-bg);
box-shadow: var(--lgs-well-shadow);
color: var(--lgs-text-1);
caret-color: var(--lgs-caret);
border-radius: var(--lgs-r-small);
}
%{*SliderControlPanelGroup>EditableValue}.gpfocus {
background: var(--lgs-well-bg) !important;
box-shadow: var(--lgs-well-shadow), var(--lgs-focus-ring) !important;
color: var(--lgs-text-1) !important;
}
/* ======================================================================
5. Dropdown buttons (DropDownControlButton: also a DialogButton, so it
is already a capsule). Rich labels keep their text levels on focus.
====================================================================== */
button%{DropDownControlButton}.DialogButton %{*GamepadDialogContent>DropDownControlButtonContents} > svg {
color: var(--lgs-text-2);
}
button%{DropDownControlButton}.DialogButton.gpfocus %{*GamepadDialogContent>DropDownControlButtonContents} > svg {
color: var(--lgs-text-1);
}
/* rich (multi-line) dropdowns are too tall for a capsule: rounded rect */
button%{DropDownControlButton}.DialogButton:has(%{DropDownLabelContainer}) {
border-radius: var(--lgs-r-card);
}
button%{DropDownControlButton}.DialogButton %{DropDownLabelTitle} {
color: var(--lgs-text-1);
}
button%{DropDownControlButton}.DialogButton :is(%{DropDownLabelDescription}, %{DropDownLabelUpperDescription}) {
color: var(--lgs-text-2);
}
/* Game Recording quality options: Steam dims both parts for its white focus */
button%{DropDownControlButton}.DialogButton %{BitrateOption},
button%{DropDownControlButton}.DialogButton.gpfocus %{BitrateOption} {
color: var(--lgs-text-2);
}
button%{DropDownControlButton}.DialogButton %{BitrateOption} %{BitrateSetting>Emphasis},
button%{DropDownControlButton}.DialogButton.gpfocus %{BitrateOption} %{BitrateSetting>Emphasis} {
color: var(--lgs-text-1);
}
/* the same rich labels inside menu rows follow the row colour (dark on the
white selected pill, white elsewhere); secondary lines at vibrancy 2 */
%{*BasicContextMenuModal>contextMenuItem} %{DropDownLabelTitle} {
color: inherit;
}
%{*BasicContextMenuModal>contextMenuItem} :is(%{DropDownLabelDescription}, %{DropDownLabelUpperDescription}) {
color: inherit;
opacity: 0.74;
}
/* ======================================================================
6. Text inputs: sunken capsule well, white text and caret, dim placeholder
====================================================================== */
.BasicUI input%{*GamepadDialogContent>BasicTextInput},
.BasicUI input%{*GamepadDialogContent>BasicTextInput}:not(.disabled):not(.gpfocus):hover,
input%{*GamepadDialogContent>BasicTextInput}:not(.lgs-x),
textarea.DialogTextInputBase:not(.lgs-x) {
background: var(--lgs-well-bg);
box-shadow: var(--lgs-well-shadow);
color: var(--lgs-text-1);
caret-color: var(--lgs-caret);
border-radius: var(--lgs-r-capsule);
transition: box-shadow var(--lgs-t-fast) var(--lgs-ease), background-color var(--lgs-t-fast) var(--lgs-ease);
}
textarea.DialogTextInputBase:not(.lgs-x) {
border-radius: var(--lgs-r-row);
}
input%{*GamepadDialogContent>BasicTextInput}::placeholder,
input.DialogTextInputBase::placeholder,
textarea.DialogTextInputBase::placeholder {
color: var(--lgs-text-3);
font-style: normal;
}
.BasicUI input%{*GamepadDialogContent>BasicTextInput}.gpfocus,
input%{*GamepadDialogContent>BasicTextInput}.gpfocus,
input%{*GamepadDialogContent>BasicTextInput}.gpfocus:hover,
textarea.DialogTextInputBase:is(.gpfocus, :focus) {
background: var(--lgs-well-bg) !important;
box-shadow: var(--lgs-well-shadow), var(--lgs-focus-ring) !important;
color: var(--lgs-text-1) !important;
}
input%{*GamepadDialogContent>BasicTextInput}:is(:disabled, :read-only, .disabled) {
color: var(--lgs-text-disabled);
}
%{*GamepadDialogContent_InnerWidth>GamepadDialogContent} ._DialogInputContainer:is(.gpfocus, .Active) {
background-color: var(--lgs-well-bg) !important;
box-shadow: var(--lgs-well-shadow), var(--lgs-focus-ring) !important;
color: var(--lgs-text-1) !important;
}
.DialogLabel {
color: var(--lgs-text-2);
}
/* ======================================================================
7. Segmented radios (Group / Shared_Radio_Group) and checkboxes
Inside a glass card: fills, not glass. Selected segment = white pill.
====================================================================== */
%{Group}:not(%{CenteredPill}) {
background-color: var(--lgs-fill-sunken);
box-shadow: var(--lgs-well-shadow);
border-radius: var(--lgs-r-capsule);
color: var(--lgs-text-1);
}
%{Group}:not(%{CenteredPill}) > %{Group>Button} {
background-color: transparent;
border-radius: var(--lgs-r-capsule);
color: var(--lgs-text-1);
text-shadow: none;
transition: background-color var(--lgs-t-fast) var(--lgs-ease), color var(--lgs-t-fast) var(--lgs-ease);
}
%{Group}:not(%{CenteredPill}) > %{Group>Button}:not(%{Group>Disabled}):hover {
background-color: var(--lgs-hover-fill);
}
%{Group}:not(%{CenteredPill}) > %{Group>Button}%{Group>Active},
%{Group}:not(%{CenteredPill}) > %{Group>Button}%{Group>Active}:hover {
background: var(--lgs-selected-fill);
color: var(--lgs-text-on-selected);
box-shadow: var(--lgs-pill-shadow);
}
%{Group>Button}:not(%{Group>Active}) + %{Group>Button}:not(%{Group>Active})::before {
background: var(--lgs-separator);
}
%{Group}%{CenteredPill} > %{Group>Button} {
border-color: var(--lgs-separator);
}
%{Group}%{CenteredPill} > %{Group>Button}%{Group>Active} {
background: var(--lgs-selected-fill);
color: var(--lgs-text-on-selected);
}
.DialogCheckbox {
background-color: var(--lgs-well-bg);
box-shadow: var(--lgs-well-shadow), inset 0 0 0 1.5px var(--lgs-control-outline);
border-radius: var(--lgs-r-small);
transition: background-color var(--lgs-t-fast) var(--lgs-ease);
}
.DialogCheckbox.Active {
background-color: var(--lgs-selected-fill);
box-shadow: none;
}
.DialogCheckbox.Active .SVGIcon_DialogCheck path {
stroke: var(--lgs-text-on-selected);
}
.DialogCheckbox_Container:hover .DialogCheckbox:not(.Disabled):not(.Active),
.DialogCheckbox:hover:not(.Disabled):not(.Active),
.DialogCheckbox:focus:not(.Disabled):not(.Active) {
background-color: var(--lgs-hover-fill);
}
/* ======================================================================
8. Context menus and dropdown menus (gamepad presentation, in a modal)
Thick-glass menu sheet, r-menu, 8px inner padding, r-row items.
Steam animates BasicContextMenuContainer (opacity + transform):
left alone, no extra materialize here.
====================================================================== */
%{*BasicContextMenuModal>BasicContextMenuHeader} {
color: var(--lgs-text-1);
text-shadow: var(--lgs-text-shadow);
}
%{*BasicContextMenuModal>contextMenuContents} {
background: var(--lgs-panel-sheen), var(--lgs-thick-bg);
backdrop-filter: var(--lgs-thick-blur);
box-shadow: var(--lgs-glass-rim), var(--lgs-glass-shadow);
border-radius: var(--lgs-r-menu);
filter: none;
padding: 8px;
}
/* Steam's 15px/40px end margins were invisible on a transparent column; on a
glass sheet they read as empty glass. The 8px padding replaces them. */
%{*BasicContextMenuModal>contextMenuContents} > :first-child {
margin-top: 0;
}
%{*BasicContextMenuModal>contextMenuContents} > :last-child {
margin-bottom: 0;
}
%{*BasicContextMenuModal>contextMenuItem} {
background: transparent;
color: var(--lgs-text-1);
border-radius: var(--lgs-r-row);
transition: background-color var(--lgs-t-fast) var(--lgs-ease), color var(--lgs-t-fast) var(--lgs-ease);
}
/* Play/Launch/Stream-type items Steam paints on every row */
%{*BasicContextMenuModal>contextMenuItem}:is(.Stream, .Connect, .Launch, .PlayMusic, .Play, .Resume, .BorrowApp) {
background: transparent;
color: var(--lgs-text-1);
}
%{*BasicContextMenuModal>contextMenuItem}:hover {
background: var(--lgs-hover-fill);
}
%{*BasicContextMenuModal>contextMenuItem}:hover:is(%{*BasicContextMenuModal>Destructive}, .Stop) {
background: var(--lgs-tint-danger);
color: var(--lgs-text-on-tint);
}
%{*BasicContextMenuModal>contextMenuItem}:hover:is(%{*BasicContextMenuModal>Positive}, .Stream, .Connect, .Launch, .PlayMusic, .Play, .Resume, .BorrowApp) {
background: var(--lgs-tint-play);
color: var(--lgs-text-on-tint);
}
%{*BasicContextMenuModal>contextMenuItem}:hover:is(%{*BasicContextMenuModal>Emphasis}, .Download, .Update, .PreLoad, .Install) {
background: var(--lgs-tint-primary);
color: var(--lgs-text-on-tint);
}
/* selected value / open-submenu parent: the white selected pill */
%{*BasicContextMenuModal>contextMenuItem}:is(%{*BasicContextMenuModal>Selected}, %{*BasicContextMenuModal>active}) {
background: var(--lgs-selected-fill) !important;
color: var(--lgs-text-on-selected) !important;
}
/* focus: illuminate + ring (beats Selected's white so focus always shows) */
%{*BasicContextMenuModal>contextMenuItem}:is(%{*BasicContextMenuModal>Focused}, .gpfocus) {
background: var(--lgs-focus-fill) !important;
box-shadow: var(--lgs-focus-ring) !important;
color: var(--lgs-text-1) !important;
}
%{*BasicContextMenuModal>contextMenuItem}:is(%{*BasicContextMenuModal>Focused}, .gpfocus):is(%{*BasicContextMenuModal>Selected}, %{*BasicContextMenuModal>active}) {
background: var(--lgs-selected-fill) !important;
color: var(--lgs-text-on-selected) !important;
}
%{*BasicContextMenuModal>contextMenuItem}:is(%{*BasicContextMenuModal>Focused}, .gpfocus):is(%{*BasicContextMenuModal>Positive}, .Stream, .Connect, .Launch, .PlayMusic, .Play, .Resume, .BorrowApp) {
background: var(--lgs-tint-lift), var(--lgs-tint-play) !important;
color: var(--lgs-text-on-tint) !important;
}
%{*BasicContextMenuModal>contextMenuItem}:is(%{*BasicContextMenuModal>Focused}, .gpfocus):is(%{*BasicContextMenuModal>Emphasis}, .Download, .Update, .PreLoad, .Install) {
background: var(--lgs-tint-lift), var(--lgs-tint-primary) !important;
color: var(--lgs-text-on-tint) !important;
}
%{*BasicContextMenuModal>contextMenuItem}:is(%{*BasicContextMenuModal>Focused}, .gpfocus):is(%{*BasicContextMenuModal>Destructive}, .Stop) {
background: var(--lgs-tint-lift), var(--lgs-tint-danger) !important;
color: var(--lgs-text-on-tint) !important;
}
%{*BasicContextMenuModal>contextMenuItem}.disabled,
%{*BasicContextMenuModal>contextMenuItem}.disabled.gpfocus {
color: var(--lgs-text-disabled) !important;
}
/* checked item: white label + a check mark instead of thin cyan text */
%{*BasicContextMenuModal>contextMenuItem}.menuChecked {
color: var(--lgs-text-1);
padding-inline-end: 40px;
}
%{*BasicContextMenuModal>contextMenuItem}.menuChecked::after {
content: "";
position: absolute;
inset-inline-end: 14px;
top: 50%;
width: 16px;
height: 16px;
margin-top: -8px;
background: currentColor;
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3.2 3.2L13 4.8' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
pointer-events: none;
}
/* check glyphs inside menu rows (e.g. the "Play from" target) follow the
label colour instead of a thin blue stroke */
%{*BasicContextMenuModal>contextMenuItem} .SVGIcon_DialogCheck path {
stroke: currentColor;
}
%{*BasicContextMenuModal>contextMenuItem}%{*BasicContextMenuModal>MenuSectionHeader} {
color: var(--lgs-text-2);
}
%{*BasicContextMenuModal>contextMenuItem}%{*BasicContextMenuModal>SubMenu} .SVGIcon_DownArrowContextMenu {
fill: currentColor;
opacity: 0.7;
}
/* separators: hairline inset from both sides (keeps Steam's 2px slot) */
#MainNavMenu-Rest %{*BasicContextMenuModal>ContextMenuSeparator},
%{*BasicContextMenuModal>ContextMenuSeparator} {
background: linear-gradient(var(--lgs-separator), var(--lgs-separator)) center / calc(100% - 24px) 1px no-repeat;
}
/* ======================================================================
9. Modals: scrim + thick-glass sheet
====================================================================== */
%{GamepadDialogOverlay} .ModalOverlayContent.ModalOverlayBackground {
background: var(--lgs-scrim);
}
%{GamepadDialogOverlay} .ModalOverlayContent.ModalOverlayBackground:has(~ .ModalOverlayContent.active .BasicUIContextMenu) {
backdrop-filter: var(--lgs-menu-scrim-blur);
}
%{*GamepadDialogContent>ModalPosition} > %{*GamepadDialogContent_InnerWidth>GamepadDialogContent} {
background: var(--lgs-panel-sheen), var(--lgs-thick-bg) !important;
backdrop-filter: var(--lgs-thick-blur);
border-color: transparent;
border-radius: var(--lgs-r-sheet);
box-shadow: var(--lgs-glass-rim), var(--lgs-glass-shadow);
}
/* custom scrolling content placed straight in the modal (no dialog card;
e.g. long text panels): give it the same sheet so it never sits on the
bare scrim. Colour only (keeps any image a custom panel paints). */
%{*GamepadDialogContent>ModalPosition} > div.Panel:not(%{*GamepadDialogContent>ModalClickToDismiss}):has(> %{ScrollPanel}) {
background-color: var(--lgs-thick-bg);
backdrop-filter: var(--lgs-thick-blur);
border-radius: var(--lgs-r-panel);
box-shadow: var(--lgs-glass-rim), var(--lgs-glass-shadow);
}
%{*GamepadDialogContent>ModalPosition} .DialogHeader {
color: var(--lgs-text-1);
}
%{*GamepadDialogContent>ModalPosition} .DialogBodyText {
color: var(--lgs-text-1);
}
.BasicUI :is(.DialogSubHeader, .DialogControlsSectionHeader),
:is(.DialogSubHeader, .DialogControlsSectionHeader):not(.lgs-x) {
color: var(--lgs-text-2);
border-color: var(--lgs-separator);
}
.DialogHeader {
text-shadow: var(--lgs-text-shadow);
}
/* ======================================================================
10. Floating focus ring (FocusRing): steady white rim + glow, rounded.
Geometry is inline and animated by Steam: untouched. The 20x opacity pulse
is held at 1 (no pulsing at rest).
====================================================================== */
%{FocusRing} {
outline: 2px solid var(--lgs-focus-outline) !important;
outline-offset: 2px;
/* r-row on panels and segments, tighter on small targets (checkboxes) */
border-radius: min(var(--lgs-r-row), 35%);
box-shadow: var(--lgs-focus-glow);
opacity: 1 !important;
}
/* ======================================================================
11. Generic progress bar (ProgressBar component: downloads, updates, zoo)
Same language as the slider: fill-3 capsule track, white fill. Steam's
indeterminate sweep animation is left as is.
====================================================================== */
%{ProgressBarIndeterminate>ProgressBar},
.gpfocus %{ProgressBarIndeterminate>ProgressBar} {
background: var(--lgs-fill-3);
border-radius: var(--lgs-r-capsule);
/* the fill paints inline "background: var(--gpColor-Blue, #1a9fff)" */
--gpColor-Blue: var(--lgs-slider-fill);
}
%{ProgressBarIndeterminate>ProgressBar} %{Indeterminate>Percent} {
border-radius: var(--lgs-r-capsule);
}
%{ProgressBarFieldStatus} %{ProgressBar>TextContainer} %{OperationText} {
color: var(--lgs-text-2);
}