/* Must stay above every style rule — a misplaced @import is dropped silently. */
@import url("/fonts/fonts.css");

/*
	Boxy — site theme.

	The palette is sampled from the key art rather than invented, so the chrome
	and the game read as one thing. boxy_cover.jpg is a blue-teal night (#0f1e28
	city, #232e37 gate, hue ~200) lit by a cyan crystal (#80bfc4 → #dafbf6), and
	boxy_logo_lg.png adds gold (#f4eaa1) and grass (#b6cf8b). The neutral grey +
	blue this replaced matched none of it.

	Accents carry meaning — don't spend them decoratively:
	  gold    the one action we want taken on a screen (Play, Sign in, Create)
	  cyan    interactive-but-secondary: links, focus, hover, selection
	  grass   live/online/success state
	  neon    the city's magenta. Rare, for genuine emphasis only.
*/
:root {
	color-scheme: dark;

	--bg: #0a151c;
	--bg-deep: #060e13;
	--surface: #10222c;
	--surface-2: #17303d;
	--surface-3: #214353;
	--sunken: #071219;
	--line: #294857;
	--line-soft: #1a323e;
	--text: #eaf6f4;
	--muted: #8fadb8;

	--primary: #63d1dd;
	--primary-strong: #b7f0f4;
	--primary-ink: #04222a;
	--gold: #f0c04e;
	--gold-strong: #ffdd85;
	--gold-ink: #2a1c02;
	--accent: #9ad86a;
	--neon: #e5589e;
	--warn: #f0bf66;
	--danger: #ff7582;

	--radius: 0.3rem;
	--radius-lg: 0.55rem;

	/* Panels are lit from above: a hairline highlight on the top edge, a dark
	   drop below. Cheap, and it's what stops surfaces reading as flat boxes. */
	--bevel: inset 0 1px 0 rgb(255 255 255 / 0.07);
	--shadow-sm: 0 2px 6px rgb(0 0 0 / 0.3);
	--shadow-md: 0 10px 26px rgb(0 0 0 / 0.34);
	--shadow-lg: 0 22px 60px rgb(0 0 0 / 0.5);
	--glow: 0 0 0 1px color-mix(in oklab, var(--primary) 55%, transparent),
		0 0 22px color-mix(in oklab, var(--primary) 28%, transparent);

	--font-display: "Chakra Petch", ui-sans-serif, system-ui, "Segoe UI", sans-serif;
	--font-body: "Barlow", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

	font-family: var(--font-body);
	background: var(--bg);
	color: var(--text);
}

*,
*::before,
*::after {
	box-sizing: border-box;
}

html,
body {
	min-height: 100%;
	margin: 0;
}

/* Lets the hero bleed past the centered column without a horizontal scrollbar.
   `clip` rather than `hidden` — hidden would make <html> a scroll container and
   break the sticky header. */
html {
	overflow-x: clip;
}

body,
button,
input,
select,
textarea {
	font: inherit;
}

/* Not a flat fill: a cool overhead wash plus two faint colour pools (crystal
   cyan, city gold) keep long pages from going dead grey between sections. */
body {
	background:
		radial-gradient(120% 70% at 50% -10%, #16303d 0%, transparent 60%),
		radial-gradient(60% 45% at 88% 8%, rgb(99 209 221 / 0.07), transparent 70%),
		radial-gradient(50% 40% at 6% 22%, rgb(240 192 78 / 0.045), transparent 70%),
		var(--bg);
	background-attachment: fixed;
}

h1,
h2,
h3,
h4,
.eyebrow,
.status-chip,
.badge,
nav a,
.primary-button,
.secondary-button,
.ghost-button,
button.primary-button {
	font-family: var(--font-display);
}

h1,
h2,
h3,
h4 {
	font-weight: 700;
	letter-spacing: -0.01em;
}

a {
	color: inherit;
}

img,
canvas {
	max-width: 100%;
}

/* One focus ring everywhere, in the interactive colour. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
	outline: 2px solid var(--primary);
	outline-offset: 2px;
	border-radius: 2px;
}

.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.site-header {
	position: sticky;
	top: 0;
	z-index: 10;
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: 1rem;
	padding: 0.7rem clamp(1rem, 4vw, 3rem);
	/* Hairline lit from the crystal, so the bar is edged rather than boxed. */
	border-bottom: 1px solid transparent;
	border-image: linear-gradient(90deg,
		transparent,
		color-mix(in oklab, var(--primary) 42%, transparent) 30%,
		color-mix(in oklab, var(--gold) 34%, transparent) 72%,
		transparent) 1;
	background: linear-gradient(180deg, rgb(7 18 25 / 0.94), rgb(7 18 25 / 0.82));
	backdrop-filter: blur(14px) saturate(1.2);
}

.brand {
	display: inline-flex;
	align-items: center;
	width: clamp(7rem, 13vw, 8.75rem);
	line-height: 0;
	text-decoration: none;
}

.brand img,
.footer-brand img {
	display: block;
	width: 100%;
	height: auto;
}

.brand img,
.footer-brand img {
	filter: drop-shadow(0 2px 0 rgb(0 0 0 / 0.45)) drop-shadow(0 7px 14px rgb(0 0 0 / 0.28));
}

nav,
.header-actions,
.actions,
.toolbar,
.json-editor-actions,
.play-actions {
	display: flex;
	align-items: center;
	gap: 0.65rem;
	flex-wrap: wrap;
}

nav a,
.text-link {
	color: var(--primary-strong);
	font-weight: 700;
	text-decoration: none;
}

/* Nav items wipe in an underline from the left on hover. */
nav a {
	position: relative;
	padding: 0.35rem 0.1rem;
	color: var(--text);
	font-size: 0.98rem;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	transition: color 140ms ease;
}

nav a::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: 0;
	width: 100%;
	height: 2px;
	background: linear-gradient(90deg, var(--primary), transparent);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 180ms ease;
}

nav a:hover,
nav a:focus-visible {
	color: var(--primary-strong);
}

nav a:hover::after,
nav a:focus-visible::after {
	transform: scaleX(1);
}

.text-link:hover {
	text-decoration: underline;
}

.header-actions {
	justify-content: end;
}

.header-actions form,
.actions form {
	margin: 0;
}

/*
	Buttons are physical: a light top edge, a dark bottom edge, and they travel
	1px on press. Gold = the action we want taken; everything else is glass.
*/
.primary-button,
.secondary-button,
.ghost-button,
button.primary-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 2.4rem;
	padding: 0 1rem;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: linear-gradient(180deg, var(--surface-2), var(--surface));
	color: var(--text);
	font-weight: 600;
	font-size: 0.95rem;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	box-shadow: var(--bevel), var(--shadow-sm);
	transition: transform 120ms ease, box-shadow 160ms ease, border-color 160ms ease,
		background-color 160ms ease, filter 160ms ease;
}

