ui/leaderboardrow.razor.scss
// Shared leaderboard row content (rank / avatar / name / time / character / blocks / score / replay).
// Self-styled because s&box stylesheets don't cascade into a child component; the host provides the
// outer positioned/selected row box. Sizes match the original High Scores rows.
@import "Theme.scss";
$yellow: #dddd99;

LeaderboardRow {
	position: relative;   // stay in normal flow (footer stacks rows in a column; host row fills its box)
	flex-direction: row;
	align-items: center;
	width: 100%;
	padding: 0 24px 0 14px;
	color: $white;
	// Non-interactive so hover/click fall through to the host's row (selection); only the replay
	// button and the avatar's profile link opt back in.
	pointer-events: none;

	.rank-column {
		width: 70px;
		flex-shrink: 0;
		align-items: center;
		MedalIcon, TrophyIcon { margin-left: -11px; }
	}

	.rank {
		font-size: 34px;
		font-family: $font-mono;
		color: #6b7385;
	}

	// 50px face comes from the component's Size.
	SteamAvatar {
		margin-right: 18px;
	}

	.name {
		flex-grow: 1;
		flex-basis: 0;        // size from available space, not content
		min-width: 0;         // allow shrink so ellipsis is deterministic on first layout
		font-size: 30px;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;

		&.own { color: $player-name; }
	}

	// Fixed lane for the time so the name width stays stable before the async payload loads.
	.time-col {
		position: relative;          // anchor for the absolutely-placed ms
		width: 85px;
		margin-right: 32px;          // room for the ms to hang into
		flex-direction: row;
		align-items: center;
		justify-content: flex-end;   // mm:ss pinned to the right edge, same x every row

		.time {
			font-size: 32px;
			font-family: $font-mono;
			color: $white;
		}

		.ms {
			position: absolute;
			left: 100%;
			margin-left: 2px;
			font-size: 22px;
			font-family: $font-mono;
			color: rgba( 248, 245, 230, 0.4 );
			white-space: nowrap;
		}
	}

	// Character preview, one tally-block wide, in a fixed lane (stable name width before load).
	.char-col {
		position: relative;
		width: 40px;
		height: 40px;
		flex-shrink: 0;
		margin-left: 8px;

		.icon-glow {
			position: absolute;
			left: -61%;
			top: -60.5%;
			width: 222%;
			height: 221%;
			z-index: 0;
			pointer-events: none;
			opacity: 0.3;
			background-image: url( "sprites/ui/icon_glow.png" );
			background-repeat: no-repeat;
			background-size: 100% 100%;
		}

		.character {
			position: absolute;
			z-index: 1;
			background-size: contain;
			background-repeat: no-repeat;
			background-position: center;
			image-rendering: pixelated;

			// Paired (twins) icon: partner behind up-right and slightly smaller, character in
			// front down-left — same composition as the picker's twins icon.
			&.rear {
				transform: translate( 11%, -9% ) scale( 0.94 );
			}

			&.front {
				transform: translate( -11%, 9% );
			}
		}
	}

	// Fixed lane for the block-tally graphic (appears async, so keep the layout stable).
	.blocks-col {
		width: 220px;
		flex-shrink: 0;
		flex-direction: row;
		align-items: center;
		margin-left: 16px;
		margin-right: 16px;
	}

	.score {
		width: 70px;
		font-size: 34px;
		font-family: $font-mono;
		color: $score-victory;
		text-align: left;

		&.non-victory { color: $score-non-victory; }
	}

	// Always reserve the replay lane, including while data loads or is missing/unusable.
	// Unavailable replays stay grey and inert; hover shows why.
	.replay {
		width: 44px;
		height: 44px;
		flex-shrink: 0;
		margin-left: 16px;
		align-items: center;
		justify-content: center;
		font-size: 24px;
		color: $black;
		background-color: $white;
		pointer-events: all;
		cursor: blank-hand;

		&:hover {
			background-color: $yellow;
		}

		&.stale {
			color: #3a3f4c;
			background-color: #6b7385;
			cursor: blank-arrow;

			&:hover {
				background-color: #6b7385;
			}
		}
	}
}