/* WareDesk cabinet — design tokens lifted directly from the Grav site's own Quark2 theme
   (grav/user/themes/quark2/css/theme.css's dark palette, the site's only theme, plus its
   configured accent-color #8428DF from quark2.yaml) so the cabinet reads as the same
   product as the marketing site around it, not a separate light-mode app bolted on. */

:root {
	--bg: #08090b;
	--bg-elev: #1d1f25;
	--bg-muted: #2a2d34;
	--bg-inverse: #f5f5f5;

	--text: #f2f2f3;
	--text-strong: #ffffff;
	--text-muted: #9a9aa0;
	--text-inverse: #111111;

	--border: rgba(255, 255, 255, 0.1);
	--border-strong: rgba(255, 255, 255, 0.2);

	--shadow-card:
		rgba(0, 0, 0, 0.85) 0 1px 5px -4px, rgba(255, 255, 255, 0.14) 0 0 0 1px,
		rgba(0, 0, 0, 0.55) 0 4px 12px 0;
	--shadow-raised:
		rgba(0, 0, 0, 0.85) 0 1px 5px -4px, rgba(255, 255, 255, 0.14) 0 0 0 1px,
		rgba(0, 0, 0, 0.65) 0 14px 32px -8px;

	--radius-sm: 6px;
	--radius: 8px;
	--radius-lg: 16px;
	--radius-pill: 9999px;

	/* Same GitHub-style semantic colors Quark2 uses for its dark-mode markdown alerts. */
	--success: #57ab5a;
	--success-bg: color-mix(in oklab, var(--success) 16%, var(--bg-elev));
	--danger: #e5534b;
	--danger-bg: color-mix(in oklab, var(--danger) 16%, var(--bg-elev));
	--warn: #c69026;
	--warn-bg: color-mix(in oklab, var(--warn) 16%, var(--bg-elev));

	/* Quark2's one deliberate accent, used just as sparingly here (CTA buttons, focus rings,
	   a few glows) — everything else in the palette above stays monochrome, same as there. */
	--accent: color-mix(in oklab, #8428df 80%, white 20%);
	--accent-contrast: #ffffff;
	--accent-soft: color-mix(in oklab, #8428df 16%, var(--bg-elev));
	--focus-ring: color-mix(in oklab, #8428df 45%, transparent);
}

* {
	box-sizing: border-box;
}

html,
body {
	margin: 0;
	padding: 0;
}

html {
	scroll-behavior: smooth;
	color-scheme: dark;
}

body {
	background: var(--bg);
	color: var(--text);
	font-family:
		"Inter",
		-apple-system,
		BlinkMacSystemFont,
		"Segoe UI",
		Roboto,
		sans-serif;
	font-size: 16px;
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
	color: var(--text-strong);
	line-height: 1.2;
	font-weight: 650;
	letter-spacing: -0.02em;
	margin: 0 0 0.5em;
}

h1 {
	font-size: clamp(2.25rem, 4vw, 3.25rem);
}

h2 {
	font-size: clamp(1.5rem, 2.6vw, 2.1rem);
}

p {
	margin: 0 0 1em;
}

a {
	color: inherit;
}

.muted {
	color: var(--text-muted);
}

.container {
	max-width: 1080px;
	margin: 0 auto;
	padding: 0 24px;
}

.container-narrow {
	max-width: 640px;
	margin: 0 auto;
	padding: 0 24px;
}

/* ---------- Nav ---------- */

.nav {
	position: sticky;
	top: 0;
	z-index: 10;
	background: color-mix(in oklab, var(--bg) 85%, transparent);
	backdrop-filter: blur(8px);
	border-bottom: 1px solid transparent;
	transition:
		box-shadow 0.25s ease,
		border-color 0.25s ease;
}

.nav.is-scrolled {
	border-bottom-color: var(--border);
	box-shadow: 0 8px 24px -18px rgba(20, 20, 22, 0.35);
}

.nav-inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	height: 68px;
}

.brand {
	display: flex;
	align-items: center;
	gap: 8px;
	font-weight: 700;
	font-size: 1.05rem;
	color: var(--text-strong);
	text-decoration: none;
}

.brand img {
	width: 28px;
	height: 28px;
	border-radius: 6px;
}

.nav-links {
	display: flex;
	align-items: center;
	gap: 28px;
}

.nav-links a:not(.btn) {
	text-decoration: none;
	color: var(--text-muted);
	font-size: 0.95rem;
}

.nav-links a:not(.btn):hover {
	color: var(--text-strong);
}

.nav-actions {
	display: flex;
	align-items: center;
	gap: 12px;
}

.lang-toggle {
	display: flex;
	background: var(--bg-muted);
	border-radius: var(--radius-pill);
	padding: 3px;
}

.lang-toggle button {
	border: none;
	background: transparent;
	padding: 5px 10px;
	border-radius: var(--radius-pill);
	font-size: 0.78rem;
	font-weight: 700;
	color: var(--text-muted);
	cursor: pointer;
}

.lang-toggle button.active {
	background: var(--bg-elev);
	color: var(--text-strong);
	box-shadow: var(--shadow-card);
}

/* ---------- Buttons ---------- */

.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 10px 18px;
	border-radius: var(--radius-pill);
	font-size: 0.95rem;
	font-weight: 600;
	text-decoration: none;
	border: 1px solid transparent;
	cursor: pointer;
	transition:
		transform 0.05s ease,
		opacity 0.15s ease;
	white-space: nowrap;
}

.btn {
	transition:
		transform 0.2s ease,
		opacity 0.2s ease,
		box-shadow 0.25s ease,
		background 0.2s ease;
}

.btn:active {
	transform: scale(0.98);
}

.btn svg {
	width: 16px;
	height: 16px;
	flex-shrink: 0;
}

.btn-primary {
	position: relative;
	overflow: hidden;
	background: var(--accent);
	color: var(--accent-contrast);
}

.btn-primary::after {
	content: "";
	position: absolute;
	top: 0;
	left: -60%;
	width: 40%;
	height: 100%;
	background: linear-gradient(115deg, transparent, rgba(255, 255, 255, 0.25), transparent);
	transform: skewX(-20deg);
	transition: left 0.6s ease;
}

.btn-primary:hover {
	opacity: 0.92;
	transform: translateY(-2px);
	box-shadow: 0 10px 24px -10px color-mix(in oklab, var(--accent) 60%, black);
}

.btn-primary:hover::after {
	left: 120%;
}

.btn-secondary {
	background: var(--bg-elev);
	color: var(--text-strong);
	border-color: var(--border-strong);
}

.btn-secondary:hover {
	background: var(--bg-muted);
}

.btn-ghost {
	background: transparent;
	color: var(--text-muted);
	border-color: transparent;
}

.btn-ghost:hover {
	color: var(--text-strong);
}

.btn-danger {
	background: var(--danger-bg);
	color: var(--danger);
}

.btn-danger:hover {
	opacity: 0.85;
}

.btn-sm {
	padding: 6px 14px;
	font-size: 0.85rem;
}

.btn:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

/* ---------- Sections ---------- */

section {
	padding: 88px 0;
}

.section-tight {
	padding: 56px 0;
}

.eyebrow {
	display: inline-block;
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-muted);
	margin-bottom: 12px;
}