.primary-button,
button.primary-button {
	border-color: color-mix(in oklab, var(--gold) 62%, #7a4d05);
	background: linear-gradient(180deg, var(--gold-strong), var(--gold) 52%, #d69a24);
	color: var(--gold-ink);
	text-shadow: 0 1px 0 rgb(255 255 255 / 0.28);
	box-shadow:
		inset 0 1px 0 rgb(255 255 255 / 0.5),
		inset 0 -1px 0 rgb(0 0 0 / 0.22),
		0 6px 18px rgb(240 192 78 / 0.2),
		var(--shadow-sm);
}

.primary-button:hover,
button.primary-button:hover {
	filter: brightness(1.07);
	box-shadow:
		inset 0 1px 0 rgb(255 255 255 / 0.55),
		inset 0 -1px 0 rgb(0 0 0 / 0.22),
		0 10px 30px rgb(240 192 78 / 0.34),
		var(--shadow-md);
}

.secondary-button:hover,
.ghost-button:hover {
	border-color: color-mix(in oklab, var(--primary) 55%, var(--line));
	background: linear-gradient(180deg, var(--surface-3), var(--surface-2));
	color: var(--primary-strong);
}

.primary-button:hover,
.secondary-button:hover,
.ghost-button:hover,
button.primary-button:hover {
	transform: translateY(-1px);
}

.primary-button:active,
.secondary-button:active,
.ghost-button:active,
button.primary-button:active {
	transform: translateY(1px);
	filter: brightness(0.96);
	box-shadow: inset 0 2px 5px rgb(0 0 0 / 0.3);
}

.hero-play-button {
	gap: 0.5rem;
}

.hero-play-button::before {
	content: "";
	width: 1.35rem;
	height: 1.35rem;
	background: url("/ui/wooden/01_element_function_button/btn_play.png") center / contain no-repeat;
	filter: drop-shadow(0 1px 1px rgb(0 0 0 / 0.28));
}

/* button.-qualified to outrank the button.primary-button base rule */
button.hero-guest-button {
	min-height: 2.9rem;
	font-size: 1.02rem;
}

.ghost-button {
	min-height: 2.1rem;
	padding-inline: 0.8rem;
	font-size: 0.85rem;
}

button.text-link {
	border: 0;
	padding: 0;
	background: transparent;
	cursor: pointer;
}

.text-link.danger {
	color: var(--danger);
}

.full {
	width: 100%;
}

main {
	width: min(1120px, calc(100% - 2rem));
	margin-inline: auto;
}

/*
	Hero: the key art, full-bleed, carrying its own logo at the right third.
	Everything interactive sits in a column over the art's left half — which is
	painted as low-detail city precisely to be sat on. The page never draws a
	second BOXY wordmark over one that's already in the picture.
*/
.hero {
	position: relative;
	display: grid;
	grid-template-areas: "stack";
	align-items: center;
	/* The band is exactly 100vw (see margin-inline), so at `100% auto` the art
	   draws itself this tall. Everything that has to meet its bottom edge —
	   the fade especially — is derived from this rather than guessed. */
	--art-h: calc(100vw / 3.5068);
	/* Break out of main's centered column to the viewport edges. */
	margin-inline: calc(50% - 50vw);
	/* At least as tall as the art, so a short column never leaves a dead strip
	   under the band; taller if the column needs it. */
	min-height: min(var(--art-h), 34rem);
	overflow: hidden;
	isolation: isolate;
}

/*
	`100% auto`, not `cover`. The art is 3.5:1; cover-fitting it into a taller
	box crops it horizontally, which throws away the city on the left and drags
	the wordmark to the middle — the exact composition this layout is built on.
	Sized to the full width it can only ever be trimmed at the bottom, and only
	on ultra-wide, where the vertically-centered wordmark survives it.

	The layer itself still stretches the full band so its scrim below is one
	continuous wash: the column can outgrow the picture, and where it does the
	art has to dissolve into the page rather than stop at a visible edge.
*/
.hero-art {
	grid-area: stack;
	align-self: stretch;
	position: relative;
	z-index: 0;
	background: url("/boxy_cover.jpg") center top / 100% auto no-repeat;
	/*
		Fades the art out at its own bottom edge instead of painting the page
		colour over it. Two reasons it has to be a mask: whatever is behind shows
		through, so there's no colour to keep in sync with the body wash; and the
		art's height is fractional (100vw / 3.5068), so a covering gradient that
		rounds a pixel short leaves the image's bright last row showing as a
		hairline. Past the mask the element is simply gone — it can't under-cover.
	*/
	-webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
	-webkit-mask-size: 100% var(--art-h);
	-webkit-mask-repeat: no-repeat;
	mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
	mask-size: 100% var(--art-h);
	mask-repeat: no-repeat;
	image-rendering: pixelated;
}

/*
	Scrim. Angled slightly off-vertical so it reads as light falling across the
	scene rather than a panel laid over it, and it must run out before ~78% or
	it dims the crystal the whole composition is built around.
*/
.hero-art::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(96deg,
		rgb(6 14 19 / 0.94) 0%,
		rgb(6 14 19 / 0.86) 28%,
		rgb(6 14 19 / 0.58) 45%,
		rgb(6 14 19 / 0.18) 61%,
		rgb(6 14 19 / 0.03) 73%,
		transparent 84%);
}

.hero-inner {
	grid-area: stack;
	align-self: center;
	position: relative;
	z-index: 1;
	width: min(1120px, calc(100% - 2rem));
	margin-inline: auto;
	padding-block: 2.5rem;
}

.hero-copy {
	width: min(100%, 27rem);
	display: grid;
	gap: 0.4rem;
}

.hero-tagline {
	margin: 0 0 0.35rem;
	font-size: 1.06rem;
	text-wrap: pretty;
}

/* Small-caps counter with a live pulse — the "people are in there" signal. */
.eyebrow.live {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
}

.eyebrow.live::before {
	content: "";
	width: 0.5rem;
	height: 0.5rem;
	border-radius: 50%;
	background: var(--accent);
	box-shadow: 0 0 0.5rem var(--accent);
	animation: live-pulse 2.4s ease-in-out infinite;
}

@keyframes live-pulse {
	50% { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
	.eyebrow.live::before {
		animation: none;
	}
}

/*
	Narrow: nothing can sit on the art and still leave the wordmark readable, so
	the two stop overlapping — art on top, column beneath. Full width at native
	aspect would be a ~110px-tall ribbon here, so this crops to the wordmark
	instead (62% across, where it sits) and trades the city for a legible logo.
*/
@media (max-width: 60rem) {
	.hero {
		grid-template-areas:
			"art"
			"copy";
		align-items: start;
		min-height: 0;
	}

	.hero-art {
		grid-area: art;
		align-self: start;
		height: clamp(11rem, 42vw, 15rem);
		background: url("/boxy_cover.jpg") 62% center / cover no-repeat;
		/* Own height now, so the fade is a plain percentage of the element. */
		-webkit-mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
		-webkit-mask-size: 100% 100%;
		mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
		mask-size: 100% 100%;
		image-rendering: pixelated;
	}

	/* No column over the art to protect — just seat it under the header. */
	.hero-art::after {
		background: linear-gradient(180deg, rgb(6 14 19 / 0.4), transparent 38%);
	}

	.hero-inner {
		grid-area: copy;
		align-self: start;
		padding-block: 0 2rem;
	}

	.hero-copy {
		width: 100%;
	}
}

.section-heading h2,
.page-title h1 {
	margin: 0;
	font-size: clamp(1.9rem, 3.4vw, 2.9rem);
	line-height: 1.04;
	letter-spacing: -0.015em;
	text-wrap: balance;
}

/* Marks the start of a section: a gold tick, then a rule running out to nothing.
   Cheap, and it gives every section the same deliberate opening beat. */
.section-heading {
	position: relative;
	padding-top: 1.1rem;
}

.section-heading::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	width: min(100%, 14rem);
	height: 2px;
	background: linear-gradient(90deg, var(--gold) 0 2.2rem, color-mix(in oklab, var(--gold) 30%, transparent) 2.2rem, transparent);
}

.hero p,
.page-title p,
.content-card p,
.world-card p,
.admin-card p,
.detail-copy {
	color: var(--muted);
	line-height: 1.6;
}

.hero p,
.page-title p {
	max-width: 58rem;
	font-size: 1.05rem;
}

/* !important because `.hero p`/`.page-title p` below are more specific and
   would otherwise recolour these to --muted. */
.eyebrow {
	margin: 0 0 0.75rem;
	color: var(--accent) !important;
	font-size: 0.76rem !important;
	font-weight: 700;
	letter-spacing: 0.11em;
	text-transform: uppercase;
}

.page,
.section-grid {
	padding: clamp(2.5rem, 6vw, 4.5rem) 0;
}

.page-title {
	margin-bottom: 2rem;
}

.two-column,
.detail-layout {
	display: grid;
	grid-template-columns: minmax(220px, 0.72fr) minmax(0, 1.28fr);
	gap: clamp(1.25rem, 4vw, 3rem);
}

/* A two-line heading beside a tall card list otherwise strands a column of dead
   space. Pinning it keeps the section's title with the rows it belongs to and
   turns that emptiness into deliberate margin. */
@media (min-width: 60rem) {
	.two-column .section-heading {
		position: sticky;
		top: 5.5rem;
		align-self: start;
	}
}

.policy-layout {
	grid-template-columns: minmax(0, 1.65fr) minmax(220px, 0.55fr);
	align-items: start;
}

.policy-copy h2 {
	margin: 1.8rem 0 0.65rem;
	color: var(--text);
	font-size: 1.2rem;
	line-height: 1.3;
}

.policy-copy ul {
	display: grid;
	gap: 0.45rem;
	padding-left: 1.25rem;
}

.contact-layout {
	grid-template-columns: minmax(0, 1.35fr) minmax(240px, 0.65fr);
	align-items: start;
}

.deletion-request-layout {
	grid-template-columns: repeat(2, minmax(0, 1fr));
	align-items: start;
}

.deletion-next-steps {
	margin-top: clamp(1.25rem, 4vw, 3rem);
}

.contact-form {
	padding: 1rem;
	border: 1px solid var(--line);
	border-radius: 0.5rem;
	background: var(--surface);
}

.contact-form > label:first-of-type {
	margin-top: 0;
}

.contact-form .form-note {
	margin: 0.4rem 0 0;
	font-size: 0.85rem;
}

.contact-actions {
	margin-top: 1rem;
}

.contact-message-body {
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}

.pager {
	justify-content: center;
	margin-top: 1.5rem;
}

.card-list,
.content-grid,
.world-directory,
.timeline,
.status-world-list,
.character-list,
.stack-form,
.json-editor-layout {
	display: grid;
	gap: 1rem;
}

.content-grid,
.play-world-grid {
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.world-directory {
	grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
}

.metric-strip,
.status-metrics,
.play-character-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
	gap: 0.75rem;
	margin: 1rem 0 2.5rem;
}

/* The one panel surface. Lit from above and sitting on the page, not drawn
   onto it — a flat fill inside a grey hairline is the whole "corporate" tell. */
.card-list article,
.timeline article,
.content-card,
.world-card,
.admin-card,
.detail-aside,
.table-panel,
.auth-card,
.status-metrics article,
.status-world-list article,
.metric-strip div,
.docs-index-entry {
	border: 1px solid var(--line-soft);
	border-radius: var(--radius-lg);
	background: linear-gradient(180deg, var(--surface-2), var(--surface) 62%);
	box-shadow: var(--bevel), var(--shadow-sm);
}

/*
	Plated panels — the wooden kit's plate used as grain, not as colour.

	The plate is a saturated brown. Laying the site's teal over it reads as mud
	at high alpha and as a brown slab in a blue-teal page at low alpha, and
	soft-light keeps too much of the brown either way. Blended at `luminosity`
	the plate contributes only its light and grain while the hue comes from the
	tint underneath, so these panels get material without turning into wood.
	The blend re-lights the panel to the plate's mid-tone, so a shade layer on
	top pulls it back down.

	Tune per panel with --plate-tint / --plate-shade-a / --plate-shade-b.
*/
.docs-page-title,
.server-banner,
.world-card,
.world-tile,
.hero-auth,
.metric-strip .metric-servers,
.metric-strip .metric-worlds,
.metric-strip .metric-players {
	background:
		linear-gradient(var(--plate-angle, 180deg),
			rgb(8 20 27 / var(--plate-shade-a, 0.5)),
			rgb(8 20 27 / var(--plate-shade-b, 0.72))),
		url("/ui/wooden/00_common/common_bg.png") center / cover,
		var(--plate-tint, linear-gradient(180deg, var(--surface-3), var(--surface) 70%));
	background-blend-mode: normal, luminosity, normal;
}

.card-list article,
.timeline article,
.content-card,
.world-card,
.admin-card,
.detail-aside,
.auth-card,
.status-metrics article,
.status-world-list article,
.metric-strip div {
	padding: 1rem;
}

.content-card {
	display: block;
	text-decoration: none;
}

.content-card hr {
	border-color: #404040;
}

/*
	Feature cards: a cyan edge lights up on hover, so the whole list reads as
	live rather than as a stack of boxes.
*/
.card-list article {
	position: relative;
	overflow: hidden;
	transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
}

.card-list article::before {
	content: "";
	position: absolute;
	inset-block: 0;
	left: 0;
	width: 2px;
	background: linear-gradient(180deg, var(--primary), transparent);
	opacity: 0;
	transition: opacity 200ms ease;
}

.card-list article:hover {
	transform: translateX(2px);
	border-color: color-mix(in oklab, var(--primary) 40%, var(--line-soft));
	box-shadow: var(--bevel), var(--shadow-md);
}

.card-list article:hover::before {
	opacity: 1;
}

.card-list h3 {
	margin: 0 0 0.4rem;
	font-size: 1.2rem;
	color: var(--text);
}

/* Changelog: the version is the anchor, so it's set as a gold readout with the
   date trailing it rather than both competing at the same weight. */
.timeline article {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 0.15rem 0.6rem;
}

.timeline strong {
	font-family: var(--font-display);
	font-size: 1.02rem;
	color: var(--gold-strong);
	font-variant-numeric: tabular-nums;
}

.timeline span {
	color: var(--muted);
	font-size: 0.85rem;
}

.timeline p {
	grid-column: 1 / -1;
	margin: 0.35rem 0 0;
	color: var(--muted);
	line-height: 1.6;
}

.content-card h2,
.world-card h2,
.admin-card h2 {
	margin: 0 0 0.5rem;
}

/* The live numbers are the loudest thing on the strip — set like a readout. */
.metric-strip strong,
.status-metrics strong {
	display: block;
	font-family: var(--font-display);
	font-size: 2.1rem;
	font-weight: 700;
	line-height: 1.1;
	color: var(--gold-strong);
	text-shadow: 0 0 18px rgb(240 192 78 / 0.28);
	font-variant-numeric: tabular-nums;
}

.metric-strip span,
.status-metrics span {
	font-family: var(--font-display);
	font-size: 0.76rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

/* Wooden texture at low opacity for grain only — let it read as wood and the
   panel fights the blue-teal everything else is built from. */
.metric-strip .metric-servers,
.metric-strip .metric-worlds,
.metric-strip .metric-players {
	position: relative;
	min-height: 5rem;
	padding-left: 4.35rem;
	overflow: hidden;
	border-color: color-mix(in oklab, var(--gold) 26%, var(--line));
}

.metric-strip .metric-servers::before,
.metric-strip .metric-worlds::before,
.metric-strip .metric-players::before {
	content: "";
	position: absolute;
	left: 1rem;
	top: 50%;
	width: 2.4rem;
	height: 2.4rem;
	transform: translateY(-50%);
	background-position: center;
	background-repeat: no-repeat;
	background-size: contain;
	filter: drop-shadow(0 3px 4px rgb(0 0 0 / 0.35));
}

.metric-strip .metric-servers::before {
	background-image: url("/ui/wooden/01_element_function_button/btn_flag.png");
}

.metric-strip .metric-worlds::before {
	background-image: url("/ui/wooden/01_element_icon/icon_map.png");
}

.metric-strip .metric-players::before {
	background-image: url("/ui/wooden/00_common/user_empty.png");
}

.metric-strip span,
.status-metrics span,
.text-muted,
td span,
.empty-note,
.satellite-readout span {
	color: var(--muted);
}

/* ---- Player docs ----
   Two surfaces only: a plated intro/title box, and a plain reading column.
   The articles are documentation prose, so the type does the work — a page of
   bordered, gradient-filled bullets reads as a wall of buttons, not as text. */

.docs-landing-title .page-actions {
	display: flex;
	gap: 0.75rem;
	flex-wrap: wrap;
	margin-top: 1.25rem;
}

/* The title box heads a single column, so it is held to the same width as the
   thing below it — full-bleed over a 48rem article reads as two layouts. */
.docs-page-title {
	--page-icon: url("/ui/wooden/01_element_function_button/btn_question.png");
	width: min(100%, 48rem);
	display: grid;
	grid-template-columns: 4rem minmax(0, 1fr);
	gap: 0.25rem 1rem;
	align-items: start;
	margin-bottom: 2rem;
	padding: 1.15rem 1.35rem;
	overflow: hidden;
	--plate-angle: 90deg;
	border: 1px solid color-mix(in oklab, var(--gold) 30%, var(--line));
	border-radius: 0.5rem;
	box-shadow: var(--bevel), var(--shadow-md);
}

.docs-page-title::before {
	content: "";
	grid-column: 1;
	grid-row: 1 / span 6;
	width: 3.55rem;
	height: 3.55rem;
	align-self: start;
	background: var(--page-icon) center / contain no-repeat;
	filter: drop-shadow(0 4px 4px rgb(0 0 0 / 0.38));
}

.docs-page-title > * {
	grid-column: 2;
}

.docs-page-title h1 {
	font-size: clamp(2rem, 4vw, 3.35rem);
}

.docs-page-title .eyebrow {
	margin-top: 0.15rem;
	margin-bottom: 0.35rem;
}

/* The landing box heads the index list instead, which is wider. */
.docs-landing-title {
	width: min(100%, 62rem);
}

/* The landing box carries real introductory copy, so its paragraphs are set as
   body text rather than as one oversized standfirst. */
.docs-landing-title p + p {
	margin-top: 0.75rem;
	font-size: 1rem;
}

.docs-title-guide,
.docs-title-world {
	--page-icon: url("/ui/wooden/01_element_icon/icon_map.png");
}

.docs-title-start {
	--page-icon: url("/ui/wooden/01_element_function_button/btn_home.png");
}

.docs-title-controls {
	--page-icon: url("/ui/wooden/01_element_function_button/btn_compass.png");
}

.docs-title-crafting {
	--page-icon: url("/ui/wooden/01_element_icon/icon_hammer.png");
}

.docs-title-faq {
	--page-icon: url("/ui/wooden/01_element_function_button/btn_question.png");
}

/* ---- Docs index: one column of summaries, read top to bottom ---- */

.docs-index {
	display: grid;
	gap: 0.85rem;
	width: min(100%, 62rem);
}

.docs-index-entry {
	--card-icon: url("/ui/wooden/01_element_function_button/btn_question.png");
	position: relative;
	display: grid;
	grid-template-columns: 3.1rem minmax(0, 1fr);
	gap: 0.15rem 1.1rem;
	padding: 1.15rem 1.35rem;
	overflow: hidden;
	text-decoration: none;
	transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
}

.docs-index-entry::before {
	content: "";
	grid-column: 1;
	grid-row: 1 / span 4;
	width: 2.65rem;
	height: 2.65rem;
	background: var(--card-icon) center / contain no-repeat;
	filter: drop-shadow(0 3px 4px rgb(0 0 0 / 0.34));
}

.docs-index-entry > * {
	grid-column: 2;
}

.docs-index-entry:hover {
	transform: translateX(2px);
	border-color: color-mix(in oklab, var(--primary) 40%, var(--line-soft));
	box-shadow: var(--bevel), var(--shadow-md);
}

.docs-index-entry h2 {
	margin: 0 0 0.4rem;
	font-size: 1.32rem;
}

.docs-index-entry p {
	margin: 0 0 0.6rem;
	color: var(--muted);
	line-height: 1.65;
}

/* The preview snippet: what the page actually tells you, in the page's own
   voice, so the reader can decide whether to open it. */
.docs-index-entry .docs-index-preview {
	margin-bottom: 0.7rem;
	padding-left: 0.85rem;
	border-left: 2px solid color-mix(in oklab, var(--gold) 45%, transparent);
	color: color-mix(in oklab, var(--text) 62%, var(--muted));
}

.docs-index-covers {
	margin: 0;
	color: var(--muted);
	font-size: 0.86rem;
}

.docs-index-covers strong {
	color: var(--accent);
	font-family: var(--font-display);
	font-size: 0.76rem;
	font-weight: 700;
	letter-spacing: 0.11em;
	text-transform: uppercase;
}

.docs-index-start {
	--card-icon: url("/ui/wooden/01_element_function_button/btn_home.png");
}

.docs-index-controls {
	--card-icon: url("/ui/wooden/01_element_function_button/btn_compass.png");
}

.docs-index-crafting {
	--card-icon: url("/ui/wooden/01_element_icon/icon_hammer.png");
}

.docs-index-world {
	--card-icon: url("/ui/wooden/01_element_icon/icon_map.png");
}

.docs-index-faq {
	--card-icon: url("/ui/wooden/01_element_function_button/btn_question.png");
}

/* ---- Docs article: a reading column ---- */

.docs-detail {
	width: min(100%, 48rem);
}

.docs-copy {
	color: var(--muted);
	font-size: 1.02rem;
	line-height: 1.72;
}

.docs-copy > p:first-child {
	color: color-mix(in oklab, var(--text) 70%, var(--muted));
	font-size: 1.12rem;
}

/* Section openings borrow the site's gold tick + fading rule, which separates
   an article's parts without drawing a box around each one. */
.docs-copy h2 {
	position: relative;
	margin: 2.4rem 0 0.8rem;
	padding-top: 1.05rem;
	color: var(--text);
	font-size: 1.32rem;
	line-height: 1.25;
}

.docs-copy h2::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	width: min(100%, 12rem);
	height: 2px;
	background: linear-gradient(90deg, var(--gold) 0 2.2rem, color-mix(in oklab, var(--gold) 30%, transparent) 2.2rem, transparent);
}

.docs-copy h2:first-child {
	margin-top: 0;
}

.docs-copy h3 {
	margin: 1.6rem 0 0.5rem;
	color: var(--text);
	font-size: 1.06rem;
	line-height: 1.3;
}

.docs-copy p {
	margin: 0 0 1.05rem;
}

.docs-copy strong {
	color: var(--text);
	font-weight: 650;
}

.docs-copy ul,
.docs-copy ol {
	display: grid;
	gap: 0.4rem;
	margin: 0 0 1.15rem;
	padding-left: 1.35rem;
}

.docs-copy li::marker {
	color: color-mix(in oklab, var(--gold) 70%, var(--muted));
}

.docs-copy li {
	padding-left: 0.15rem;
}

.docs-copy dl {
	grid-template-columns: minmax(7rem, auto) 1fr;
	gap: 0.55rem 1.1rem;
	margin: 0 0 1.15rem;
}

.docs-copy dt {
	color: var(--text);
	font-weight: 650;
}

.docs-copy dd {
	color: var(--muted);
}

/* Key/command reference tables. Wrapped so a narrow phone scrolls the table
   rather than the page. */
.docs-table {
	overflow-x: auto;
	margin: 0 0 1.35rem;
}

.docs-copy table {
	margin: 0;
	color: var(--muted);
	font-size: 0.97rem;
}

.docs-copy th {
	color: var(--text);
	font-family: var(--font-display);
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	white-space: nowrap;
}

.docs-copy td:first-child {
	white-space: nowrap;
}

.docs-copy code {
	display: inline-block;
	padding: 0.08rem 0.32rem;
	border: 1px solid var(--line);
	border-radius: 0.3rem;
	background: var(--sunken);
	color: var(--text);
	font: 700 0.9em ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* One aside per section at most: a gold rule and a slightly lifted ground,
   used for the thing a player will otherwise learn by losing something. */
.docs-note {
	margin: 0 0 1.35rem;
	padding: 0.85rem 1.1rem;
	border-left: 3px solid var(--gold);
	border-radius: 0 var(--radius) var(--radius) 0;
	background: linear-gradient(90deg, rgb(240 192 78 / 0.09), transparent 70%);
}

.docs-copy .docs-note p:last-child {
	margin-bottom: 0;
}

.docs-note strong {
	color: var(--gold-strong);
}

/* Footer of an article: where to go next. */
.docs-next {
	margin-top: 2.5rem;
	padding-top: 1.1rem;
	border-top: 1px solid var(--line-soft);
}

.docs-next p {
	margin: 0;
}

/* ---- World directory: server groups, world cards, character lists ----
   Shared by /worlds, /status, and the account page's character section. */

.server-group {
	margin-top: 2.4rem;
}

.server-banner {
	display: flex;
	align-items: center;
	gap: 0.85rem;
	flex-wrap: wrap;
	margin-bottom: 1rem;
	padding: 0.55rem 1rem 0.55rem 0.55rem;
	overflow: hidden;
	--plate-angle: 90deg;
	--plate-shade-a: 0.72;
	--plate-shade-b: 0.42;
	border: 1px solid color-mix(in oklab, var(--gold) 30%, var(--line));
	border-radius: var(--radius-lg);
	box-shadow: var(--bevel), var(--shadow-sm);
}

.server-banner::before {
	content: "";
	flex: 0 0 auto;
	width: 2.85rem;
	height: 2.85rem;
	background: url("/ui/wooden/01_element_function_button/btn_flag.png") center / contain no-repeat;
	filter: drop-shadow(0 3px 3px rgb(0 0 0 / 0.35));
}

.server-banner-title h2,
.server-banner-title h3 {
	margin: 0;
	font-size: 1.35rem;
	line-height: 1.2;
}

.server-banner-title span {
	color: var(--muted);
	font-size: 0.85rem;
}

.server-banner-meta {
	display: flex;
	align-items: center;
	gap: 0.85rem;
	flex-wrap: wrap;
	margin-left: auto;
}

.server-banner-stat {
	color: var(--muted);
	font-size: 0.9rem;
	font-weight: 650;
}

.server-banner.compact {
	margin-bottom: 0;
	padding: 0.4rem 0.85rem 0.4rem 0.5rem;
}

.server-banner.compact::before {
	width: 2.1rem;
	height: 2.1rem;
}

.server-banner.compact .server-banner-title h2,
.server-banner.compact .server-banner-title h3 {
	font-size: 1.05rem;
}

.status-chip {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.16rem 0.62rem;
	border: 1px solid color-mix(in oklab, var(--accent) 40%, transparent);
	border-radius: 999px;
	background: color-mix(in oklab, var(--accent) 13%, transparent);
	color: var(--accent);
	font-size: 0.74rem;
	font-weight: 800;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	white-space: nowrap;
}

.status-chip::before {
	content: "";
	width: 0.5rem;
	height: 0.5rem;
	border-radius: 50%;
	background: currentColor;
	box-shadow: 0 0 0.4rem currentColor;
}

.status-chip.offline {
	border-color: color-mix(in oklab, var(--muted) 30%, transparent);
	background: color-mix(in oklab, var(--muted) 9%, transparent);
	color: var(--muted);
}

.status-chip.offline::before {
	box-shadow: none;
}

.world-card {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border-color: color-mix(in oklab, var(--gold) 24%, var(--line));
	box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.07);
}

.world-card.is-offline {
	border-color: var(--line);
	background: var(--surface);
	box-shadow: none;
}

.world-card h3 {
	margin: 0 0 0.5rem;
	font-size: 1.3rem;
	line-height: 1.2;
}

.world-card > .primary-button,
.world-card-actions {
	margin-top: auto;
}

.world-card-header,
.world-stats,
.status-world-list article {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1rem;
}

.world-stats {
	margin: 0.9rem 0 1.15rem;
	flex-wrap: wrap;
	justify-content: flex-start;
	gap: 0.5rem 1.35rem;
}

.world-stat {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	color: var(--muted);
	font-size: 0.9rem;
}

.world-stat::before {
	content: "";
	flex: 0 0 auto;
	width: 1.3rem;
	height: 1.3rem;
	background: var(--stat-icon) center / contain no-repeat;
	filter: drop-shadow(0 2px 2px rgb(0 0 0 / 0.3));
}

.world-stat-players {
	--stat-icon: url("/ui/wooden/00_common/user_empty.png");
}

.world-stat-id {
	--stat-icon: url("/ui/wooden/01_element_icon/icon_map.png");
}

.world-card-actions {
	position: relative;
	display: flex;
	align-items: center;
	gap: 0.65rem;
	padding-top: 1.05rem;
}

.world-card-actions > .primary-button,
.world-card-actions > .secondary-button {
	flex: 1 1 auto;
}

/* The "Play as Guest" button posts a form (antiforgery token), so the flex
   sizing that normally lands on the buttons passes through the form wrapper. */
.world-card-actions > form {
	display: flex;
	flex: 1 1 auto;
}

.world-card-actions > form > .primary-button,
.world-card-actions > form > .secondary-button {
	flex: 1 1 auto;
	width: 100%;
}

/* Signed-in-guest nudge above the directory: convert to keep progress. */
.guest-banner {
	margin: 0 0 1.5rem;
	padding: 0.9rem 1.15rem;
	border: 1px solid var(--line);
	border-radius: 10px;
	background: var(--surface);
}

.guest-banner p {
	margin: 0;
}

/* Home-page world showcase: one tile per public world, led by its screenshot
   (or the generated per-world placeholder until one is dropped into
   img/worlds/). Live tiles are links through /worlds/play/{id}. */
.world-showcase {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
	gap: 1.25rem;
	margin-top: 1.5rem;
}

.world-tile {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border: 1px solid var(--line-soft);
	border-radius: var(--radius-lg);
	box-shadow: var(--bevel), var(--shadow-sm);
	text-decoration: none;
	transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}

/* A live world lifts and catches the crystal light; an offline one can't. */
a.world-tile:hover,
a.world-tile:focus-visible {
	transform: translateY(-4px);
	border-color: color-mix(in oklab, var(--primary) 60%, var(--line));
	box-shadow: var(--bevel), var(--shadow-md), var(--glow);
}

.world-tile.is-offline {
	border-color: var(--line-soft);
	background: var(--surface);
	box-shadow: none;
	opacity: 0.7;
	filter: saturate(0.5);
}

.world-tile-shot {
	position: relative;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	border-bottom: 1px solid rgb(0 0 0 / 0.45);
}

.world-tile-shot img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 300ms ease;
}

