ui/hud.razor.scss
// Devil Daggers palette: near-black ground, ember orange, blood red. No blues.
$accent: #ff7a1c;
$accent-dim: #a8410c;
$charge: #ffd34a;
$panel-bg: rgba(6, 4, 3, 0.94);
$text: #f0dcc8;
$muted: #8a6a58;

.hud
{
	position: absolute;
	width: 100%;
	height: 100%;
	font-family: Consolas, monospace;
	color: $text;
	pointer-events: none;

	&.panel-open
	{
		pointer-events: all;
	}

	// Photo mode. Opacity rather than display:none so layout, hit testing and every OnUpdate
	// behind it carry on exactly as they were: the overlay comes off the glass, the game does
	// not change.
	&.photo-hidden { opacity: 0; }

	// ------------------------------------------------------------ top progress bar

	.topbar
	{
		position: absolute;
		top: 24px;
		left: 50%;
		transform: translateX( -50% );
		width: 620px;
		flex-direction: column;
		align-items: center;

		.tier
		{
			font-size: 16px;
			letter-spacing: 6px;
			color: $accent;
			margin-bottom: 6px;
		}

		.bar
		{
			width: 100%;
			height: 10px;
			background-color: rgba(255, 255, 255, 0.08);
			border: 1px solid rgba(255, 255, 255, 0.15);
			overflow: hidden;

			.fill
			{
				height: 100%;
				background-color: $accent;
				transition: width 0.25s ease-out;
			}
		}

		.counts
		{
			margin-top: 6px;
			font-size: 13px;
			color: $muted;
			gap: 8px;

			.remaining { color: $text; }
			.pct { color: $accent-dim; margin-left: 12px; }
		}
	}

	// ------------------------------------------------------------ stage cleared banner

	.cleared
	{
		position: absolute;
		top: 34%;
		left: 50%;
		transform: translateX( -50% );
		flex-direction: column;
		align-items: center;
		text-align: center;

		.big
		{
			font-size: 52px;
			letter-spacing: 10px;
			color: $charge;
			text-stroke: 2px rgba(0, 0, 0, 0.55);
		}

		.next
		{
			margin-top: 10px;
			font-size: 18px;
			letter-spacing: 5px;
			color: $accent;
		}
	}

	// ------------------------------------------------------------ wallet

	.wallet
	{
		position: absolute;
		top: 24px;
		left: 24px;
		flex-direction: column;
		background-color: rgba(8, 11, 16, 0.55);
		padding: 14px 18px;
		border-left: 2px solid $accent;

		.dust
		{
			flex-direction: column;
			margin-bottom: 8px;

			.label { font-size: 11px; letter-spacing: 4px; color: $muted; }
			.value { font-size: 30px; color: $accent; }
		}

		.line
		{
			justify-content: space-between;
			gap: 18px;
			font-size: 13px;

			.label { color: $muted; }
		}
	}

	// ------------------------------------------------------------ residue callout

	.residue
	{
		position: absolute;
		top: 96px;
		left: 50%;
		transform: translateX( -50% );
		flex-direction: column;
		align-items: center;
		font-size: 22px;
		letter-spacing: 6px;
		color: $charge;

		.sub
		{
			font-size: 12px;
			letter-spacing: 3px;
			color: $muted;
			margin-top: 4px;
		}
	}

	// ------------------------------------------------------------ crosshair

	.crosshair
	{
		position: absolute;
		left: 50%;
		top: 50%;
		width: 10px;
		height: 10px;
		margin-left: -5px;
		margin-top: -5px;
		border: 2px solid rgba(255, 255, 255, 0.35);
		border-radius: 50%;
		transition: all 0.08s ease-out;

		&.on-target
		{
			border-color: $accent;
			width: 18px;
			height: 18px;
			margin-left: -9px;
			margin-top: -9px;
		}
	}

	// The burn warning. A border that closes in from the screen edge, so it registers in
	// peripheral vision while you are aiming at something else entirely.
	.burn
	{
		position: absolute;
		top: 0px;
		left: 0px;
		width: 100%;
		height: 100%;
		border: 26px solid rgba( 255, 60, 20, 0.55 );
	}

	.burn-word
	{
		position: absolute;
		bottom: 22%;
		left: 50%;
		transform: translateX( -50% );
		font-size: 26px;
		letter-spacing: 12px;
		color: #ff5a2a;
		text-stroke: 2px rgba( 0, 0, 0, 0.6 );
	}

	.hint
	{
		position: absolute;
		bottom: 22px;
		left: 50%;
		transform: translateX( -50% );
		font-size: 12px;
		color: $muted;

		b { color: $text; }
	}

	// ------------------------------------------------------------ upgrade panel

	// Catches clicks that miss the panel, so the play field dismisses the menu. Lower z-index
	// than .panel so the panel itself still gets its own clicks.
	.panel-backdrop
	{
		position: absolute;
		top: 0px;
		left: 0px;
		width: 100%;
		height: 100%;
		z-index: 0;
	}

	.panel
	{
		position: absolute;
		top: 0px;
		right: 0px;
		width: 468px;
		height: 100%;
		background-color: $panel-bg;
		border-left: 2px solid $accent;
		flex-direction: column;
		padding: 0px;
		z-index: 1;

		// A header BAND rather than a row of text floating in the same space as the content.
		// This is most of what separated the panel from the welcome sheets: the sheets have a
		// clear title zone and the panel had four words and a number sharing a margin.
		.panel-head
		{
			align-items: center;
			padding: 20px 24px 0px 24px;
			margin-bottom: 0px;
			gap: 18px;
			background-color: rgba( 0, 0, 0, 0.35 );
			border-bottom: 1px solid rgba( 255, 122, 28, 0.22 );

			// The tabs used to wrap: at 17px with 4px of tracking, four labels plus the dust
			// readout overflowed the panel and "UPGRADES" broke across two lines mid-word.
			// Nothing in this row may wrap or shrink.
			flex-wrap: nowrap;

			.title
			{
				font-size: 13px;
				letter-spacing: 3px;
				color: $muted;
				white-space: nowrap;
				flex-shrink: 0;
				padding-bottom: 12px;
				border-bottom: 2px solid rgba( 0, 0, 0, 0 );
				transition: all 0.12s ease-out;

				&:hover { color: $text; }

				&.on
				{
					color: $accent;
					border-bottom-color: $accent;
				}
			}

			// The wallet, given the weight of a readout instead of the weight of a footnote.
			// It is the number every decision on this panel is measured against.
			.dust-inline
			{
				font-size: 16px;
				color: $accent;
				margin-left: auto;
				margin-bottom: 12px;
				letter-spacing: 1px;
				white-space: nowrap;
				flex-shrink: 0;
			}
		}

		.boards
		{
			flex-direction: column;
			flex-grow: 1;
			overflow-y: scroll;
			padding: 18px 24px 24px 24px;
			gap: 18px;
		}

		.upgrades
		{
			flex-direction: column;
			flex-grow: 1;
			overflow-y: scroll;
			padding: 16px 24px 24px 24px;
			gap: 10px;
		}
	}

	.board
	{
		flex-direction: column;

		.board-title
		{
			font-size: 13px;
			letter-spacing: 4px;
			color: $accent-dim;
			padding-bottom: 6px;
			border-bottom: 1px solid rgba(255, 255, 255, 0.08);
			margin-bottom: 6px;
		}

		.board-note
		{
			font-size: 12px;
			color: $muted;
			padding: 8px 0px;

			&.error { color: $charge; }
		}

		.rank-row
		{
			align-items: baseline;
			padding: 4px 6px;
			font-size: 13px;
			gap: 10px;

			.rank { color: $muted; width: 44px; }
			.who { flex-grow: 1; }
			.score { color: $accent-dim; }

			&.me
			{
				background-color: rgba(255, 122, 28, 0.14);
				.who { color: $accent; }
				.score { color: $accent; }
			}
		}
	}

	.refresh
	{
		align-self: center;
		padding: 8px 20px;
		margin-top: 4px;
		font-size: 12px;
		letter-spacing: 4px;
		color: $muted;
		border: 1px solid rgba(255, 255, 255, 0.12);

		&:hover { color: $accent; border-color: $accent-dim; }
	}

	.charge
	{
		position: absolute;
		bottom: 52px;
		left: 50%;
		transform: translateX( -50% );
		font-size: 14px;
		letter-spacing: 3px;
		color: $muted;

		b { color: $text; }

		flex-direction: column;
		align-items: center;
		gap: 7px;

		&.ready { color: $accent; b { color: $accent; } }
		&.armed { color: #ff5a3c; b { color: #ff5a3c; } }
		&.window { color: $charge; b { color: $charge; } }
		&.caught { color: #7dff9b; b { color: #7dff9b; } }

		.live { flex-direction: column; align-items: center; }
		.ready-line { color: $accent; }

		.depth
		{
			width: 230px;
			height: 4px;
			margin-top: 5px;
			background-color: rgba(255, 255, 255, 0.10);

			.fill { height: 100%; background-color: #ff5a3c; }
		}

		.reload
		{
			flex-direction: column;
			align-items: center;

			// The bar is the reload; the bright slice inside it is the target you aim for.
			.bar
			{
				position: relative;
				width: 290px;
				height: 11px;
				background-color: rgba(255, 255, 255, 0.08);
				border: 1px solid rgba(255, 255, 255, 0.16);

				.window
				{
					position: absolute;
					top: 0px;
					height: 100%;
					background-color: rgba(255, 211, 74, 0.55);
					border-left: 1px solid $charge;
					border-right: 1px solid $charge;
				}

				.playhead
				{
					position: absolute;
					top: -3px;
					width: 3px;
					height: 17px;
					background-color: #ffffff;
				}

				.fill
				{
					position: absolute;
					top: 0px;
					left: 0px;
					height: 100%;
					background-color: rgba(255, 122, 28, 0.75);
				}
			}

			// The minigame is bigger and brighter than the passive cooldown bar: it wants
			// your attention for two seconds, then gets out of the way.
			&.attempt .bar
			{
				width: 360px;
				height: 15px;
				border-color: $charge;
			}
		}

		.sub { font-size: 11px; letter-spacing: 2px; color: $muted; margin-top: 4px; }
	}

	// Projected position of the buried charge. Nothing in the world can show this, because the
	// charge is inside solid rock by design.
	.charge-marker
	{
		position: absolute;
		width: 0px;
		height: 0px;
		flex-direction: column;
		align-items: center;

		.ring
		{
			position: absolute;
			left: -17px;
			top: -17px;
			width: 34px;
			height: 34px;
			border: 2px solid #ff5a3c;
			border-radius: 50%;
		}

		.label
		{
			position: absolute;
			top: 22px;
			left: -60px;
			width: 120px;
			text-align: center;
			font-size: 11px;
			letter-spacing: 2px;
			color: #ff5a3c;
		}
	}

	.charge-offscreen
	{
		position: absolute;
		top: 58%;
		left: 50%;
		transform: translateX( -50% );
		font-size: 14px;
		letter-spacing: 4px;
		color: #ff5a3c;
	}

	// AN UPGRADE CARD.
	//
	// The note was that these read as a specification rather than as a game. Structurally the
	// problem was that name, level, description, effect and cost were five pieces of text at
	// four sizes stacked in a box, so there was no shape to scan and every row demanded to be
	// read in full. The fix is hierarchy, not more words: a bar down the left edge that lights
	// when you can afford it, the name given real size, the cost pulled out as its own chip on
	// the right, and the prose demoted to the quietest thing in the card.
	.upgrade
	{
		flex-direction: column;
		flex-shrink: 0;
		background-color: rgba(255, 255, 255, 0.028);
		border: 1px solid rgba(255, 255, 255, 0.06);
		border-left: 3px solid rgba(255, 255, 255, 0.10);
		transition: all 0.1s ease-out;

		// The pad selection. A mouse player never sees this: a highlight that does not follow
		// the cursor would just be confusing next to a hover state.
		&.selected
		{
			border-color: $accent;
			border-left-color: $charge;
			background-color: rgba( 255, 150, 40, 0.14 );
		}

		.body { flex-direction: column; padding: 13px 15px; }

		// Same rule as .primer: a wrapped line in a flex column needs an explicit width and
		// flex-shrink: 0 or it collapses and overdraws the row beneath it.
		.desc
		{
			width: 100%;
			flex-shrink: 0;
			line-height: 16px;
			word-break: break-word;
		}

		.row { flex-shrink: 0; }

		.buymax
		{
			justify-content: center;
			padding: 5px 0px;
			font-size: 11px;
			letter-spacing: 3px;
			color: $accent;
			background-color: rgba(255, 122, 28, 0.10);
			border-top: 1px solid rgba(255, 122, 28, 0.28);

			b { color: $text; }
			&:hover { background-color: rgba(255, 122, 28, 0.26); }
		}

		.row { justify-content: space-between; align-items: center; }

		// A title row with a mark on it. The glyph is what stops eight cards of dense text from
		// reading as one wall: you learn the shapes after a run or two and stop reading names.
		.head
		{
			width: 100%;
			flex-shrink: 0;
			align-items: center;
			gap: 11px;
		}

		.glyph
		{
			width: 22px;
			height: 22px;
			flex-shrink: 0;
			border: 2px solid rgba( 255, 255, 255, 0.22 );
			background-color: rgba( 255, 255, 255, 0.05 );
		}

		// One per upgrade, drawn only from borders and background so nothing needs importing.
		// Deliberately not literal pictures: they are marks to recognise, not illustrations.
		.glyph.drillspeed { background-color: #ffc75c; border-color: #fff0c0; }
		.glyph.blastradius { background-color: #ff6a1a; border-color: #ffb27a; border-radius: 11px; }
		.glyph.chargechance { background-color: #ff2a10; border-color: #ff9a80; border-radius: 4px; }
		.glyph.chargeradius { background-color: transparent; border-color: #ff5a3c; border-radius: 11px; }
		.glyph.dustyield { background-color: #b8763a; border-color: #ffd9a8; }
		.glyph.drones { background-color: transparent; border-color: #ffd34a; border-bottom-width: 7px; }
		.glyph.demolition { background-color: #ff8a3a; border-color: #ffd0a8; border-radius: 4px; }
		.glyph.dronerate { background-color: #ffd34a; border-color: #fff4c8; border-radius: 11px; }

		.name
		{
			font-size: 16px;
			letter-spacing: 1px;
			color: $text;
			flex-grow: 1;
		}

		// The level as a numbered badge rather than the words "Lv 3". At a glance you want the
		// number, and the label was costing three characters of width on every single row.
		.level
		{
			flex-shrink: 0;
			min-width: 26px;
			padding: 2px 7px;
			font-size: 12px;
			text-align: center;
			color: $muted;
			background-color: rgba( 255, 255, 255, 0.06 );
			border: 1px solid rgba( 255, 255, 255, 0.10 );
		}

		.desc
		{
			font-size: 11px;
			line-height: 15px;
			color: $muted;
			margin: 0px 0px 8px 0px;
			opacity: 0.72;
		}

		.foot
		{
			width: 100%;
			flex-shrink: 0;
			justify-content: space-between;
			align-items: center;
			padding-top: 8px;
			border-top: 1px solid rgba( 255, 255, 255, 0.06 );
		}

		.current { font-size: 12px; letter-spacing: 1px; color: $accent-dim; }

		// The price, as a chip. It is the thing you are deciding about, so it gets an edge and
		// a background of its own instead of being the last words on a line.
		.cost
		{
			font-size: 13px;
			letter-spacing: 1px;
			color: $muted;
			padding: 4px 10px;
			border: 1px solid rgba(255, 255, 255, 0.10);
			flex-shrink: 0;
		}

		&.affordable
		{
			border-color: rgba(255, 122, 28, 0.35);
			border-left-color: $accent;
			background-color: rgba(255, 122, 28, 0.06);

			.cost
			{
				color: $accent;
				border-color: rgba(255, 122, 28, 0.55);
				background-color: rgba(255, 122, 28, 0.12);
			}

			&:hover
			{
				background-color: rgba(255, 122, 28, 0.15);
				border-color: $accent;

				.cost { background-color: rgba(255, 122, 28, 0.26); }
			}
		}

		// Earned Marks recede: the list should read as "what is left to do", not a trophy wall.
		&.mark
		{
			.level { color: $muted; }

			&.earned
			{
				opacity: 0.55;
				border-color: rgba(255, 211, 74, 0.30);
				.name { color: $charge; }
				.level { color: $charge; }
			}
		}

		// Core Tree nodes read as gold rather than ember, so the two currencies never blur.
		&.core
		{
			border-color: rgba(255, 211, 74, 0.20);

			.cost { color: $charge; }

			&.affordable
			{
				border-color: $charge;
				background-color: rgba(255, 211, 74, 0.10);
				&:hover { background-color: rgba(255, 211, 74, 0.24); }
			}
		}
	}

	// ------------------------------------------------------------ resonance

	.resonance
	{
		position: absolute;
		top: 50%;
		right: 40px;
		transform: translateY( -50% );
		flex-direction: column;
		align-items: flex-end;

		.stacks
		{
			font-size: 24px;
			letter-spacing: 4px;
			color: $charge;
		}

		.rbar
		{
			width: 170px;
			height: 4px;
			margin-top: 5px;
			background-color: rgba(255, 255, 255, 0.10);

			.fill { height: 100%; background-color: $charge; }
		}

		.count { font-size: 11px; letter-spacing: 2px; color: $muted; margin-top: 4px; }
	}

	.mark-toast
	{
		position: absolute;
		top: 22%;
		left: 50%;
		transform: translateX( -50% );
		flex-direction: column;
		align-items: center;

		.head { font-size: 11px; letter-spacing: 6px; color: $muted; }
		.name { font-size: 26px; letter-spacing: 4px; color: $charge; margin-top: 3px; }
	}

	.markbar
	{
		width: 100%;
		height: 3px;
		margin-top: 6px;
		background-color: rgba(255, 255, 255, 0.09);

		.fill { height: 100%; background-color: $accent-dim; }
	}

	.leeches
	{
		position: absolute;
		top: 132px;
		left: 24px;
		flex-direction: column;
		font-size: 13px;
		letter-spacing: 2px;
		color: #6fdc7a;

		.sub { font-size: 10px; letter-spacing: 1px; color: $muted; margin-top: 2px; }
	}

	.shield-banner
	{
		position: absolute;
		top: 84px;
		left: 50%;
		transform: translateX( -50% );
		flex-direction: column;
		align-items: center;
		font-size: 15px;
		letter-spacing: 4px;
		color: #6fd3ff;

		.sub { font-size: 11px; letter-spacing: 2px; color: $muted; margin-top: 2px; }

		// The break window is the reward for the skill shot, so it reads as a good thing.
		&.broken { color: #9dff9a; }
	}

	// The one piece of text that announces a failure. Centred and large because by the time it
	// shows, the world has already rebuilt and there is nothing left in it to read.
	// Welcome pages and the start screen. A full-screen sheet over a black void.
	.overlay
	{
		position: absolute;
		top: 0px;
		left: 0px;
		width: 100%;
		height: 100%;
		align-items: center;
		justify-content: center;
		background-color: rgba( 0, 0, 0, 0.92 );
	}

	// The pause overlay is deliberately the only one you can see through. The welcome and start
	// sheets are a screen you are ON; pause is a screen you are BEHIND, and leaving the frozen
	// monolith dimly visible is what tells you the game is still there waiting.
	.overlay.transparent { background-color: rgba( 0, 0, 0, 0.72 ); }

	.sheet
	{
		flex-direction: column;
		width: 780px;

		// Three buttons do not need the full reading width the tutorial pages were sized for.
		&.pause { width: 460px; }
		max-height: 88%;
		padding: 32px 36px;
		border: 2px solid $accent;
		background-color: rgba( 12, 8, 6, 0.96 );
		overflow-y: scroll;

		.sheet-eyebrow
		{
			font-size: 11px;
			letter-spacing: 5px;
			color: $muted;
			margin-bottom: 10px;
			flex-shrink: 0;
		}

		.sheet-title
		{
			font-size: 38px;
			letter-spacing: 11px;
			color: $accent;
			flex-shrink: 0;
			text-shadow: 0px 0px 28px rgba( 255, 150, 40, 0.55 );
		}

		.sheet-lead
		{
			width: 100%;
			flex-shrink: 0;
			font-size: 14px;
			line-height: 20px;
			letter-spacing: 1px;
			color: $text;
			margin-top: 10px;
			margin-bottom: 22px;
			word-break: break-word;
		}

		.sheet-rows
		{
			flex-direction: column;
			width: 100%;
			flex-shrink: 0;
			gap: 16px;
		}

		// Each row is an icon and a paragraph. The icons are CSS shapes rather than art, so the
		// welcome screen needs no assets and cannot break on a missing texture.
		.srow
		{
			width: 100%;
			flex-shrink: 0;
			gap: 16px;
			align-items: flex-start;

			.icon
			{
				width: 44px;
				height: 44px;
				flex-shrink: 0;
				border: 2px solid rgba( 255, 255, 255, 0.18 );
			}

			.icon.rock { background-color: #b8763a; border-color: #ffd9a8; }
			.icon.ladder
			{
				background-color: transparent;
				border-color: $accent;
				border-left-width: 10px;
			}
			.icon.bolt
			{
				background-color: #ffc75c;
				border-color: #fff0c0;
				height: 12px;
				margin-top: 16px;
			}
			// NOT `.icon.charge`. There is a `.charge` readout at the bottom of the HUD with
			// `position: absolute`, and since `.icon.charge` never redeclared `position`, the
			// tutorial icon inherited it and left its row entirely: the swatch simply vanished
			// and the text slid left. Two unrelated things wanted the same word.
			.icon.bore { background-color: #ff6a1a; border-color: #ffb27a; border-radius: 22px; }
			.icon.volatile { background-color: #ff2a10; border-color: #ff9a80; }
			.icon.spotter
			{
				background-color: #ffe14d;
				border-color: #fff6bb;
				border-radius: 22px;
			}
			.icon.sentinel { background-color: #ff5a2a; border-color: #ffb59a; border-radius: 8px; }
			.icon.anchor { background-color: #6fdd52; border-color: #c6ffb8; border-radius: 4px; }
			.icon.barrier
			{
				background-color: transparent;
				border-color: #ff5f8f;
				border-width: 4px;
			}
			.icon.crawler
			{
				background-color: #ff7a2a;
				border-color: #ffd6a8;
				height: 24px;
				margin-top: 12px;
			}
			// The floor page. These are swatches of the actual tile colours, so the page is
			// teaching you a lookup you will use rather than a set of arbitrary badges.
			.icon.rocket
			{
				background-color: #ff8a3a;
				border-color: #ffd0a8;
				border-bottom-width: 10px;
				border-bottom-color: #fff0c0;
			}

			.icon.warn { background-color: #ff9e14; border-color: #ffd08a; }
			// Matches the raised slabs in the arena: brighter than anything else on the page,
			// and the only swatch in the whole tutorial that is not in the ember palette.
			.icon.dead
			{
				background-color: #c766ff;
				border-color: #f0d0ff;
				border-bottom-width: 8px;
				border-bottom-color: #6a1090;
			}
			.icon.air
			{
				background-color: transparent;
				border-color: #8fd8ff;
				border-top-width: 10px;
			}

			.icon.leech { background-color: #7dff9b; border-color: #d8ffe4; border-radius: 22px; }
			.icon.move { background-color: transparent; border-color: #8fd8ff; border-bottom-width: 10px; }

			.stext
			{
				flex-direction: column;
				flex-grow: 1;
				flex-shrink: 1;
				font-size: 12px;
				line-height: 18px;
				color: $muted;
				word-break: break-word;

				b
				{
					font-size: 14px;
					letter-spacing: 2px;
					color: $text;
					margin-bottom: 5px;
				}
			}

			.c-y { color: #ffe14d; }
			.c-o { color: #ff9a2a; }
			.c-r { color: #ff3a2a; }

			// `.stext` is a flex COLUMN, so an inline span inside a paragraph is not inline at
			// all: it becomes a full-width row of its own. The lock ramp was rendering as
			// "yellow" / "," / "orange" / ", then" down six lines with the punctuation stranded.
			//
			// Rather than fight that, the three colours get an explicit row. It reads better as a
			// ramp than it ever did as a sentence.
			.ramp
			{
				width: 100%;
				flex-shrink: 0;
				flex-direction: row;
				align-items: center;
				gap: 8px;
				margin-top: 6px;
				margin-bottom: 6px;
				font-size: 11px;
				letter-spacing: 1px;

				.arrow { color: rgba( 255, 255, 255, 0.3 ); }
			}
		}

		.sheet-actions
		{
			width: 100%;
			flex-shrink: 0;
			gap: 12px;
			margin-top: 26px;
			justify-content: flex-end;

			&.column { flex-direction: column; justify-content: flex-start; }
		}

		// A settings row: name on the left, state on the right. A row rather than a button
		// because the label has to be readable at a glance without pressing anything, which is
		// the whole job of a mute switch.
		.toggle
		{
			width: 100%;
			flex-direction: row;
			align-items: center;
			justify-content: space-between;
			padding: 11px 22px;
			font-size: 13px;
			letter-spacing: 3px;
			color: $muted;
			border: 1px solid rgba( 255, 255, 255, 0.12 );
			cursor: pointer;
			transition: all 0.1s ease-out;

			&:hover
			{
				border-color: $accent;
				background-color: rgba( 255, 150, 40, 0.14 );
			}

			&.selected
			{
				border-color: $accent;
				background-color: rgba( 255, 150, 40, 0.16 );
				.name { color: $text; }
			}

			.state
			{
				font-size: 12px;
				letter-spacing: 2px;

				&.on { color: $accent; }
				&.off { color: rgba( 255, 255, 255, 0.28 ); }
			}
		}

		.sheet-btn
		{
			flex-direction: column;
			align-items: center;
			justify-content: center;
			padding: 13px 26px;
			font-size: 14px;
			letter-spacing: 4px;
			color: $text;
			border: 1px solid rgba( 255, 255, 255, 0.24 );
			cursor: pointer;
			transition: all 0.1s ease-out;

			&:hover
			{
				border-color: $accent;
				background-color: rgba( 255, 150, 40, 0.16 );
			}

			&.ghost { color: $muted; border-color: rgba( 255, 255, 255, 0.12 ); }

			// Pad highlight. Written after .ghost so a highlighted ghost button still reads as
			// highlighted rather than keeping the dimmer border.
			&.selected
			{
				color: $text;
				border-color: $accent;
				background-color: rgba( 255, 150, 40, 0.16 );
			}

			&.big { width: 100%; padding: 18px 22px; font-size: 17px; }

			// A fresh save cannot dent the Monolith. Shown, explained, and declined rather than
			// hidden: hiding it would make the shared half of the game invisible on day one.
			&.locked
			{
				color: $muted;
				border-color: rgba( 255, 255, 255, 0.08 );
				&:hover { border-color: rgba( 255, 90, 60, 0.5 ); background-color: rgba( 255, 60, 40, 0.08 ); }
			}

			.sub
			{
				width: 100%;
				flex-shrink: 0;
				font-size: 10px;
				letter-spacing: 1px;
				line-height: 15px;
				color: $muted;
				margin-top: 7px;
				text-align: center;
				word-break: break-word;
			}
		}
	}

	// The end of a hundred stage climb. Deliberately the biggest thing in the game.
	.ladder-done
	{
		position: absolute;
		top: 18%;
		left: 50%;
		transform: translateX( -50% );
		width: 620px;
		flex-direction: column;
		align-items: center;
		padding: 34px 30px;
		background-color: rgba( 0, 0, 0, 0.86 );
		border: 2px solid $accent;

		.done-title
		{
			font-size: 40px;
			letter-spacing: 12px;
			color: $accent;
			text-shadow: 0px 0px 30px rgba( 255, 150, 40, 0.6 );
		}

		.done-sub
		{
			font-size: 12px;
			letter-spacing: 5px;
			color: $muted;
			margin-top: 6px;
		}

		.done-time
		{
			font-size: 54px;
			letter-spacing: 4px;
			color: #ffffff;
			margin-top: 22px;
		}

		.done-rank
		{
			font-size: 13px;
			letter-spacing: 3px;
			color: $charge;
			margin-top: 6px;
			margin-bottom: 26px;
		}

		.done-actions
		{
			width: 100%;
			gap: 14px;
			align-items: stretch;
		}

		.done-btn
		{
			flex-grow: 1;
			flex-basis: 0px;
			flex-direction: column;
			align-items: center;
			padding: 16px 12px;
			font-size: 15px;
			letter-spacing: 4px;
			color: $text;
			border: 1px solid rgba( 255, 255, 255, 0.22 );
			cursor: pointer;
			transition: all 0.1s ease-out;

			&:hover
			{
				border-color: $accent;
				background-color: rgba( 255, 150, 40, 0.14 );
			}

			.sub
			{
				width: 100%;
				flex-shrink: 0;
				font-size: 10px;
				letter-spacing: 1px;
				line-height: 14px;
				color: $muted;
				margin-top: 8px;
				text-align: center;
				word-break: break-word;
			}
		}
	}

	// Controller prompt row. Glyphs sit inline with their labels, so the bar reads the same as
	// the keyboard version rather than becoming a row of floating icons.
	// Control legend inside the upgrade panel. Sits under the tabs so it reads as belonging to
	// the panel rather than to the world behind it.
	.pad-hints
	{
		align-items: center;
		flex-wrap: nowrap;
		gap: 4px;
		padding: 10px 24px 0px 24px;
		margin-bottom: 0px;
		font-size: 10px;
		letter-spacing: 1px;
		color: $muted;

		image
		{
			width: 18px;
			height: 18px;
			flex-shrink: 0;
		}

		span
		{
			margin-right: 10px;
			flex-shrink: 0;
			white-space: nowrap;
		}
	}

	.hint.pad
	{
		align-items: center;
		gap: 6px;

		image
		{
			width: 22px;
			height: 22px;
			flex-shrink: 0;
		}

		span
		{
			margin-right: 12px;
			flex-shrink: 0;
		}
	}

	.stage-lost
	{
		position: absolute;
		top: 34%;
		left: 0px;
		width: 100%;
		flex-direction: column;
		align-items: center;
		pointer-events: none;

		.lost-title
		{
			font-size: 46px;
			letter-spacing: 14px;
			color: #ff3a2a;
			text-shadow: 0px 0px 26px rgba( 255, 40, 30, 0.75 );
		}

		.lost-sub
		{
			font-size: 13px;
			letter-spacing: 3px;
			color: $muted;
			margin-top: 10px;
		}
	}

	.hollow-banner
	{
		position: absolute;
		top: 62px;
		left: 50%;
		transform: translateX( -50% );
		font-size: 12px;
		letter-spacing: 5px;
		color: #b98cff;
	}

	.hollow
	{
		flex-direction: column;
		padding: 10px 12px;
		margin-bottom: 10px;
		border: 1px solid rgba(185, 140, 255, 0.24);
		background-color: rgba(185, 140, 255, 0.05);

		flex-shrink: 0;

		.row { justify-content: space-between; flex-shrink: 0; }
		.name { font-size: 14px; letter-spacing: 3px; color: #b98cff; }
		.level { font-size: 11px; color: $muted; }

		.desc
		{
			width: 100%;
			flex-shrink: 0;
			font-size: 11px;
			line-height: 16px;
			color: $muted;
			margin: 4px 0px 8px 0px;
			word-break: break-word;
		}

		.hollow-btn
		{
			flex-direction: column;
			flex-shrink: 0;
			padding: 6px 8px;
			margin-bottom: 5px;
			border: 1px solid rgba(255, 255, 255, 0.08);

			.hname { font-size: 12px; letter-spacing: 2px; color: $muted; flex-shrink: 0; }

			.sub
			{
				width: 100%;
				flex-shrink: 0;
				font-size: 10px;
				line-height: 14px;
				color: $muted;
				margin-top: 3px;
				word-break: break-word;
			}

			&.on
			{
				border-color: rgba(185, 140, 255, 0.5);
				.hname { color: #b98cff; }
				&:hover { background-color: rgba(185, 140, 255, 0.16); }
			}

			&.cleared .hname { color: #7dff9b; }
			&.active { border-color: #b98cff; background-color: rgba(185, 140, 255, 0.18); }
		}
	}

	.slag
	{
		flex-direction: column;
		padding: 10px 12px;
		margin-bottom: 10px;
		border: 1px solid rgba(125, 255, 155, 0.22);
		background-color: rgba(125, 255, 155, 0.05);

		flex-shrink: 0;

		.row { justify-content: space-between; flex-shrink: 0; }
		.name { font-size: 14px; letter-spacing: 3px; color: #7dff9b; b { color: #ffffff; } }
		.level { font-size: 12px; color: $muted; }

		.desc
		{
			width: 100%;
			flex-shrink: 0;
			font-size: 11px;
			line-height: 16px;
			color: $muted;
			margin-top: 4px;
			word-break: break-word;
		}

		.slag-actions { gap: 8px; margin-top: 9px; align-items: stretch; }

		.slag-btn
		{
			flex-grow: 1;
			flex-basis: 0px;
			flex-direction: column;
			align-items: center;
			padding: 7px 6px;
			font-size: 11px;
			letter-spacing: 2px;
			color: $muted;

			// The Fracture and Reroll blurbs are full sentences now. Without these they
			// collapsed onto one line and ran over the Hollow Runs block below.
			.sub
			{
				width: 100%;
				flex-shrink: 0;
				line-height: 14px;
				word-break: break-word;
			}
			border: 1px solid rgba(255, 255, 255, 0.10);

			.sub { font-size: 9px; letter-spacing: 1px; color: $muted; margin-top: 3px; }

			&.on
			{
				color: #7dff9b;
				border-color: rgba(125, 255, 155, 0.5);
				&:hover { background-color: rgba(125, 255, 155, 0.16); }
			}
		}
	}

	// Explains what a currency IS before offering anything to spend it on. Cores, Slag and
	// Marks were three unlabelled systems sharing one panel, which is why they read as noise.
	// Explains what a currency IS before offering anything to spend it on.
	//
	// Every rule below about width and shrinking is load-bearing. Multi-line text in a flex
	// column collapses to a single line's worth of height unless it is told not to shrink, and
	// the overflow then draws straight over the next block: that is what made the Cores and
	// Marks tabs render as overlapping mush.
	.primer
	{
		flex-direction: column;
		width: 100%;
		flex-shrink: 0;
		padding: 12px 16px;
		margin-bottom: 14px;
		background-color: rgba( 0, 0, 0, 0.25 );
		border-left: 2px solid $accent-dim;
		opacity: 0.9;

		.ptitle
		{
			width: 100%;
			flex-shrink: 0;
			font-size: 11px;
			letter-spacing: 3px;
			line-height: 18px;
			margin-bottom: 6px;
			color: $accent;
		}

		.ptext
		{
			width: 100%;
			flex-shrink: 0;
			font-size: 12px;
			line-height: 18px;
			margin-bottom: 8px;
			color: $muted;
			word-break: break-word;
		}
	}

	// The concrete before/after for the NEXT purchase. This is the line that makes a buy
	// decision possible without doing the arithmetic yourself.
	//
	// Promoted to the second most prominent thing in a card, after the name. It used to be
	// smaller than the description, which buried the only sentence that answers the question
	// the player is actually asking.
	.gain
	{
		width: 100%;
		flex-shrink: 0;
		font-size: 13px;
		line-height: 18px;
		color: $charge;
		margin: 9px 0px 7px 0px;
		word-break: break-word;
	}

	.cores-head
	{
		justify-content: center;
		align-items: baseline;
		padding: 14px 0px 16px 0px;
		margin-bottom: 12px;
		font-size: 12px;
		letter-spacing: 3px;
		color: $muted;
		border-bottom: 1px solid rgba( 255, 122, 28, 0.18 );

		b { color: $charge; font-size: 26px; letter-spacing: 0px; }
	}

	.travel
	{
		margin-top: 14px;
		padding: 12px;
		flex-direction: column;
		align-items: center;
		text-align: center;
		border: 1px solid $accent-dim;
		background-color: rgba(255, 122, 28, 0.08);

		.title { font-size: 15px; letter-spacing: 4px; color: $accent; }
		.sub { font-size: 11px; color: $muted; margin-top: 4px; }

		&:hover { background-color: rgba(255, 122, 28, 0.22); }

		&.back
		{
			border-color: rgba(255, 255, 255, 0.14);
			background-color: rgba(255, 255, 255, 0.04);
			.title { color: $text; }
		}
	}

	.collapse
	{
		margin-top: 10px;
		padding: 14px;
		flex-direction: column;
		align-items: center;
		border: 1px solid rgba(255, 255, 255, 0.1);
		opacity: 0.5;

		.title { font-size: 16px; letter-spacing: 5px; }
		.sub { font-size: 12px; color: $muted; margin-top: 4px; }

		&.ready
		{
			opacity: 1;
			border-color: $charge;
			background-color: rgba(255, 177, 74, 0.1);

			.title { color: $charge; }

			&:hover { background-color: rgba(255, 177, 74, 0.22); }
		}
	}
}