.eyebrow-dot {
	display: inline-flex;
	align-items: center;
	gap: 8px;
}

.eyebrow-dot::before {
	content: "";
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--accent);
	box-shadow: 0 0 0 0 var(--accent-soft);
	animation: dotPulse 2.4s ease-in-out infinite;
}

@keyframes dotPulse {
	0% {
		box-shadow: 0 0 0 0 var(--accent-soft);
	}
	70% {
		box-shadow: 0 0 0 6px transparent;
	}
	100% {
		box-shadow: 0 0 0 0 transparent;
	}
}

.hero {
	position: relative;
	text-align: center;
	padding: 96px 0 64px;
	overflow: hidden;
}

.hero::before {
	content: "";
	position: absolute;
	inset: -10% -10% auto -10%;
	height: 520px;
	background: radial-gradient(ellipse 60% 100% at 50% 0%, var(--accent-soft), transparent 70%);
	pointer-events: none;
	z-index: -2;
	animation: heroGlow 9s ease-in-out infinite alternate;
}

.hero::after {
	content: "";
	position: absolute;
	inset: 0;
	background-image: radial-gradient(var(--border-strong) 1px, transparent 1px);
	background-size: 28px 28px;
	-webkit-mask-image: radial-gradient(ellipse 55% 65% at 50% 10%, black 40%, transparent 100%);
	mask-image: radial-gradient(ellipse 55% 65% at 50% 10%, black 40%, transparent 100%);
	pointer-events: none;
	z-index: -1;
}