a.world-tile:hover .world-tile-shot img {
	transform: scale(1.04);
}

.world-tile.is-offline .world-tile-shot img,
.world-tile.is-offline .world-tile-placeholder {
	filter: grayscale(0.85);
}

.world-tile-shot .status-chip {
	position: absolute;
	top: 0.6rem;
	right: 0.6rem;
	backdrop-filter: blur(4px);
}

/* Screenshot stand-in: each world gets a stable hue (set inline as --world-hue,
   banded to green→blue by WorldScreenshots.PlaceholderHue) lighting a voxel
   grid. Muted on purpose — it stands in for a screenshot, so it shouldn't
   out-shout the tiles that have one. */
.world-tile-placeholder {
	display: grid;
	place-items: center;
	height: 100%;
	background:
		radial-gradient(circle at 22% 30%, hsl(var(--world-hue, 180) 44% 58% / 0.26), transparent 14rem),
		linear-gradient(145deg,
			hsl(var(--world-hue, 180) 34% 20% / 0.96),
			hsl(calc(var(--world-hue, 180) + 26) 30% 13% / 0.94) 55%,
			rgb(7 18 25 / 0.98)),
		repeating-linear-gradient(135deg, rgb(255 255 255 / 0.05) 0 1px, transparent 1px 22px);
}

