ui/gamecard.razor.scss
@import "Theme.scss";
// A game card. The parent grid sets its width (launcher 360px, browser 274px); everything else -
// the frame, the cloud thumbnail, the verified badge - lives here so the launcher and browser stay identical.
GameCard
{
width: 360px; // default (launcher); the browser narrows this. Fixed (no grow) so cards keep a
flex-grow: 0; // uniform size and art aspect ratio instead of stretching to fill partial rows.
flex-direction: column;
align-items: stretch;
background-color: $panel;
border: 0.15px solid $line;
border-radius: $r-lg;
overflow: hidden; // the card art and corners clip to the rounded frame
cursor: pointer;
pointer-events: all;
transition: all .12s ease;
@include elevate;
&:hover
{
border-color: rgba(216, 181, 107, .5);
transform: translateY(-4px);
box-shadow: 0 18px 38px rgba(0,0,0,.5);
.play { color: $gold-bright; }
}
// Header: a 16:9 panel carrying the cloud thumbnail, or a fallback suit mark when there's none.
.art
{
height: 202px;
position: relative;
align-items: center;
justify-content: center;
background-image: linear-gradient(to bottom, $art-top, $art-bottom);
overflow: hidden;
.shot
{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
background-position: center;
border-top-left-radius: $r-lg;
border-top-right-radius: $r-lg;
}
// No thumbnail: a faint suit mark so the header isn't blank.
.noart
{
font-size: 72px;
color: rgba(246, 242, 230, .14);
}
// Covers the art while this package mounts + starts.
.loading
{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
background-color: rgba(8, 13, 11, .8);
font-family: $sans;
font-size: 14px;
font-weight: 800;
letter-spacing: 1px;
text-transform: uppercase;
color: $gold;
}
}
// Body: title + play affordance, the author/verified byline, muted stats.
.info
{
flex-direction: column;
align-items: stretch;
gap: 9px;
padding: 18px 20px 20px;
.row
{
flex-direction: row;
align-items: baseline;
justify-content: space-between;
// Game titles can run long - keep them on one line so the card height stays uniform.
.name
{
font-family: $serif;
font-size: 23px;
font-weight: 700;
color: $text;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.play
{
font-family: $sans;
font-size: 13px;
font-weight: 800;
color: $gold;
flex-shrink: 0;
transition: color .12s ease;
}
}
// Author line + an optional "verified" badge for first-party (Facepunch) games.
.byline
{
flex-direction: row;
align-items: center;
gap: 4px;
.tagline
{
font-family: $sans;
font-size: 11px;
font-weight: 800;
letter-spacing: 1.5px;
text-transform: uppercase;
color: $gold;
}
.verified
{
flex-direction: row;
align-items: center;
gap: 3px;
font-family: $sans;
font-size: 10px;
font-weight: 800;
letter-spacing: 1px;
text-transform: uppercase;
color: $gold-bright;
.ico
{
font-family: "Material Icons";
font-size: 14px;
letter-spacing: 0;
text-transform: none; // ligature name is case-sensitive - uppercase breaks the glyph
color: $gold-bright;
}
}
}
.stats
{
flex-direction: row;
align-items: flex-start;
gap: 7px;
font-family: $sans;
font-size: 12px;
font-weight: 500;
color: $text-mut;
// The blurb fallback can be a full sentence - let it wrap, but cap it at two lines
// (s&box has no line-clamp, so max-height + hidden overflow does the clipping) so the
// card height stays roughly uniform.
span
{
overflow: hidden;
white-space: normal;
line-height: 1.35;
max-height: 33px;
}
}
}
}