@keyframes heroGlow {
	from {
		opacity: 0.7;
		transform: translateY(0) scale(1);
	}
	to {
		opacity: 1;
		transform: translateY(14px) scale(1.06);
	}
}

.hero .eyebrow {
	animation: fadeInUp 0.7s ease both;
}

.hero h1 {
	animation: fadeInUp 0.7s ease 0.08s both;
}

.hero p {
	animation: fadeInUp 0.7s ease 0.16s both;
}

.hero-actions {
	display: flex;
	justify-content: center;
	gap: 12px;
	margin-top: 32px;
	flex-wrap: wrap;
	animation: fadeInUp 0.7s ease 0.24s both;
}

@keyframes fadeInUp {
	from {
		opacity: 0;
		transform: translateY(18px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

.scroll-hint {
	display: flex;
	justify-content: center;
	margin-top: 56px;
	color: var(--text-muted);
	animation:
		fadeInUp 0.7s ease 0.4s both,
		scrollBounce 2.2s ease-in-out 1.2s infinite;
}

.scroll-hint svg {
	width: 20px;
	height: 20px;
}

@keyframes scrollBounce {
	0%,
	100% {
		transform: translateY(0);
	}
	50% {
		transform: translateY(6px);
	}
}

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

@media (max-width: 800px) {
	.grid {
		grid-template-columns: 1fr;
	}
}

.card {
	background: var(--bg-elev);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-card);
	padding: 28px;
	transition:
		transform 0.3s ease,
		box-shadow 0.3s ease,
		border-color 0.3s ease;
}

.card:hover {
	transform: translateY(-6px);
	box-shadow: var(--shadow-raised);
	border-color: var(--border-strong);
}

.card-icon {
	width: 40px;
	height: 40px;
	border-radius: var(--radius);
	background: var(--bg-muted);
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--text-strong);
	margin-bottom: 16px;
	transition:
		transform 0.3s ease,
		background 0.3s ease,
		color 0.3s ease;
}

.card:hover .card-icon {
	transform: scale(1.08) rotate(-4deg);
	background: var(--accent-soft);
	color: var(--accent);
}

.card-icon svg {
	width: 20px;
	height: 20px;
}

.steps {
	position: relative;
	display: grid;
	gap: 24px;
	grid-template-columns: repeat(3, 1fr);
}

.steps::before {
	content: "";
	position: absolute;
	top: 24px;
	left: 16.6%;
	right: 16.6%;
	height: 2px;
	background: linear-gradient(90deg, transparent, var(--border-strong), transparent);
	z-index: 0;
}

@media (max-width: 800px) {
	.steps {
		grid-template-columns: 1fr;
	}
	.steps::before {
		display: none;
	}
}

.step-item {
	position: relative;
	z-index: 1;
}

.step-icon-wrap {
	position: relative;
	width: 48px;
	height: 48px;
	margin-bottom: 16px;
}

.step-icon {
	width: 48px;
	height: 48px;
	border-radius: 50%;
	background: var(--bg-elev);
	border: 1px solid var(--border);
	box-shadow: var(--shadow-card);
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--accent);
	transition:
		transform 0.3s ease,
		box-shadow 0.3s ease;
}

.step-icon svg {
	width: 22px;
	height: 22px;
}

.step-item:hover .step-icon {
	transform: translateY(-3px);
	box-shadow: var(--shadow-raised);
}

.step-number {
	position: absolute;
	bottom: -2px;
	right: -2px;
	width: 22px;
	height: 22px;
	border-radius: 50%;
	background: var(--bg-inverse);
	color: var(--text-inverse);
	display: flex;
	align-items: center;
	justify-content: center;
	font-weight: 700;
	font-size: 0.68rem;
	box-shadow: 0 0 0 3px var(--bg);
}

.cta-band {
	position: relative;
	overflow: hidden;
	background: var(--bg-inverse);
	color: var(--text-inverse);
	border-radius: var(--radius-lg);
	padding: 56px 40px;
	text-align: center;
}

.cta-band::before {
	content: "";
	position: absolute;
	inset: -60%;
	background: radial-gradient(circle at 30% 20%, color-mix(in oklab, var(--accent) 35%, transparent), transparent 60%);
	animation: heroGlow 10s ease-in-out infinite alternate;
	pointer-events: none;
}

.cta-band > * {
	position: relative;
	z-index: 1;
}

.cta-band h2 {
	color: var(--text-inverse);
}