.world-tile-placeholder span {
	font-family: var(--font-display);
	font-size: 3.4rem;
	font-weight: 700;
	color: hsl(var(--world-hue, 180) 45% 76% / 0.8);
	text-shadow: 0 4px 14px rgb(0 0 0 / 0.55);
}

.world-tile-body {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	flex: 1;
	padding: 1rem 1.1rem 1.15rem;
}

.world-tile-body h3 {
	margin: 0;
	font-size: 1.25rem;
	line-height: 1.2;
	color: var(--text);
}

.world-tile-body p {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	margin: 0;
	color: var(--muted);
	line-height: 1.5;
}

.world-tile-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 1rem;
	margin-top: auto;
	padding-top: 0.6rem;
}

.world-tile-characters {
	padding: 0.15rem 0.6rem;
	border: 1px solid color-mix(in oklab, var(--accent) 45%, transparent);
	border-radius: 999px;
	background: color-mix(in oklab, var(--accent) 12%, transparent);
	color: var(--accent);
	font-size: 0.78rem;
	font-weight: 700;
}

.world-showcase-footer {
	margin: 1.5rem 0 0;
}

.character-list {
	gap: 0.55rem;
	margin: 0 0 1.3rem;
}

.character-list-label {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	margin: 0 0 0.15rem;
	color: var(--accent);
	font-size: 0.76rem;
	font-weight: 800;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.empty-note {
	font-size: 0.9rem;
}

/* One approved app inside the account card: name and dates on the left, the
   button that takes the approval back on the right. The button keeps its own
   width here rather than spanning the card, so a list of devices does not read
   as a stack of primary actions. */
.linked-client {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.9rem;
	padding: 0.6rem 0;
	border-top: 1px solid var(--line-soft);
}

.linked-client span {
	display: block;
	font-size: 0.82rem;
}

.linked-client button {
	flex: none;
	width: auto;
}

.character-pick {
	display: flex;
	align-items: center;
	gap: 0.8rem;
	width: 100%;
	padding: 0.55rem 0.85rem 0.55rem 0.6rem;
	border: 1px solid color-mix(in oklab, var(--line) 82%, var(--gold));
	border-radius: 0.5rem;
	background:
		linear-gradient(180deg, rgb(33 67 83 / 0.9), rgb(8 20 27 / 0.95)),
		linear-gradient(90deg, rgb(240 191 102 / 0.1), transparent 45%);
	color: var(--text);
	text-align: left;
	text-decoration: none;
	cursor: pointer;
	box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.05);
	transition: border-color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}

