/*
 * Buttons, surfaces, chips, form fields, and the utility classes, shared by
 * the marketing pages and the dashboard. Utilities load last so they win any
 * specificity tie against the rules above them.
 */

.btn {
	--btn-bg: var(--accent);
	--btn-bg-hover: color-mix(in srgb, var(--accent) 84%, #fff);
	--btn-ink: var(--accent-ink);
	--btn-line: transparent;
	--btn-line-hover: transparent;
	--btn-glow: var(--accent-glow);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-block-size: 40px;
	padding-block: 9px;
	padding-inline: 16px;
	border: 1px solid var(--btn-line);
	border-radius: var(--radius-sm);
	background-color: var(--btn-bg);
	color: var(--btn-ink);
	font: inherit;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	transition-property: background-color, border-color, color, box-shadow, transform;
	transition-duration: var(--dur);
	transition-timing-function: var(--ease-out);
}

.btn:not(:disabled, [aria-disabled="true"]):hover {
	background-color: var(--btn-bg-hover);
	border-color: var(--btn-line-hover);
	box-shadow: 0 6px 18px var(--btn-glow);
	transform: translateY(-1px);
}

.btn:not(:disabled, [aria-disabled="true"]):active {
	background-color: var(--btn-bg);
	box-shadow: none;
	transform: translateY(0);
	transition-duration: 40ms;
}

.btn:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

.btn:disabled,
.btn[aria-disabled="true"] {
	opacity: 0.5;
	cursor: not-allowed;
}

.btn-lg { min-block-size: 50px; padding-inline: 24px; font-size: 15px; }
.btn-sm { min-block-size: 32px; padding-block: 6px; padding-inline: 12px; font-size: 13px; }

.btn-ghost {
	--btn-bg: transparent;
	--btn-bg-hover: var(--panel-hover);
	--btn-ink: var(--text-dim);
	--btn-line: var(--line-strong);
	--btn-line-hover: var(--text-faint);
	--btn-glow: transparent;
}

.btn-ghost:not(:disabled, [aria-disabled="true"]):hover { color: var(--text); }

.btn-quiet {
	--btn-bg: var(--panel-hover);
	--btn-bg-hover: color-mix(in srgb, var(--panel-hover) 88%, var(--text));
	--btn-ink: var(--text);
	--btn-line: var(--line-strong);
	--btn-line-hover: var(--text-faint);
	--btn-glow: transparent;
}

/* Sets its own ink instead of --accent-ink, which is derived from a tenant's
   chosen accent color and says nothing about whether it reads on this red. */
.btn-danger {
	--btn-bg: var(--bad-strong);
	--btn-bg-hover: color-mix(in srgb, var(--bad-strong) 85%, #000);
	--btn-ink: #fff;
	--btn-glow: color-mix(in srgb, var(--bad) 30%, transparent);
}

/* Discord's own blurple rather than the tenant accent: this button hands the
   visitor to Discord. White on it is 4.61:1. */
.btn-discord {
	--btn-bg: #5865f2;
	--btn-bg-hover: #4752c4;
	--btn-ink: #fff;
	--btn-glow: rgb(88 101 242 / 0.35);
}

.btn-discord::before {
	content: "";
	width: 18px;
	height: 18px;
	flex: none;
	background: currentColor;
	-webkit-mask: var(--discord-mask) center / contain no-repeat;
	mask: var(--discord-mask) center / contain no-repeat;
}

:root {
	--discord-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 127 96'><path d='M107 8A105 105 0 0 0 81 0l-3 7a97 97 0 0 0-29 0l-4-7a105 105 0 0 0-26 8C2 33-1 57 1 81a106 106 0 0 0 32 16l6-11a69 69 0 0 1-11-5l3-2a75 75 0 0 0 64 0l3 2a68 68 0 0 1-11 5l6 11a106 106 0 0 0 32-16c3-28-2-52-18-73ZM42 66c-6 0-12-6-12-13s5-13 12-13 12 6 12 13-5 13-12 13Zm43 0c-7 0-12-6-12-13s5-13 12-13 12 6 12 13-5 13-12 13Z'/></svg>");
}

.card {
	background-color: var(--panel);
	background-image: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	padding: 22px;
}

.card.is-warn { border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.card.is-danger { border-color: color-mix(in srgb, var(--bad) 50%, transparent); }
.card.is-good { border-color: color-mix(in srgb, var(--good) 45%, transparent); }
.card.is-accent { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }

.card-hover {
	transition-property: border-color, background-color, box-shadow, transform;
	transition-duration: var(--dur);
	transition-timing-function: var(--ease-out);
}

.card-hover:hover {
	border-color: var(--line-strong);
	background-color: var(--panel-hover);
	box-shadow: var(--shadow);
	transform: translateY(-2px);
}

.card-feature {
	position: relative;
	overflow: hidden;
}

.card-feature::before {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	block-size: 1px;
	background: linear-gradient(90deg, transparent, var(--accent-glow), transparent);
	opacity: 0;
	transition: opacity var(--dur) var(--ease-out);
}

.card-feature:hover::before { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
	.btn,
	.card-hover { transform: none !important; }
}

.panel {
	background-color: var(--bg-raised);
	background-image: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--radius-lg);
	overflow: hidden;
}

.chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding-block: 3px;
	padding-inline: 10px;
	border: 1px solid var(--line-strong);
	border-radius: 999px;
	background-color: var(--bg-raised);
	color: var(--text-dim);
	font-size: 12px;
	font-weight: 600;
	line-height: 1.5;
	white-space: nowrap;
}

.chip-accent {
	border-color: color-mix(in srgb, var(--accent) 30%, transparent);
	background-color: var(--accent-soft);
	color: color-mix(in srgb, var(--accent) 55%, var(--text));
}

.chip-premium {
	border-color: color-mix(in srgb, var(--premium) 35%, transparent);
	background-color: color-mix(in srgb, var(--premium) 12%, transparent);
	color: var(--premium);
}

.chip-good {
	border-color: color-mix(in srgb, var(--good) 35%, transparent);
	background-color: color-mix(in srgb, var(--good) 14%, transparent);
	color: color-mix(in srgb, var(--good) 60%, var(--text));
}

.chip-bad {
	border-color: color-mix(in srgb, var(--bad) 35%, transparent);
	background-color: color-mix(in srgb, var(--bad) 14%, transparent);
	color: color-mix(in srgb, var(--bad) 60%, var(--text));
}

.dot {
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background-color: var(--text-faint);
	flex: none;
}

.dot-good { background-color: var(--good); box-shadow: 0 0 0 3px color-mix(in srgb, var(--good) 20%, transparent); }

label.field {
	display: grid;
	gap: 6px;
	font-size: 13px;
	font-weight: 600;
	color: var(--text-dim);
}

input[type="text"],
input[type="url"],
input[type="number"],
input[type="password"],
input[type="search"],
input[type="color"],
select,
textarea {
	inline-size: 100%;
	min-block-size: 40px;
	padding-block: 9px;
	padding-inline: 12px;
	background-color: var(--panel-hover);
	border: 1px solid var(--line-strong);
	border-radius: var(--radius-sm);
	color: var(--text);
	font: inherit;
	font-size: 14px;
	font-weight: 400;
	line-height: 1.4;
	transition-property: border-color, box-shadow, background-color;
	transition-duration: var(--dur);
	transition-timing-function: var(--ease-out);
}

:where(input, select, textarea):where(:not(:disabled, :focus)):hover { border-color: var(--text-faint); }

input:focus,
select:focus,
textarea:focus {
	outline: none;
	border-color: var(--accent);
	box-shadow: 0 0 0 3px var(--accent-soft);
}

input::placeholder,
textarea::placeholder { color: var(--text-faint); }

:is(input, select, textarea)[aria-invalid="true"] { border-color: var(--bad); }

:is(input, select, textarea)[aria-invalid="true"]:focus {
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--bad) 24%, transparent);
}