.cta-band .muted {
	color: rgba(255, 255, 255, 0.65);
}

footer {
	border-top: 1px solid var(--border);
	padding: 40px 0;
	color: var(--text-muted);
	font-size: 0.9rem;
	display: flex;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 12px;
}

/* ---------- Auth pages ---------- */

.auth-shell {
	min-height: 100vh;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
}

.back-to-site {
	position: fixed;
	top: 24px;
	left: 24px;
	z-index: 10;
}

.auth-card {
	width: 100%;
	max-width: 400px;
	background: var(--bg-elev);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-raised);
	padding: 36px;
}

.auth-card .brand {
	justify-content: center;
	margin-bottom: 24px;
	display: flex;
}

.auth-tabs {
	display: flex;
	background: var(--bg-muted);
	border-radius: var(--radius-pill);
	padding: 4px;
	margin-bottom: 24px;
}

.auth-tab {
	flex: 1;
	text-align: center;
	padding: 8px;
	border-radius: var(--radius-pill);
	font-size: 0.9rem;
	font-weight: 600;
	cursor: pointer;
	color: var(--text-muted);
	border: none;
	background: transparent;
}

.auth-tab.active {
	background: var(--bg-elev);
	color: var(--text-strong);
	box-shadow: var(--shadow-card);
}

.field {
	margin-bottom: 16px;
}

.field label {
	display: block;
	font-size: 0.85rem;
	font-weight: 600;
	margin-bottom: 6px;
	color: var(--text-strong);
}

.field input,
.field select {
	width: 100%;
	padding: 10px 12px;
	border-radius: var(--radius-sm);
	border: 1px solid var(--border-strong);
	font-size: 0.95rem;
	font-family: inherit;
	background: var(--bg-elev);
	color: var(--text);
}

.field input:focus,
.field select:focus {
	outline: none;
	border-color: var(--text-strong);
}

.field-hint {
	font-size: 0.8rem;
	color: var(--text-muted);
	margin-top: 4px;
}

.form-error {
	background: var(--danger-bg);
	color: var(--danger);
	border-radius: var(--radius-sm);
	padding: 10px 12px;
	font-size: 0.88rem;
	margin-bottom: 16px;
	display: none;
}

.form-error.visible {
	display: block;
}

.btn-block {
	width: 100%;
}

/* ---------- Dashboard ---------- */

.app-shell {
	min-height: 100vh;
	display: flex;
	flex-direction: column;
}

.topbar {
	background: var(--bg-elev);
	border-bottom: 1px solid var(--border);
}

.topbar-inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	height: 64px;
}

.user-chip {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 0.9rem;
	color: var(--text-muted);
}

.avatar {
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: var(--bg-inverse);
	color: var(--text-inverse);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 0.8rem;
	font-weight: 700;
}

main.dash {
	flex: 1;
	padding: 40px 0 80px;
}

.dash-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 28px;
	gap: 12px;
}

/* The old `flex-wrap: wrap` here wrapped based on content width — meaning the same viewport
   could lay out differently just because German button labels are longer than their English
   originals, making "+ Connect a shop" visibly jump to a new line purely from toggling the
   language, with no resize involved. Layout should react to the viewport, not to which
   language happens to be active: the title block is now the one that absorbs extra text length
   (its own paragraph just wraps to another line, which reads as normal), the actions never
   shrink or wrap on their own, and the header only restructures at an actual width breakpoint. */
.dash-header > *:first-child {
	min-width: 0;
	flex: 1 1 auto;
}

.dash-header .actions-row {
	flex-shrink: 0;
}

@media (max-width: 720px) {
	.dash-header {
		flex-direction: column;
		align-items: flex-start;
	}
}

.empty-state {
	text-align: center;
	padding: 64px 24px;
	border: 1px dashed var(--border-strong);
	border-radius: var(--radius-lg);
	color: var(--text-muted);
}

.shop-list {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.shop-card {
	background: var(--bg-elev);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-card);
	overflow: hidden;
	transition:
		box-shadow 0.25s ease,
		border-color 0.25s ease;
}

.shop-card:hover {
	box-shadow: var(--shadow-raised);
	border-color: var(--border-strong);
}

/* Opt-in, not automatic: only the very first render of the shop list marks its cards
   .card-enter (see dashboard.html's renderAll/renderShopCard). Expanding a card, switching its
   tabs, and refreshing after an action all update the card in place now — none of them recreate
   this element, so none of them should replay its "I just appeared" entrance. */