.character-pick::before {
	content: "";
	flex: 0 0 auto;
	width: 2.5rem;
	height: 2.55rem;
	background: url("/ui/wooden/00_common/user_empty.png") center / contain no-repeat;
	filter: drop-shadow(0 2px 3px rgb(0 0 0 / 0.32));
}

.character-pick::after {
	content: "";
	flex: 0 0 auto;
	width: 1rem;
	height: 1.3rem;
	margin-left: auto;
	background: url("/ui/wooden/00_common/arrow_right_n.png") center / contain no-repeat;
	filter: drop-shadow(0 2px 2px rgb(0 0 0 / 0.3));
	opacity: 0.45;
	transition: opacity 120ms ease, transform 120ms ease;
}

.character-pick:hover,
.character-pick:focus-visible {
	border-color: color-mix(in oklab, #f0bf66 55%, var(--line));
	transform: translateY(-1px);
	box-shadow:
		inset 0 1px 0 rgb(255 255 255 / 0.08),
		0 6px 14px rgb(0 0 0 / 0.28);
}

.character-pick:hover::after,
.character-pick:focus-visible::after {
	opacity: 1;
	transform: translateX(2px);
}

.character-pick-body {
	display: grid;
	gap: 0.1rem;
	min-width: 0;
}

.character-pick-body strong {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.character-pick .character-pick-meta {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	color: var(--muted);
	font-size: 0.85rem;
}

.online-now {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	color: var(--accent);
	font-size: 0.78rem;
	font-weight: 750;
	font-style: normal;
}

.online-now::before {
	content: "";
	width: 0.45rem;
	height: 0.45rem;
	border-radius: 50%;
	background: currentColor;
	box-shadow: 0 0 0.35rem currentColor;
}

.status-world-list {
	gap: 1.35rem;
}

.status-server {
	display: grid;
	gap: 0.6rem;
}

.status-world-list article strong {
	display: block;
}

.status-world-list article > div span {
	color: var(--muted);
	font-size: 0.85rem;
}

.world-card-host {
	color: var(--muted);
	font-size: 0.85rem;
	font-weight: 650;
	white-space: nowrap;
}

/*
	Sign-in / register get the same key art as the home hero — arriving here from
	the header shouldn't feel like leaving the game. Same rule as the hero: the
	form takes the art's left half and never covers the wordmark.
*/
.auth-page {
	position: relative;
	min-height: calc(100svh - 7rem);
	display: grid;
	align-items: center;
	--art-h: calc(100vw / 3.5068);
	/* This element IS <main>, which sets an explicit width — so the bleed needs
	   width:auto too, or the negative margins just shift the column sideways. */
	width: auto;
	margin-inline: calc(50% - 50vw);
	padding: 2.5rem max(calc(50vw - 560px), 1.5rem);
	overflow: hidden;
	isolation: isolate;
}

.auth-page::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	background: url("/boxy_cover.jpg") center top / 100% auto no-repeat;
	-webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
	-webkit-mask-size: 100% var(--art-h);
	-webkit-mask-repeat: no-repeat;
	mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
	mask-size: 100% var(--art-h);
	mask-repeat: no-repeat;
}

.auth-page::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	background: linear-gradient(96deg,
		rgb(6 14 19 / 0.95) 0%,
		rgb(6 14 19 / 0.88) 30%,
		rgb(6 14 19 / 0.6) 46%,
		rgb(6 14 19 / 0.2) 62%,
		transparent 84%);
}