input[type="color"] {
	padding: 4px;
	block-size: 40px;
	cursor: pointer;
}

input[type="file"] {
	font-size: 13px;
	color: var(--text-dim);
}

/* The native picker button takes no colour from the rules around it, so on a
   dark page it lands as a light OS control unless it is drawn here. */
input[type="file"]::file-selector-button {
	margin-inline-end: 10px;
	padding-block: 7px;
	padding-inline: 12px;
	border: 1px solid var(--line-strong);
	border-radius: var(--radius-sm);
	background-color: var(--panel-hover);
	color: var(--text);
	font: inherit;
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
	transition-property: background-color, border-color;
	transition-duration: var(--dur);
	transition-timing-function: var(--ease-out);
}

input[type="file"]::file-selector-button:hover {
	border-color: var(--text-faint);
	background-color: color-mix(in srgb, var(--panel-hover) 88%, var(--text));
}

input[type="file"]:disabled::file-selector-button { cursor: not-allowed; }

/* The arrow is drawn, not native, so it takes the text color on every OS. */
select:not([multiple]) {
	appearance: none;
	padding-inline-end: 34px;
	background-image:
		linear-gradient(45deg, transparent 50%, var(--text-dim) 50%),
		linear-gradient(135deg, var(--text-dim) 50%, transparent 50%);
	background-position: calc(100% - 19px) 50%, calc(100% - 14px) 50%;
	background-size: 5px 5px;
	background-repeat: no-repeat;
}

select:not([multiple]):dir(rtl) { background-position: 14px 50%, 19px 50%; }

select option { background-color: var(--panel); color: var(--text); }

textarea {
	resize: vertical;
	min-block-size: 90px;
	line-height: 1.55;
}

input[type="checkbox"],
input[type="radio"] {
	inline-size: 16px;
	block-size: 16px;
	margin: 0;
	flex: none;
	accent-color: var(--accent);
	cursor: pointer;
}

input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

input:disabled,
select:disabled,
textarea:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

.hint {
	font-size: 12px;
	color: var(--text-faint);
	font-weight: 450;
	line-height: 1.5;
}

.switch {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 10px;
	cursor: pointer;
	user-select: none;
}

.switch input { position: absolute; opacity: 0; pointer-events: none; }

.switch .track {
	position: relative;
	flex: none;
	inline-size: 38px;
	block-size: 22px;
	border-radius: 999px;
	background-color: var(--line-strong);
	transition-property: background-color, opacity;
	transition-duration: var(--dur);
	transition-timing-function: var(--ease-out);
}

.switch .track::after {
	content: "";
	position: absolute;
	inset-block-start: 3px;
	inset-inline-start: 3px;
	inline-size: 16px;
	block-size: 16px;
	border-radius: 50%;
	background-color: var(--text-dim);
	box-shadow: 0 1px 3px rgb(0 0 0 / 0.35);
	transition-property: translate, background-color;
	transition-duration: var(--dur);
	transition-timing-function: var(--ease-out);
}