.shop-card.card-enter {
	animation: fadeInUp 0.4s ease both;
}

.shop-list .shop-card.card-enter:nth-child(1) {
	animation-delay: 0ms;
}

.shop-list .shop-card.card-enter:nth-child(2) {
	animation-delay: 60ms;
}

.shop-list .shop-card.card-enter:nth-child(3) {
	animation-delay: 120ms;
}

.shop-list .shop-card.card-enter:nth-child(n + 4) {
	animation-delay: 180ms;
}

.shop-card-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 20px 24px;
	cursor: pointer;
	gap: 16px;
	flex-wrap: wrap;
}

.shop-card-chevron {
	display: inline-flex;
}

.shop-card-chevron svg {
	width: 18px;
	height: 18px;
	transition: transform 0.25s ease;
}

.shop-card-chevron.open svg {
	transform: rotate(180deg);
}

.shop-card-title {
	display: flex;
	align-items: center;
	gap: 12px;
}

.shop-card-title code {
	font-size: 0.8rem;
	background: var(--bg-muted);
	padding: 2px 8px;
	border-radius: var(--radius-sm);
}

.badge {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: 0.78rem;
	font-weight: 600;
	padding: 3px 10px;
	border-radius: var(--radius-pill);
}

.badge-dot {
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: currentColor;
}

.badge-active {
	background: var(--success-bg);
	color: var(--success);
}

.badge-inactive {
	background: var(--bg-muted);
	color: var(--text-muted);
}

.badge-warn {
	background: var(--warn-bg);
	color: var(--warn);
}

/* A real, persisted-element accordion: this wrapper stays in the DOM across expand/collapse
   (dashboard.html's toggleShop() only ever toggles the .open class and updates
   .shop-card-body-inner's content in place — it never recreates .shop-card-body itself), so a
   genuine `transition` works here, unlike the old display:none/block + replayed-animation
   approach. grid-template-rows 0fr -> 1fr is the standard CSS-only way to transition to/from a
   content's natural height without knowing that height in advance or measuring it in JS. */
.shop-card-body {
	display: grid;
	grid-template-rows: 0fr;
	border-top: 1px solid transparent;
	transition:
		grid-template-rows 0.32s ease,
		border-color 0.32s ease;
}

.shop-card-body.open {
	grid-template-rows: 1fr;
	border-top-color: var(--border);
}

.shop-card-body-inner {
	/* This is the actual grid item being sized 0fr -> 1fr — it must carry NO padding of its own.
	   Padding always adds to a box's rendered height regardless of min-height:0 (that override
	   only cancels the *content-based* automatic minimum, not padding), so putting padding here
	   would floor the collapsed height at 2x that padding instead of true 0 — exactly the "doesn't
	   fully close" bug this fixes. The real padding lives one level deeper, on
	   .shop-card-body-content, where it can be clipped by this element's overflow:hidden instead
	   of contributing to it.
	*/
	overflow: hidden;
	min-height: 0;
}

.shop-card-body-content {
	padding: 24px;
}

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

.tab-row {
	display: flex;
	gap: 4px;
	background: var(--bg-muted);
	border-radius: var(--radius-pill);
	padding: 4px;
	margin-bottom: 20px;
	width: fit-content;
	flex-wrap: wrap;
}

.tab-btn {
	border: none;
	background: transparent;
	padding: 7px 16px;
	border-radius: var(--radius-pill);
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--text-muted);
	cursor: pointer;
}

.tab-btn.active {
	background: var(--bg-elev);
	color: var(--text-strong);
	box-shadow: var(--shadow-card);
}

.tab-pane {
	display: none;
}

.tab-pane.active {
	display: block;
	animation: tabFadeIn 0.25s ease both;
}

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

.stat-row {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
	gap: 12px;
	margin-bottom: 20px;
}

.stat-tile {
	background: var(--bg-muted);
	border-radius: var(--radius);
	padding: 14px 16px;
	transition:
		transform 0.2s ease,
		background 0.2s ease;
}

.stat-tile:hover {
	transform: translateY(-2px);
	background: var(--accent-soft);
}

.stat-tile .value {
	font-size: 1.4rem;
	font-weight: 700;
	color: var(--text-strong);
	font-variant-numeric: tabular-nums;
}

.stat-tile .label {
	font-size: 0.78rem;
	color: var(--text-muted);
}