.auth-card {
	position: relative;
	z-index: 1;
	width: min(100%, 27rem);
	padding: 1.35rem;
	box-shadow: var(--bevel), 0 0 0 1px rgb(0 0 0 / 0.5), var(--shadow-lg);
}

.auth-card h1 {
	margin: 0 0 1rem;
	font-size: 1.8rem;
}

/* Same trade as the home hero: full width the art is an unreadable ribbon here,
   so it becomes a banner cropped to the wordmark with the form below it. */
@media (max-width: 60rem) {
	.auth-page {
		--auth-banner: clamp(9rem, 38vw, 13rem);
		align-items: start;
		padding-top: calc(var(--auth-banner) + 1.5rem);
	}

	.auth-page::before {
		inset: 0 0 auto 0;
		height: var(--auth-banner);
		background: url("/boxy_cover.jpg") 62% center / cover no-repeat;
		-webkit-mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
		-webkit-mask-size: 100% 100%;
		mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
		mask-size: 100% 100%;
	}

	.auth-page::after {
		inset: 0 0 auto 0;
		height: var(--auth-banner);
		background: linear-gradient(180deg, rgb(6 14 19 / 0.4), transparent 38%);
	}
}

label {
	display: block;
	margin: 0.8rem 0 0.3rem;
	color: var(--muted);
	font-family: var(--font-display);
	font-size: 0.78rem;
	font-weight: 600;
	letter-spacing: 0.07em;
	text-transform: uppercase;
}

/* Recessed rather than flat: fields read as cut into the panel, which is what
   separates them from the raised controls. */
input,
select,
textarea {
	width: 100%;
	padding: 0.65rem 0.7rem;
	border: 1px solid var(--line-soft);
	border-radius: var(--radius);
	background: var(--sunken);
	color: var(--text);
	box-shadow: inset 0 2px 5px rgb(0 0 0 / 0.4);
	transition: border-color 150ms ease, box-shadow 150ms ease;
}

input:hover,
select:hover,
textarea:hover {
	border-color: var(--line);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
	outline: none;
	border-color: var(--primary);
	box-shadow: inset 0 2px 5px rgb(0 0 0 / 0.4), var(--glow);
}

::placeholder {
	color: color-mix(in oklab, var(--muted) 62%, transparent);
}

textarea {
	resize: vertical;
}

.appeal-dialog {
	width: min(92vw, 42rem);
	padding: 1.25rem;
	border: 1px solid var(--line);
	border-radius: 0.5rem;
	background: var(--surface);
	color: var(--text);
}

.appeal-dialog::backdrop {
	background: rgb(0 0 0 / 0.72);
}

.appeal-dialog h3 {
	margin: 0;
}

.discipline-grid {
	margin: 1rem 0 2rem;
}

.appeal-history {
	margin: 0.75rem 0;
	padding: 0.75rem;
	border-left: 3px solid var(--line);
}

.appeal-history p {
	margin: 0.25rem 0;
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}

/* Inline checkbox + label, overriding the block `label` and full-width `input`
   defaults used by the stacked text fields above. */
.checkbox-row {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin: 0.9rem 0 0.3rem;
}

.checkbox-row input[type="checkbox"] {
	width: auto;
	margin: 0;
	flex: 0 0 auto;
	accent-color: var(--primary);
	box-shadow: none;
}

.checkbox-row input[type="checkbox"]:focus-visible {
	outline: 2px solid var(--primary);
	outline-offset: 3px;
	box-shadow: 0 0 0 4px color-mix(in oklab, var(--primary) 18%, transparent);
}

/* Undo the uppercase display treatment the `label` rule gives field captions.
   This one is a sentence the player has to actually read (the age gate is the
   load-bearing case), not a caption. */
.checkbox-row span {
	color: var(--text);
	font-family: var(--font-body);
	font-size: 0.95rem;
	font-weight: 500;
	letter-spacing: normal;
	text-transform: none;
}

.toolbar {
	margin-bottom: 1rem;
}

.toolbar input {
	max-width: 34rem;
}

.validation,
.notice.error {
	color: var(--danger) !important;
}

.validation {
	display: block;
	margin-top: 0.25rem;
	font-size: 0.85rem;
}

.form-note {
	color: var(--muted);
}

.notice-card {
	display: grid;
	gap: 0.35rem;
	padding: 1rem;
	border: 1px solid var(--border);
	border-radius: 0.55rem;
	background: color-mix(in oklab, var(--surface) 78%, transparent);
}

.notice-card span {
	color: var(--muted);
	font-size: 0.85rem;
}

.notice-card strong {
	color: var(--text);
}

.notice-card p {
	margin: 0;
	color: var(--muted);
}

.notice {
	display: inline-block;
	padding: 0.55rem 0.7rem;
	border: 1px solid color-mix(in oklab, var(--accent) 35%, transparent);
	border-radius: 0.4rem;
	background: color-mix(in oklab, var(--accent) 12%, transparent);
	color: var(--accent) !important;
}

.notice.error {
	border-color: color-mix(in oklab, var(--danger) 35%, transparent);
	background: color-mix(in oklab, var(--danger) 12%, transparent);
}

.check-row {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin: 0;
}

.check-row input {
	width: auto;
}

.table-panel {
	overflow-x: auto;
}

table {
	width: 100%;
	border-collapse: collapse;
}

th,
td {
	padding: 0.75rem;
	border-bottom: 1px solid var(--line);
	text-align: left;
	vertical-align: top;
}

td span {
	display: block;
	margin-top: 0.25rem;
	font-size: 0.75rem;
	overflow-wrap: anywhere;
}

dl {
	display: grid;
	grid-template-columns: 7rem 1fr;
	gap: 0.5rem 1rem;
}

dt {
	color: var(--muted);
}

dd {
	margin: 0;
}

.site-footer {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1.35rem;
	flex-wrap: wrap;
	margin-top: 4rem;
	padding: 2.5rem 1rem;
	border-top: 1px solid var(--line-soft);
	/* Closes the page off with the same deep wash the hero opens on. */
	background:
		radial-gradient(80% 130% at 50% 100%, rgb(33 67 83 / 0.5), transparent 70%),
		var(--bg-deep);
	color: var(--muted);
}

.site-footer a:not(.footer-brand) {
	font-family: var(--font-display);
	font-size: 0.85rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-decoration: none;
	transition: color 140ms ease;
}

.site-footer a:not(.footer-brand):hover {
	color: var(--primary-strong);
}

.footer-brand {
	display: inline-flex;
	width: 5.25rem;
	line-height: 0;
	opacity: 0.85;
	transition: opacity 140ms ease;
}

.footer-brand:hover {
	opacity: 1;
}

.satellite-toolbar {
	display: grid;
	grid-template-columns: minmax(220px, 1.4fr) minmax(120px, 0.6fr) minmax(120px, 0.6fr) auto auto;
	gap: 0.75rem;
	align-items: end;
	margin-bottom: 1rem;
}

.satellite-toolbar label {
	margin: 0;
}

.satellite-toolbar label span {
	display: block;
	margin-bottom: 0.3rem;
	color: var(--muted);
	font-size: 0.9rem;
	font-weight: 650;
}

.satellite-shell {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 180px;
	gap: 1rem;
	align-items: start;
}

.satellite-map-wrap {
	min-height: min(72svh, 760px);
	display: grid;
	place-items: center;
	overflow: hidden;
	border: 1px solid var(--line);
	border-radius: 0.5rem;
	background: #05070b;
}

#satellite-map {
	width: min(100%, 760px);
	aspect-ratio: 1;
	height: auto;
	background: #05070b;
	cursor: grab;
	image-rendering: pixelated;
	image-rendering: crisp-edges;
	touch-action: none;
}

#satellite-map:active {
	cursor: grabbing;
}

.satellite-readout {
	display: grid;
	gap: 0.35rem;
	padding: 0.9rem;
	border: 1px solid var(--line);
	border-radius: 0.5rem;
	background: var(--surface);
}