.switch:hover input:not(:disabled, :checked) + .track {
	background-color: color-mix(in srgb, var(--line-strong) 70%, var(--text-faint));
}

.switch input:checked + .track { background-color: var(--accent); }
.switch input:checked + .track::after { translate: 16px 0; background-color: var(--text); }
.switch:dir(rtl) input:checked + .track::after { translate: -16px 0; }

.switch input:focus-visible + .track {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

.switch:has(input:disabled) { cursor: not-allowed; }
.switch input:disabled + .track { opacity: 0.45; }
.switch input:disabled ~ :not(.track) { color: var(--text-faint); }

.sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.skip-link {
	position: absolute;
	inset-inline-start: -9999px;
	inset-block-start: 8px;
	z-index: 100;
	background-color: var(--accent);
	color: var(--accent-ink);
	padding-block: 10px;
	padding-inline: 16px;
	border-radius: var(--radius-sm);
	font-size: 14px;
	font-weight: 600;
}

.skip-link:focus { inset-inline-start: 16px; }

.spinner {
	width: 16px;
	height: 16px;
	border: 2px solid var(--line-strong);
	border-block-start-color: var(--accent);
	border-radius: 50%;
	animation: spin 0.7s linear infinite;
	flex: none;
}

@keyframes spin { to { transform: rotate(360deg); } }

.fade-in { animation: fade-in 0.35s ease both; }

@keyframes fade-in {
	from { opacity: 0; transform: translateY(6px); }
	to { opacity: 1; transform: none; }
}

kbd {
	display: inline-block;
	padding-inline: 6px;
	border: 1px solid var(--line-strong);
	border-block-end-width: 2px;
	border-radius: 6px;
	background-color: var(--bg-raised);
	color: var(--text-dim);
	font-size: 11.5px;
	font-weight: 600;
	line-height: 1.6;
	white-space: nowrap;
}

:where(.card) table {
	inline-size: 100%;
	border-collapse: collapse;
	font-size: 13.5px;
	font-variant-numeric: tabular-nums;
}

:where(.card) :is(th, td) {
	padding-block: 9px;
	padding-inline: 8px;
	border-block-end: 1px solid var(--hairline);
	text-align: start;
}

:where(.card) thead th {
	font-size: 11.5px;
	font-weight: 650;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-faint);
	border-block-end-color: var(--line);
}

:where(.card) tbody tr:hover { background-color: var(--panel-hover); }

.toast-host {
	position: fixed;
	inset-block-end: 20px;
	inset-inline-end: 20px;
	z-index: 200;
	display: grid;
	gap: 8px;
	max-inline-size: min(380px, calc(100vw - 40px));
}

.toast {
	padding-block: 12px;
	padding-inline: 16px;
	border-inline-start: 3px solid var(--accent);
	box-shadow: var(--shadow-lg);
	font-size: 13.5px;
}

.toast-good { border-inline-start-color: var(--good); }
.toast-warn { border-inline-start-color: var(--warn); }
.toast-bad { border-inline-start-color: var(--bad); }

.modal-backdrop {
	position: fixed;
	inset: 0;
	z-index: 300;
	display: grid;
	place-items: center;
	padding: 20px;
	background-color: rgb(6 10 16 / 0.6);
	backdrop-filter: blur(2px);
}

.modal {
	inline-size: 100%;
	max-inline-size: 440px;
	border-color: var(--line-strong);
	box-shadow: var(--shadow-lg);
}

.empty-state {
	padding-block: 48px;
	padding-inline: 24px;
	text-align: center;
}

/* The account menu doubles as mobile nav, so the header needs no separate
   small-screen layout. */
.menu { position: relative; }