.actions-row {
	display: flex;
	gap: 10px;
	flex-wrap: wrap;
	margin-top: 8px;
}

.reveal-box {
	background: var(--bg-muted);
	border: 1px solid var(--border-strong);
	border-radius: var(--radius);
	padding: 16px;
	margin-bottom: 20px;
	animation: cardBodyIn 0.3s ease both;
}

.reveal-box code {
	display: block;
	word-break: break-all;
	background: var(--bg-elev);
	padding: 8px 10px;
	border-radius: var(--radius-sm);
	margin-top: 6px;
	font-size: 0.82rem;
}

.ticket-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 12px 0;
	border-bottom: 1px solid var(--border);
	gap: 12px;
}

.ticket-row:last-child {
	border-bottom: none;
}

.inline-form {
	display: flex;
	gap: 10px;
	flex-wrap: wrap;
	align-items: flex-end;
}

.toast-stack {
	position: fixed;
	bottom: 24px;
	right: 24px;
	display: flex;
	flex-direction: column;
	gap: 10px;
	z-index: 50;
}

.toast {
	background: var(--bg-inverse);
	color: var(--text-inverse);
	padding: 12px 18px;
	border-radius: var(--radius);
	box-shadow: var(--shadow-raised);
	font-size: 0.88rem;
	max-width: 320px;
	animation: toastIn 0.3s ease both;
}

.toast.leaving {
	animation: toastOut 0.25s ease both;
}

@keyframes toastIn {
	from {
		opacity: 0;
		transform: translateY(12px) scale(0.96);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes toastOut {
	from {
		opacity: 1;
		transform: none;
	}
	to {
		opacity: 0;
		transform: translateY(8px) scale(0.96);
	}
}

.toast.error {
	background: var(--danger);
}

.spinner-text {
	color: var(--text-muted);
	font-size: 0.9rem;
	padding: 24px 0;
	text-align: center;
	animation: pulseFade 1.6s ease-in-out infinite;
}

@keyframes pulseFade {
	0%,
	100% {
		opacity: 0.55;
	}
	50% {
		opacity: 1;
	}
}

.checkbox-row {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 16px;
}

/* A real on/off setting reads better as a toggle switch than a checkbox — the underlying
   <input type="checkbox"> stays fully real (still keyboard-focusable, still what
   form.bot_enabled.checked reads), just visually hidden and replaced by .toggle-track/.toggle-thumb,
   the standard accessible "checkbox styled as a switch" pattern. */
.toggle-switch {
	position: relative;
	display: inline-flex;
	align-items: center;
	flex-shrink: 0;
	cursor: pointer;
}

.toggle-switch input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	margin: 0;
}

.toggle-track {
	width: 40px;
	height: 22px;
	border-radius: var(--radius-pill);
	background: var(--bg-muted);
	border: 1px solid var(--border-strong);
	transition:
		background 0.25s ease,
		border-color 0.25s ease;
}

.toggle-thumb {
	display: block;
	width: 16px;
	height: 16px;
	margin: 2px;
	border-radius: 50%;
	background: var(--bg-elev);
	box-shadow: var(--shadow-card);
	transition:
		transform 0.25s cubic-bezier(0.4, 0, 0.2, 1),
		width 0.15s ease;
}

.toggle-switch input:checked + .toggle-track {
	background: var(--success);
	border-color: var(--success);
}

.toggle-switch input:checked + .toggle-track .toggle-thumb {
	transform: translateX(18px);
}

.toggle-switch:active .toggle-thumb {
	width: 19px;
}

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

.toggle-switch input:disabled + .toggle-track {
	opacity: 0.5;
	cursor: not-allowed;
}

/* ---------- Scroll-reveal (landing page sections/cards) ---------- */

.reveal {
	opacity: 0;
	transform: translateY(24px);
	transition:
		opacity 0.6s ease,
		transform 0.6s ease;
	transition-delay: var(--reveal-delay, 0ms);
}

.reveal.is-visible {
	opacity: 1;
	transform: none;
}

.reveal-group .reveal:nth-child(1) {
	--reveal-delay: 0ms;
}

.reveal-group .reveal:nth-child(2) {
	--reveal-delay: 90ms;
}

.reveal-group .reveal:nth-child(3) {
	--reveal-delay: 180ms;
}

/* Respect it: everything above is a nice-to-have, never something that should make the page
   move for someone who's asked their OS not to. */
@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
	}

	.reveal {
		opacity: 1;
		transform: none;
	}
}