.satellite-readout strong {
	font-size: 1.35rem;
}

.texture-preview-cell {
	width: 3rem;
}

.texture-thumb,
.color-swatch,
.face-tile .texture-preview {
	border: 1px solid var(--line);
	border-radius: 0.25rem;
	image-rendering: pixelated;
}

.texture-thumb,
.color-swatch {
	width: 32px;
	height: 32px;
}

.color-swatch {
	display: inline-block;
}

.color-swatch.inline,
.color-swatch.large {
	vertical-align: middle;
}

.color-swatch.large,
.face-tile .texture-preview {
	width: 64px;
	height: 64px;
}

.texture-preview-large img {
	width: 128px;
	height: 128px;
	border: 1px solid var(--line);
	border-radius: 0.3rem;
	image-rendering: pixelated;
}

.face-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1rem;
}

.face-tile {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.3rem;
}

.face-label {
	font-size: 0.85rem;
	font-weight: 650;
}

.face-overlay-label {
	color: var(--muted);
	font-size: 0.75rem;
}

.node-preview-3d {
	display: flex;
	justify-content: center;
	padding: 0.5rem;
	border: 1px solid var(--line);
	border-radius: 0.4rem;
	background: var(--surface);
}

.node-preview-3d canvas {
	border-radius: 0.3rem;
}

.json-editor-layout textarea {
	min-height: 30rem;
	padding: 1rem;
	background: var(--sunken);
	font-family: "SF Mono", "Fira Code", Consolas, monospace;
	font-size: 0.85rem;
	line-height: 1.5;
	tab-size: 2;
}

@media (max-width: 760px) {
	.site-header,
	.two-column,
	.detail-layout,
	.satellite-toolbar,
	.satellite-shell {
		grid-template-columns: 1fr;
	}

	.site-header {
		position: static;
		gap: 0.85rem;
	}

	.header-actions,
	nav {
		justify-content: start;
	}

	.brand {
		width: 7.75rem;
	}

	.hero {
		min-height: 62svh;
		padding-inline: 1rem;
	}

	.hero::after {
		background: linear-gradient(0deg, rgb(17 20 22 / 0.92), rgb(17 20 22 / 0.35));
	}

	.metric-strip,
	.status-metrics {
		grid-template-columns: 1fr;
	}

	.world-card-header {
		flex-wrap: wrap;
	}

	.server-banner-meta {
		width: 100%;
		margin-left: 0;
		padding-left: 3.7rem;
	}

	.docs-page-title,
	.docs-index-entry {
		grid-template-columns: 1fr;
	}

	.docs-page-title::before,
	.docs-index-entry::before {
		grid-column: 1;
		grid-row: auto;
	}

	.docs-page-title > *,
	.docs-index-entry > * {
		grid-column: 1;
	}

	.toolbar {
		align-items: stretch;
		flex-direction: column;
	}

	.satellite-map-wrap {
		min-height: auto;
	}

	.face-grid {
		grid-template-columns: repeat(2, 1fr);
	}

	dl {
		grid-template-columns: 1fr;
	}
}

/* Home hero auth widget ---------------------------------------------------- */

/*
	The console the whole hero funnels into. Heavier glass than a normal panel:
	it has to hold its own over the busiest part of the artwork.
*/
.hero-auth {
	position: relative;
	z-index: 2;
	width: min(100%, 27rem);
	margin-top: 1.1rem;
	margin-left: auto;
	margin-right: auto;
	padding: 1.15rem;
	/* Nearly opaque: this one sits on the artwork, not on the page. */
	--plate-shade-a: 0.82;
	--plate-shade-b: 0.93;
	--plate-tint: linear-gradient(180deg, #1d3d4d, #0b1c25 75%);
	border: 1px solid color-mix(in oklab, var(--primary) 22%, var(--line));
	border-radius: var(--radius-lg);
	box-shadow:
		var(--bevel),
		0 0 0 1px rgb(0 0 0 / 0.5),
		var(--shadow-lg);
	backdrop-filter: blur(6px);
}

/* Crystal light catching the top edge. */
.hero-auth::before {
	content: "";
	position: absolute;
	inset-inline: 12%;
	top: -1px;
	height: 1px;
	background: linear-gradient(90deg, transparent, var(--primary), transparent);
	opacity: 0.85;
}

.hero-auth h2 {
	margin: 0.25rem 0 0.5rem;
	font-size: 1.5rem;
}

/* CSS-only tab toggle for the sign-in / register card. */
.auth-tab-input {
	position: absolute;
	opacity: 0;
	pointer-events: none;
}

.auth-tablist {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0.3rem;
	margin-bottom: 0.9rem;
	border: 1px solid var(--line-soft);
	border-radius: var(--radius);
	padding: 0.25rem;
	background: var(--sunken);
	box-shadow: inset 0 2px 6px rgb(0 0 0 / 0.45);
}

.auth-tablist label {
	margin: 0;
	text-align: center;
	padding: 0.5rem;
	border-radius: calc(var(--radius) - 1px);
	cursor: pointer;
	color: var(--muted);
	font-family: var(--font-display);
	font-size: 0.9rem;
	font-weight: 600;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	transition: background-color 150ms ease, color 150ms ease;
}

.auth-tablist label:hover {
	color: var(--primary-strong);
}

#tab-signin:checked ~ .auth-tablist label[for="tab-signin"],
#tab-register:checked ~ .auth-tablist label[for="tab-register"] {
	background: linear-gradient(180deg, var(--surface-3), var(--surface-2));
	color: var(--text);
	box-shadow: var(--bevel), var(--shadow-sm);
}

/* The radios are visually hidden, so the ring has to land on their labels. */
.auth-tab-input:focus-visible ~ .auth-tablist label[for="tab-signin"],
.auth-tab-input:focus-visible ~ .auth-tablist label[for="tab-register"] {
	outline: 2px solid var(--primary);
	outline-offset: 1px;
}

.auth-panel {
	display: none;
	flex-direction: column;
}

#tab-signin:checked ~ .auth-signin,
#tab-register:checked ~ .auth-register {
	display: flex;
}

.auth-panel .full {
	margin-top: 1rem;
}