.avatar-button {
	display: block;
	padding: 0;
	border: 1px solid var(--line-strong);
	border-radius: 50%;
	background: none;
	cursor: pointer;
	line-height: 0;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.avatar-button img { width: 30px; height: 30px; border-radius: 50%; display: block; }
.avatar-button:hover { border-color: var(--accent); }
.menu.open .avatar-button { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

.menu-pop {
	position: absolute;
	inset-block-start: calc(100% + 10px);
	inset-inline-end: 0;
	min-inline-size: 224px;
	padding: 8px;
	border: 1px solid var(--line-strong);
	border-radius: var(--radius);
	background-color: var(--panel);
	background-image: var(--surface);
	box-shadow: var(--shadow-lg);
	z-index: 60;
	/* Not display:none, so it can animate and a screen reader still finds
	   nothing focusable while it is shut. */
	opacity: 0;
	visibility: hidden;
	transform: translateY(-4px);
	/* visibility flips instantly on open but is delayed on close, so the fade
	   has time to run even on a tab the browser is throttling. */
	transition: opacity 0.14s ease, transform 0.14s ease, visibility 0s linear 0.14s;
}

.menu.open .menu-pop {
	opacity: 1;
	visibility: visible;
	transform: none;
	transition: opacity 0.14s ease, transform 0.14s ease, visibility 0s;
}

.menu-head {
	padding-block: 6px 10px;
	padding-inline: 10px;
	border-block-end: 1px solid var(--hairline);
	margin-block-end: 6px;
}

.menu-pop a {
	display: block;
	padding-block: 8px;
	padding-inline: 10px;
	border-radius: var(--radius-sm);
	font-size: 13.5px;
	color: var(--text-dim);
	text-decoration: none;
}

.menu-pop a:hover { background-color: var(--panel-hover); color: var(--text); }
.menu-pop a:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.menu-sep { border: 0; border-block-start: 1px solid var(--hairline); margin-block: 6px; }

/* The way into the settings search from the top bar, mirroring the shortcut it
   announces; the palette itself is built in src/ui/settingsSearch.js. */
.search-btn {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-block-size: 34px;
	padding-block: 0;
	padding-inline: 10px;
	border: 1px solid var(--line-strong);
	border-radius: var(--radius-sm);
	background-color: var(--panel);
	color: var(--text-dim);
	font: inherit;
	font-size: 13px;
	cursor: pointer;
	transition-property: color, border-color, background-color;
	transition-duration: var(--dur);
	transition-timing-function: var(--ease-out);
}

.search-btn:hover {
	color: var(--text);
	border-color: var(--accent-glow);
	background-color: var(--panel-hover);
}

.search-btn .icon { flex: none; }
.search-btn kbd { margin-inline-start: 14px; }
.search-btn-label { white-space: nowrap; }

@media (max-width: 819.98px) {
	.search-btn-label,
	.search-btn kbd { display: none; }
	.search-btn { padding-inline: 8px; }
}

.search-scrim {
	position: fixed;
	inset: 0;
	z-index: 300;
	display: grid;
	place-items: start center;
	padding-block-start: 12vh;
	padding-inline: 20px;
	background-color: rgb(6 10 16 / 0.6);
	backdrop-filter: blur(2px);
}

.search-panel {
	inline-size: 100%;
	max-inline-size: 620px;
	max-block-size: 70vh;
	display: flex;
	flex-direction: column;
	border: 1px solid var(--line-strong);
	border-radius: var(--radius-lg);
	background-color: var(--bg-raised);
	background-image: var(--surface);
	box-shadow: var(--shadow-lg);
	overflow: hidden;
}

.search-field {
	display: flex;
	align-items: center;
	gap: 10px;
	padding-block: 14px;
	padding-inline: 16px;
	border-block-end: 1px solid var(--hairline);
	color: var(--text-faint);
}

/* Qualified by the element: the shared input[type="text"] rules outrank a bare
   class, and this field is a bare line inside the palette, not a form control. */
input.search-input {
	flex: 1;
	min-inline-size: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	color: var(--text);
	font: inherit;
	font-size: 15px;
}

/* The open palette is the focus; a ring inside its own field reads as a second
   frame around a box that is already the only thing on screen. */
input.search-input:focus,
input.search-input:focus-visible {
	outline: none;
	box-shadow: none;
	border-color: transparent;
}

.search-results {
	display: grid;
	gap: 2px;
	padding: 6px;
	overflow: auto;
	overscroll-behavior: contain;
}

.search-row {
	display: flex;
	align-items: center;
	gap: 10px;
	inline-size: 100%;
	padding-block: 9px;
	padding-inline: 10px;
	border: 0;
	border-radius: var(--radius-sm);
	background: none;
	color: var(--text-dim);
	font: inherit;
	text-align: start;
	cursor: pointer;
}

.search-row:hover,
.search-row.is-active { background-color: var(--accent-soft); color: var(--text); }
.search-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.search-row .icon { flex: none; opacity: 0.75; }
.search-row-gem { color: var(--premium); flex: none; opacity: 1; }
.search-row-text { flex: 1; min-inline-size: 0; display: grid; }

.search-row-title {
	font-size: 13.5px;
	font-weight: 560;
	color: var(--text);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.search-row-path {
	font-size: 11.5px;
	color: var(--text-faint);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.search-empty {
	padding-block: 30px;
	padding-inline: 16px;
	text-align: center;
	color: var(--text-faint);
	font-size: 13.5px;
}

.search-foot {
	display: flex;
	align-items: center;
	gap: 14px;
	padding-block: 9px;
	padding-inline: 14px;
	border-block-start: 1px solid var(--hairline);
	font-size: 11.5px;
	color: var(--text-faint);
}

.search-foot kbd { margin-inline-end: 5px; }

@media (max-width: 620px) {
	.search-scrim { padding: 0; place-items: stretch; }
	.search-panel { max-block-size: none; border: 0; border-radius: 0; }
}

/* The settings rail: the server's identity, its plan, and the nine areas,
   beside the nav that is already scoped to that server. */

/* The small-screen form: a card in normal flow, hidden until the toggle
   above it opens it. The min-width: 901px block below adds the fixed
   desktop dock on top of it. A fixed rail a narrow viewport can't afford
   covers the content instead of sitting beside it, so in-flow is the
   default and the dock is only added where there is room. */
.settings-layout { display: block; }

.rail {
	display: grid;
	gap: 6px;
	padding: 10px;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background-color: var(--panel);
	background-image: var(--surface);
	overscroll-behavior: contain;
	scrollbar-width: thin;
}

.rail-top {
	display: flex;
	align-items: center;
	gap: 8px;
	padding-block: 2px 10px;
	padding-inline: 2px;
	border-block-end: 1px solid var(--hairline);
}

.rail-server {
	display: flex;
	align-items: center;
	gap: 10px;
	min-width: 0;
	flex: 1;
	padding-block: 4px;
	padding-inline: 6px;
	border-radius: var(--radius-sm);
	transition: background-color var(--dur) var(--ease-out);
}

.rail-server:hover { background-color: var(--panel-hover); }
.rail-server:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.rail-server-text { display: grid; min-width: 0; }

.rail-server-name {
	font-size: 13.5px;
	font-weight: 640;
	line-height: 1.3;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.rail-server-sub {
	font-size: 11.5px;
	line-height: 1.4;
	color: var(--text-faint);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.rail-collapse {
	display: grid;
	place-items: center;
	width: 26px;
	height: 26px;
	flex: none;
	padding: 0;
	border: 1px solid var(--line);
	border-radius: var(--radius-sm);
	background-color: var(--panel-hover);
	color: var(--text-dim);
	cursor: pointer;
	transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}

.rail-collapse:hover { color: var(--text); border-color: var(--line-strong); }
.rail-collapse:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Gold in both states, the way the plan row reads on Ticket Tool: the fill says
   "this is the paid thing", the chip says whether you have it. */
.rail-plan {
	position: relative;
	overflow: hidden;
	display: flex;
	align-items: center;
	gap: 9px;
	margin-block: 6px 4px;
	padding-block: 9px;
	padding-inline: 11px;
	border: 1px solid transparent;
	border-radius: var(--radius-sm);
	background-image: var(--premium-ramp);
	color: color-mix(in srgb, var(--premium) 22%, #000);
	font-size: 12.5px;
	font-weight: 650;
	box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.42), var(--shadow);
	transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}

.rail-plan-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.rail-plan-value {
	flex: none;
	padding-block: 2px;
	padding-inline: 8px;
	border-radius: 999px;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.01em;
}

.rail-plan-free .rail-plan-value { background-color: rgb(0 0 0 / 0.16); }

.rail-plan-paid .rail-plan-value {
	background-color: color-mix(in srgb, var(--good) 82%, #000);
	color: color-mix(in srgb, var(--good) 16%, #fff);
}

a.rail-plan:hover {
	transform: translateY(-1px);
	box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.5), var(--shadow-lg);
}

a.rail-plan:active { transform: translateY(1px); }
a.rail-plan:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.rail-plan::after {
	content: "";
	position: absolute;
	inset-block: 0;
	inset-inline-start: -55%;
	inline-size: 38%;
	background-image: linear-gradient(105deg, transparent, rgb(255 255 255 / 0.5), transparent);
	pointer-events: none;
	opacity: 0;
}

a.rail-plan:hover::after { animation: rail-sweep 1.1s cubic-bezier(0.22, 0.61, 0.36, 1) 1; }

@keyframes rail-sweep {
	from { opacity: 1; transform: translateX(0); }
	to { opacity: 1; transform: translateX(560%); }
}

.rail-nav { display: grid; gap: 6px; }

/* Each row is its own framed object rather than a flat list item, which is what
   makes the rail read as Ticket Tool's rather than a generic sidebar. */
.rail-item {
	display: flex;
	align-items: center;
	gap: 10px;
	padding-block: 8px;
	padding-inline: 10px;
	border: 1px solid var(--line);
	border-radius: var(--radius-sm);
	background-color: var(--panel);
	font-size: 13.5px;
	font-weight: 500;
	color: var(--text-dim);
	transition-property: background-color, color, border-color;
	transition-duration: var(--dur);
	transition-timing-function: var(--ease-out);
}

.rail-item:hover { background-color: var(--panel-hover); border-color: var(--line-strong); color: var(--text); }
.rail-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.rail-item.is-active {
	background-color: var(--accent-soft);
	border-color: color-mix(in srgb, var(--accent) 34%, transparent);
	color: var(--text);
	font-weight: 620;
	box-shadow: inset 2px 0 0 var(--accent);
}

.rail-item .icon { flex: none; opacity: 0.8; }
.rail-item:hover .icon { opacity: 1; }
.rail-item.is-active .icon { color: var(--accent); opacity: 1; }

.rail-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.rail-badge {
	inline-size: 6px;
	block-size: 6px;
	flex: none;
	background-color: var(--premium);
	box-shadow: none;
}

.tab-badge {
	inline-size: 5px;
	block-size: 5px;
	margin-inline-start: 7px;
	background-color: var(--premium);
	box-shadow: none;
}

/* Stands in for the whole rail on a phone: names the current server and
   opens the menu, since the rail itself is off-canvas there. */
.rail-toggle {
	display: none;
	align-items: center;
	gap: 10px;
	width: 100%;
	margin-block-end: 14px;
	padding-block: 9px;
	padding-inline: 12px;
	border: 1px solid var(--line);
	border-radius: var(--radius-sm);
	background-color: var(--panel);
	background-image: var(--surface);
	color: var(--text);
	font: inherit;
	font-size: 13.5px;
	font-weight: 600;
	text-align: start;
	cursor: pointer;
}

.rail-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rail-toggle[aria-expanded="true"] { border-color: var(--accent-glow); }
.rail-toggle .hamburger { margin-inline-start: auto; color: var(--text-dim); }
.rail-toggle-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.hamburger { display: inline-grid; gap: 3px; width: 14px; flex: none; }
.hamburger i { display: block; height: 2px; border-radius: 2px; background: currentColor; }

/* dash-has-rail is set on <body> by the router rather than on an element
   inside the view, because the site header also has to make room for the
   fixed rail and a class inside <main> can never reach it. */
@media (min-width: 901px) {
	body.dash-has-rail { --rail-w: 244px; }
	body.dash-has-rail.dash-rail-collapsed { --rail-w: 68px; }

	/* Fixed to the viewport's edge, not the centred wrap, so there is no
	   containing block for it to scroll away from. */
	.dash-has-rail .settings-nav {
		position: fixed;
		inset-block: 0;
		inset-inline-start: 0;
		inline-size: var(--rail-w);
		z-index: 55;
		display: block;
	}

	/* Only while the collapse button is working. Left on permanently, the same
	   transition plays on first paint, sliding the whole page in from the edge
	   because the rail's width is undefined until the router sets it. */
	.dash-rail-animating .settings-nav { transition: inline-size var(--dur) var(--ease-out); }

	.dash-rail-animating .site-header,
	.dash-rail-animating main { transition: padding-inline-start var(--dur) var(--ease-out); }

	.dash-has-rail .rail {
		height: 100%;
		padding-block: 0 10px;
		padding-inline: 10px;
		border: 0;
		border-inline-end: 1px solid var(--line);
		border-radius: 0;
		background-color: var(--bg-raised);
		background-image: none;
		/* Hidden across the axis that animates: a label mid-collapse would raise a
		   scrollbar for the fraction of a second it does not fit. */
		overflow: hidden auto;
		/* Rows keep their natural height rather than stretching to fill it,
		   which is what a grid does by default. */
		align-content: start;
	}

	/* Height matches the site header so the two border lines read as one;
	   the negative margin makes it full-bleed and the padding restores
	   alignment with the nav rows below. */
	.dash-has-rail .rail-top {
		height: var(--header-height);
		box-sizing: border-box;
		margin-block: 0;
		margin-inline: -10px;
		padding-block: 0;
		padding-inline: 20px;
	}

	.dash-has-rail .site-header,
	.dash-has-rail main { padding-inline-start: var(--rail-w); }

	/* Chrome spans full width; .wrap keeps its own reading-width cap. */
	.dash-has-rail .site-header .wrap { max-width: none; }

	.dash-rail-collapsed .rail { padding-block: 0 10px; padding-inline: 8px; }

	/* Still exactly one header tall, stacked instead of inline; avatar and
	   chevron are sized down so both rows fit in that height. */
	.dash-rail-collapsed .rail-top {
		flex-direction: column;
		justify-content: center;
		gap: 4px;
		height: var(--header-height);
		margin-block: 0;
		margin-inline: -8px;
		padding: 0;
	}
	.dash-rail-collapsed .rail-collapse { width: 22px; height: 22px; }
	.dash-rail-collapsed .rail-server { flex: none; justify-content: center; padding: 4px; }
	.dash-rail-collapsed .rail-item,
	.dash-rail-collapsed .rail-plan { justify-content: center; padding-inline: 0; }
	.dash-rail-collapsed .rail-item.is-active { box-shadow: none; }

	.dash-rail-collapsed .rail-server-text,
	.dash-rail-collapsed .rail-label,
	.dash-rail-collapsed .rail-plan-label,
	.dash-rail-collapsed .rail-plan-value,
	.dash-rail-collapsed .rail-badge { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	.dash-rail-animating .settings-nav,
	.dash-rail-animating .site-header,
	.dash-rail-animating main { transition: none; }
	a.rail-plan:hover { transform: none; }
	a.rail-plan:hover::after { animation: none; }
}

.profile-card { display: grid; gap: 14px; }
.profile-heading { font-size: 15px; }

/* Capped near Discord's own render width, so the preview is close to what
   the artwork actually has to survive. */
.profile-preview {
	max-width: 620px;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--bg-raised);
	overflow: hidden;
}

.profile-banner {
	position: relative;
	/* Discord's own banner ratio, so the preview is the right shape at any
	   card width. */
	aspect-ratio: 680 / 240;
	/* Flat, not a gradient: a gradient read as leftover placeholder content
	   rather than an empty state. */
	background: var(--panel);
	display: grid;
	place-items: center;
	cursor: pointer;
}

.profile-banner:hover { filter: brightness(1.08); }
.profile-banner:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Absolutely positioned so it can't contribute height: an in-flow img at
   height:100% inside an auto-height parent falls back to its own intrinsic
   ratio instead, which let a square upload override aspect-ratio and square
   off the banner. */
.profile-banner-img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.profile-drop-hint {
	font-size: 13px;
	font-weight: 560;
	color: var(--text-dim);
	pointer-events: none;
}

/* Full strength, never dimmed: this is exactly what Discord will show, so
   dimming it would misrepresent it. The ring marks it as inherited. */
.profile-avatar.is-inherited { box-shadow: 0 0 0 6px var(--bg-raised), 0 0 0 7px var(--line-strong); }

/* Overlaps the banner's lower edge, the detail that reads as a Discord
   profile rather than a photo above a form. */
.profile-avatar-slot { margin-top: -46px; }

.profile-avatar {
	position: relative;
	width: 80px;
	height: 80px;
	border-radius: 50%;
	background: var(--panel);
	/* The ring is the page behind it, the way Discord punches the avatar
	   out of the banner rather than drawing a border on top. */
	box-shadow: 0 0 0 6px var(--bg-raised);
	display: grid;
	place-items: center;
	overflow: hidden;
	cursor: pointer;
}

.profile-avatar:hover { filter: brightness(1.1); }
.profile-avatar:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.profile-avatar-img { width: 100%; height: 100%; object-fit: cover; display: block; }

.profile-avatar-empty {
	font-size: 26px;
	line-height: 1;
	color: var(--text-faint);
	pointer-events: none;
}

.profile-clear {
	position: absolute;
	top: 6px;
	right: 6px;
	width: 22px;
	height: 22px;
	display: grid;
	place-items: center;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: rgba(8, 9, 13, 0.72);
	color: var(--text);
	font-size: 12px;
	line-height: 1;
	cursor: pointer;
	opacity: 0;
	transition: opacity 0.15s, background 0.15s;
}

.profile-banner:hover .profile-clear,
.profile-avatar:hover .profile-clear,
.profile-clear:focus-visible { opacity: 1; }
.profile-clear:hover { background: var(--bad); }

.profile-avatar .profile-clear { top: 2px; right: 2px; width: 20px; height: 20px; }

.profile-body { padding: 0 20px 18px; display: grid; gap: 10px; }

/* Borderless until touched, so it reads as the profile's name rather than
   a form field sitting inside a preview. */
.profile-name-input {
	width: 100%;
	padding-block: 4px;
	padding-inline: 8px;
	margin-inline-start: -8px;
	border: 1px solid transparent;
	border-radius: var(--radius-sm);
	background: transparent;
	font-size: 19px;
	font-weight: 640;
	letter-spacing: -0.02em;
}

.profile-name-input:hover:not(:disabled) { border-color: var(--line); background: var(--bg); }
.profile-name-input:focus { border-color: var(--accent); background: var(--bg); }

.profile-about { display: grid; gap: 8px; }

.profile-about-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	padding-bottom: 6px;
	border-bottom: 1px solid var(--line);
}

.profile-about-label {
	font-size: 11px;
	font-weight: 650;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: var(--text-faint);
}

.profile-counter { font-size: 11.5px; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.profile-counter.is-full { color: var(--warn); }

.profile-bio { min-height: 104px; font-size: 13.5px; }
.profile-note { margin: 0; }

.image-field { display: flex; gap: 14px; align-items: flex-start; }
.image-field > .stack { justify-items: start; }

.image-preview {
	width: 64px;
	height: 64px;
	border-radius: 12px;
	object-fit: cover;
	background: var(--bg);
	border: 1px solid var(--line);
	flex: none;
}

.image-field input[type="file"] { font-size: 12.5px; color: var(--text-dim); }

/* Deliberately not a .card: an upsell that looks identical to the settings
   around it reads as another form you failed to fill in, not an offer. */
.notice {
	display: flex;
	align-items: center;
	gap: 10px;
	padding-block: 10px;
	padding-inline: 14px;
	border: 1px solid var(--line);
	border-radius: var(--radius-sm);
	background-color: var(--panel);
	font-size: 13px;
}

.notice-text { flex: 1; min-inline-size: 0; }
.notice .btn { flex: none; }

.notice-premium {
	border-color: color-mix(in srgb, var(--premium) 32%, transparent);
	background-color: color-mix(in srgb, var(--premium) 8%, transparent);
	color: var(--premium);
}

.notice-premium .notice-text { color: var(--text-dim); }

/* Fixed dark ink: --accent-ink follows the tenant's accent, not this gold. */
.notice-premium .btn {
	--btn-bg: var(--premium);
	--btn-bg-hover: color-mix(in srgb, var(--premium) 85%, #fff);
	--btn-ink: #241a00;
	--btn-glow: color-mix(in srgb, var(--premium) 30%, transparent);
	background-image: var(--premium-ramp);
}

/* An accent edge, not a filled gradient, so this doesn't compete with the
   lock notice above it. */
.upsell {
	display: grid;
	gap: 12px;
	justify-items: start;
	padding: 20px;
	border-radius: var(--radius);
	border: 1px solid var(--line);
	border-inline-start: 3px solid var(--premium);
	background-color: var(--panel);
	background-image: var(--surface);
}

.upsell h3 { font-size: 16px; }

@media (max-width: 900px) {
	.rail-toggle { display: flex; }
	.rail-collapse { display: none; }

	.settings-nav { display: none; margin-block-end: 20px; }
	.settings-nav.open { display: block; }

	/* Opened from a button directly above it, so it enters from that edge rather
	   than fading in place, which looks like a redraw on a phone. */
	.settings-nav.open .rail { animation: rail-drop var(--dur) var(--ease-out) both; }
	.rail-item { padding-block: 11px; }
	.rail-nav { gap: 8px; }
}

@keyframes rail-drop {
	from { opacity: 0; transform: translateY(-6px); }
	to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
	.settings-nav.open .rail { animation: none; }
}

.tabstrip {
	display: flex;
	gap: 4px;
	margin-block-end: 22px;
	padding-block-end: 2px;
	border-block-end: 1px solid var(--hairline);
	/* Scrolls rather than wraps, so extra tabs on a phone don't push the
	   content off the screen. */
	overflow-x: auto;
	scrollbar-width: none;
}

.tabstrip::-webkit-scrollbar { display: none; }

.tabstrip-tab {
	display: inline-flex;
	align-items: center;
	white-space: nowrap;
	padding-block: 9px;
	padding-inline: 13px;
	font-size: 13.5px;
	font-weight: 500;
	color: var(--text-dim);
	border-start-start-radius: var(--radius-sm);
	border-start-end-radius: var(--radius-sm);
	box-shadow: inset 0 -2px 0 transparent;
	transition: color var(--dur) var(--ease-out), background-color var(--dur) var(--ease-out);
}

.tabstrip-tab:hover { color: var(--text); background-color: var(--panel); }

/* Restated on the tab itself: the strip's own rules win over the global focus
   rule on specificity, so a keyboard user would otherwise see nothing here. */
.tabstrip-tab:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: -2px;
	color: var(--text);
}

.tabstrip-tab.is-active {
	color: var(--text);
	font-weight: 600;
	box-shadow: inset 0 -2px 0 var(--accent);
}

.tabstrip-more {
	display: inline-flex;
	align-items: center;
	white-space: nowrap;
	margin-inline-start: auto;
	padding-block: 9px;
	padding-inline: 13px;
	border: 0;
	border-radius: var(--radius-sm);
	font-size: 13px;
	color: var(--text-dim);
	background: none;
	cursor: pointer;
}

.tabstrip-more:hover { color: var(--text); }
.tabstrip-more:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.tabstrip-advanced {
	flex-wrap: wrap;
	margin-block: 4px 22px;
}

.tabstrip-advanced[hidden] { display: none; }

.tabstrip-wrap {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

/* The same quiet disclosure as the tab strip's "More", one level down: a group
   or a field inside an otherwise-visible group, rather than a whole tab. */
.group-more {
	display: inline-flex;
	align-items: center;
	white-space: nowrap;
	padding-block: 9px;
	padding-inline: 13px;
	border: 0;
	border-radius: var(--radius-sm);
	font-size: 13px;
	color: var(--text-dim);
	background: none;
	cursor: pointer;
}

.group-more:hover { color: var(--text); }
.group-more:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.group-disclosure[hidden] { display: none; }

.screen-head { display: grid; gap: 6px; }

.screen-head-row {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 16px;
}

/* Sized like a section heading, not the global h1 clamp, which tops out at
   3.15rem for a marketing page's one big statement. */
.screen-head h1 { font-size: 21px; margin: 0; line-height: 1.2; }
.screen-head p { margin: 0; max-width: 74ch; }

/* Two up rather than one, so four figures are one glance on a phone instead of
   a screen and a half of scrolling. */
@media (max-width: 620px) {
	.stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.stat-grid .stat-tile-value { font-size: 23px; }
}

.stat-tile { display: grid; gap: 4px; padding-block: 16px; padding-inline: 18px; }
.stat-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.stat-tile-label {
	font-size: 11px;
	font-weight: 650;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--text-faint);
}

.stat-tile-value {
	font-family: var(--font-display);
	font-size: 28px;
	font-weight: 700;
	letter-spacing: -0.02em;
	line-height: 1.1;
	font-variant-numeric: tabular-nums;
}

/* Sits on the bottom edge of the form it saves, so it is in view whenever the
   end of that form is. */
.save-bar {
	position: sticky;
	inset-block-end: 0;
	z-index: 20;
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
	padding-block: 16px;
	background-image: linear-gradient(transparent, var(--bg) 42%);
}

.save-bar.is-rejected { animation: save-shake 0.62s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; }

@keyframes save-shake {
	10%, 90% { transform: translateX(-2px); }
	20%, 80% { transform: translateX(4px); }
	30%, 50%, 70% { transform: translateX(-7px); }
	40%, 60% { transform: translateX(7px); }
}

.onboard-step {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 16px;
	padding-block: 12px;
	border-block-start: 1px solid var(--hairline);
}

.onboard-main { display: flex; align-items: flex-start; gap: 12px; min-inline-size: 0; }

.onboard-check {
	inline-size: 20px;
	block-size: 20px;
	flex: none;
	margin-block-start: 2px;
	display: grid;
	place-items: center;
	border: 2px solid var(--line-strong);
	border-radius: 50%;
	font-size: 11px;
	line-height: 1;
	/* The page colour, not white: a pale --good on a white-label theme would
	   swallow a hardcoded tick. */
	color: var(--bg);
}

.onboard-check.is-done { border-color: transparent; background-color: var(--good); }
.onboard-title { font-size: 13.5px; font-weight: 620; }
.onboard-step.is-done .onboard-title { color: var(--text-dim); }
.onboard-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; flex: none; }

@media (max-width: 620px) {
	.onboard-step { flex-direction: column; gap: 10px; }
	.onboard-actions { justify-content: flex-start; padding-inline-start: 32px; }
}

.loading-row {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 28px;
	color: var(--text-dim);
	font-size: 13.5px;
}

/* Most servers have no Discord banner, since that needs boost level two, so
   this leads with logo and name rather than banner art. */
.server-card {
	display: flex;
	align-items: center;
	gap: 14px;
	padding-block: 14px;
	padding-inline: 19px 16px;
	min-block-size: 74px;
	/* Fills its grid cell, so two cards in a row match even when one wraps. */
	block-size: 100%;
	box-sizing: border-box;
	position: relative;
	overflow: hidden;
	cursor: pointer;
}

.server-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.server-card::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	inset-block: 0;
	inline-size: 3px;
	background-color: var(--line-strong);
}

.server-card.is-live::before { background: var(--good); }

.server-card-text { min-width: 0; flex: 1; display: grid; gap: 3px; }

.server-card-name {
	font-size: 15px;
	font-weight: 620;
	line-height: 1.3;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.server-card-meta {
	display: flex;
	align-items: center;
	gap: 7px;
	flex-wrap: wrap;
	font-size: 12px;
	color: var(--text-faint);
}

.server-card-status { display: inline-flex; align-items: center; gap: 6px; }
.server-card.is-live .server-card-status { color: #6fce8d; }

.server-add {
	justify-content: center;
	color: var(--text-dim);
	border-style: dashed;
}

.server-add::before { display: none; }