/* "or" rule between the credential forms and the guest path. */
.auth-alt {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 0.7rem;
	margin: 1rem 0 0.75rem;
	color: var(--muted);
	font-family: var(--font-display);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.auth-alt::before,
.auth-alt::after {
	content: "";
	height: 1px;
	background: linear-gradient(90deg, transparent, var(--line), transparent);
}

/* Google's pre-approved Android/Web asset is rendered byte-for-byte and at its
   intended 180x40 CSS size. Keep hover/focus treatment outside the artwork. */
.google-signin-form {
	display: flex;
	justify-content: center;
}

.google-signin-button {
	display: block;
	width: 180px;
	height: 40px;
	padding: 0;
	border: 0;
	border-radius: 20px;
	background: transparent;
	cursor: pointer;
}

.google-signin-button img {
	display: block;
	width: 180px;
	height: 40px;
}

.google-signin-button:focus-visible {
	outline: 3px solid var(--accent, #f0ba59);
	outline-offset: 3px;
}

.centered-note {
	text-align: center;
}

/* ---- Admin area ---- */
.admin-nav {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem;
	margin: 1rem 0 1.5rem;
	border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.admin-nav-link {
	padding: 0.5rem 0.9rem;
	border-radius: 8px 8px 0 0;
	color: inherit;
	text-decoration: none;
	font-weight: 600;
	font-size: 0.95rem;
	opacity: 0.7;
	border-bottom: 2px solid transparent;
}
.admin-nav-link:hover { opacity: 1; }
.admin-nav-link.active {
	opacity: 1;
	border-bottom-color: currentColor;
}
.admin-grid {
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	align-items: start;
}
.badge {
	display: inline-block;
	padding: 0.1rem 0.5rem;
	border-radius: 999px;
	font-size: 0.78rem;
	font-weight: 700;
	background: rgba(255, 255, 255, 0.12);
}
.badge.ok { background: rgba(76, 175, 80, 0.25); }
.badge.warn { background: rgba(255, 193, 7, 0.25); }
.badge.bad { background: rgba(244, 67, 54, 0.28); }
.admin-card form + form { margin-top: 1rem; }
.muted { opacity: 0.65; }
.inline-form { display: inline; }
/* Several links in one table cell — spaced so they don't read as one phrase. */
.inline-actions { display: inline-flex; gap: 0.85rem; flex-wrap: wrap; }
.field-row { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: end; }
.field-row > * { flex: 1 1 auto; }

/* ---------------------------------------------------------------------------
   Consent, birthdate, and parental controls
   ------------------------------------------------------------------------ */

/* The consent block needs room for a readable line length inside the scroll
   box, so the cards that host it are wider than the plain sign-in card. */
.auth-card-wide {
	width: min(100%, 44rem);
	/* This card is a grid item. The preformatted legal documents otherwise
	   contribute their desktop line width as its automatic minimum, which
	   makes the whole form overflow a phone even though its declared width is
	   100%. */
	min-width: 0;
}

.field-help {
	margin: 0.35rem 0 0;
	color: var(--muted);
	font-size: 0.85rem;
	line-height: 1.5;
}

/* Birthdate is one of the two required decisions on this screen, so give it a
   distinct control panel instead of letting the short input disappear among
   the ordinary account fields. */
.birthdate-field {
	margin: 1.1rem 0 0.35rem;
	padding: 0.95rem 1rem 1rem;
	border: 1px solid color-mix(in oklab, var(--primary) 52%, var(--line));
	border-radius: var(--radius-lg);
	background:
		linear-gradient(135deg,
			color-mix(in oklab, var(--surface-2) 88%, var(--primary)),
			var(--surface) 72%);
	box-shadow: var(--bevel), 0 8px 22px rgb(0 0 0 / 0.2);
}

.birthdate-field > label {
	margin: 0 0 0.5rem;
	color: var(--primary-strong);
	font-size: 0.86rem;
}

/* A date is a short value, so it stays compact while retaining the height and
   visual weight of Boxy's primary controls. */
.birthdate-input {
	max-width: 15rem;
	min-height: 3rem;
	padding: 0.7rem 0.85rem;
	border-color: color-mix(in oklab, var(--primary) 62%, var(--line));
	background: linear-gradient(180deg,
		color-mix(in oklab, var(--sunken) 84%, var(--primary)),
		var(--sunken));
	font-family: var(--font-display);
	font-size: 1.05rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	box-shadow:
		inset 0 2px 5px rgb(0 0 0 / 0.42),
		0 0 0 1px color-mix(in oklab, var(--primary) 16%, transparent);
}

.birthdate-field .field-help {
	max-width: 34rem;
}

.consent-block {
	margin: 1.35rem 0 0.35rem;
}

.consent-heading {
	margin: 0 0 0.75rem;
	font-size: 1.05rem;
}

.consent-doc + .consent-doc {
	margin-top: 1.35rem;
}

.consent-doc-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.75rem;
	flex-wrap: wrap;
	margin-bottom: 0.4rem;
}

.consent-doc-head h3 {
	margin: 0;
	font-size: 1rem;
}

.consent-version {
	color: var(--muted);
	font-size: 0.8rem;
	white-space: nowrap;
}

/* The agreement viewer: a sunken well the reader scrolls, matching the recessed
   treatment used for form fields. Height is capped in `vh` as well as `rem` so
   the accept checkbox below it stays reachable on a short phone screen without
   scrolling the whole page first. */
.consent-scroll {
	max-height: min(22rem, 45vh);
	overflow-y: auto;
	overscroll-behavior: contain;
	/* Momentum scrolling on iOS, and a visible target for a mouse wheel. */
	-webkit-overflow-scrolling: touch;
	padding: 0.85rem 1rem;
	background: var(--sunken);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	box-shadow: inset 0 2px 6px rgb(0 0 0 / 0.45);
	scrollbar-color: var(--surface-3) var(--sunken);
}

.consent-scroll:focus-visible {
	outline: 2px solid var(--primary);
	outline-offset: 2px;
}

/* Always show the scrollbar rather than the overlay style, so it's obvious the
   text continues past the fold. */
.consent-scroll::-webkit-scrollbar {
	width: 0.7rem;
}

.consent-scroll::-webkit-scrollbar-track {
	background: var(--sunken);
	border-radius: var(--radius);
}

.consent-scroll::-webkit-scrollbar-thumb {
	background: var(--surface-3);
	border: 2px solid var(--sunken);
	border-radius: 999px;
}

.consent-scroll::-webkit-scrollbar-thumb:hover {
	background: var(--line);
}

/* The agreements are plain ASCII wrapped to a fixed column, so they are
   rendered in a monospace face at that width: the file's own line breaks are
   the layout. `pre-wrap` only kicks in on a viewport too narrow for the
   column. */
.consent-text {
	margin: 0;
	font-family: ui-monospace, "SFMono-Regular", "Cascadia Mono", "Menlo", "Consolas",
		"Liberation Mono", monospace;
	font-size: 0.82rem;
	line-height: 1.55;
	color: var(--text);
	white-space: pre-wrap;
	/* `anywhere` also participates in intrinsic sizing; `break-word` only
	   changes final line layout and still lets the <pre> widen its grid item. */
	overflow-wrap: anywhere;
	tab-size: 4;
}

/* The documents are read first; their decisions then form one prominent,
   keyboard-friendly step instead of being split between two scroll boxes. */
.consent-agreements {
	min-inline-size: 0;
	margin: 1.25rem 0 0.6rem;
	padding: 0.8rem;
	border: 1px solid color-mix(in oklab, var(--primary) 58%, var(--line));
	border-radius: var(--radius-lg);
	background:
		linear-gradient(135deg,
			color-mix(in oklab, var(--surface-2) 88%, var(--primary)),
			var(--surface) 72%);
	box-shadow: var(--bevel), 0 8px 22px rgb(0 0 0 / 0.2);
}

.consent-agreements legend {
	padding: 0 0.4rem;
	color: var(--primary-strong);
	font-family: var(--font-display);
	font-size: 0.82rem;
	font-weight: 700;
	letter-spacing: 0.07em;
	text-transform: uppercase;
}

.consent-agreement.checkbox-row {
	align-items: flex-start;
	margin: 0;
	padding: 0.8rem 0.85rem;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: color-mix(in oklab, var(--sunken) 78%, var(--surface-2));
	cursor: pointer;
	transition: border-color 150ms ease, background-color 150ms ease,
		box-shadow 150ms ease;
}

.consent-agreement + .consent-agreement {
	margin-top: 0.65rem;
}

.consent-agreement:hover,
.consent-agreement:focus-within {
	border-color: color-mix(in oklab, var(--primary) 64%, var(--line));
	background: color-mix(in oklab, var(--surface-2) 88%, var(--primary));
}

.consent-agreement:focus-within {
	box-shadow: var(--glow);
}

.consent-agreement input[type="checkbox"] {
	width: 1.4rem;
	height: 1.4rem;
	margin-top: 0.05rem;
	cursor: pointer;
}

.consent-agreement span {
	font-size: 1rem;
	line-height: 1.4;
}

@media (max-width: 34rem) {
	.consent-text {
		font-size: 0.75rem;
	}

	.birthdate-field,
	.consent-agreements {
		padding-inline: 0.75rem;
	}
}

/* A one-time secret the reader has to copy accurately: monospace, generously
   spaced, and selectable as a unit. */
.recovery-code {
	margin: 0.75rem 0 0;
	padding: 0.75rem 1rem;
	background: var(--sunken);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	font-family: ui-monospace, "SFMono-Regular", "Cascadia Mono", "Menlo", "Consolas",
		"Liberation Mono", monospace;
	font-size: 1.05rem;
	letter-spacing: 0.08em;
	overflow-wrap: anywhere;
	user-select: all;
}

.notice-card-strong {
	border-color: color-mix(in oklab, var(--gold) 45%, var(--line));
	box-shadow: var(--bevel), 0 0 0 1px color-mix(in oklab, var(--gold) 22%, transparent);
}

/* Label/value rows for a read-only status summary. */
.status-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.4rem;
}

.status-list li {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 1rem;
	padding-bottom: 0.4rem;
	border-bottom: 1px solid var(--line-soft);
}

.status-list li:last-child {
	border-bottom: none;
	padding-bottom: 0;
}

.status-list span {
	color: var(--muted);
}

.control-group-heading {
	margin: 1.35rem 0 0.25rem;
	font-size: 1rem;
}

.control-toggles {
	display: grid;
	gap: 0.9rem;
	margin: 0.5rem 0 1.1rem;
}

/* The help line belongs to the switch above it, so it indents past the box. */
.control-toggle .field-help {
	margin-left: 1.75rem;
}

/* Reported user content is evidence: quote it verbatim in monospace so a
   moderator sees the exact spacing and characters that were used, including the
   tricks used to slip past filters. */
.report-quote-label {
	margin: 0.9rem 0 0.25rem;
	color: var(--muted);
	font-family: var(--font-display);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.07em;
	text-transform: uppercase;
}

.report-quote {
	margin: 0;
	padding: 0.7rem 0.85rem;
	max-height: 14rem;
	overflow: auto;
	background: var(--sunken);
	border: 1px solid var(--line);
	border-left: 3px solid var(--warn);
	border-radius: var(--radius);
	font-family: ui-monospace, "SFMono-Regular", "Cascadia Mono", "Menlo", "Consolas",
		"Liberation Mono", monospace;
	font-size: 0.85rem;
	line-height: 1.5;
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}
