/* ==========================================================================
   Roblox App Store - design system
   Calm neutrals, hairline strokes, generous radii, restrained motion.
   ========================================================================== */

:root {
	--font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", "Inter",
		"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	--font-mono: ui-monospace, SFMono-Regular, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;

	/* The values below are the App Store's own: system greys, label colours as
	   alpha over the page rather than flat hexes, and its key blue. */
	--bg: #f5f5f7;
	--bg-elevated: #ffffff;
	--bg-sunken: #f2f2f7;
	--bg-hover: rgba(0, 0, 0, 0.04);
	--surface-translucent: rgba(245, 245, 247, 0.82);
	/* The matte behind a pillarboxed screenshot. Darker than any surface, so
	   the side bars read as a frame and not as an empty card. */
	--shot-matte: #e4e4e9;

	--text: rgba(0, 0, 0, 0.85);
	--text-secondary: rgba(0, 0, 0, 0.5);
	--text-tertiary: #8e8e93;

	/* A keyline is .15 alpha; anything structural below it is .1. */
	--stroke: rgba(0, 0, 0, 0.15);
	--stroke-strong: rgba(0, 0, 0, 0.25);
	--stroke-faint: rgba(0, 0, 0, 0.10);

	--accent: #007aff;
	--accent-hover: #005cd7;
	--accent-quiet: rgba(0, 122, 255, 0.10);
	--accent-text: #ffffff;

	--positive: #1d8a4e;
	--positive-quiet: rgba(29, 138, 78, 0.10);
	--warning: #a6641a;
	--warning-quiet: rgba(166, 100, 26, 0.12);
	--danger: #c8342b;
	--danger-quiet: rgba(200, 52, 43, 0.10);

	--radius-sm: 9px;
	--radius: 12px;
	--radius-lg: 17px;
	--radius-xl: 24px;
	--radius-pill: 1000px;

	--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
	--shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 6px 20px rgba(0, 0, 0, 0.05);
	--shadow-lg: 0 2px 6px rgba(0, 0, 0, 0.05), 0 20px 50px rgba(0, 0, 0, 0.10);

	--ease: cubic-bezier(0.4, 0, 0.2, 1);
	--fast: 150ms;
	--medium: 220ms;

	--header-height: 60px;
	--page-max: 1140px;
}

@media (prefers-color-scheme: dark) {
	:root {
		--bg: #000000;
		--bg-elevated: #1c1c1e;
		--bg-sunken: #2c2c2e;
		--bg-hover: rgba(255, 255, 255, 0.06);
		--surface-translucent: rgba(10, 10, 11, 0.82);
		--shot-matte: #17171a;

		--text: rgba(255, 255, 255, 0.85);
		--text-secondary: rgba(255, 255, 255, 0.55);
		--text-tertiary: #8e8e93;

		--stroke: rgba(255, 255, 255, 0.15);
		--stroke-strong: rgba(255, 255, 255, 0.25);
		--stroke-faint: rgba(255, 255, 255, 0.10);

		--accent: #0a84ff;
		--accent-hover: #409cff;
		--accent-quiet: rgba(10, 132, 255, 0.16);

		--positive: #32d074;
		--positive-quiet: rgba(50, 208, 116, 0.14);
		--warning: #ffb340;
		--warning-quiet: rgba(255, 179, 64, 0.14);
		--danger: #ff6961;
		--danger-quiet: rgba(255, 105, 97, 0.14);

		--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
		--shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 6px 20px rgba(0, 0, 0, 0.35);
		--shadow-lg: 0 2px 6px rgba(0, 0, 0, 0.5), 0 20px 50px rgba(0, 0, 0, 0.5);
	}
}

/* -- reset ---------------------------------------------------------------- */

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

html {
	-webkit-text-size-adjust: 100%;
	/* Reserve the scrollbar's width on every page, or a short one is 15px
	   wider than a long one and the centred header and footer jump sideways
	   as you move between them. */
	scrollbar-gutter: stable;
}

body {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 15px;
	line-height: 1.55;
	color: var(--text);
	background: var(--bg);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	font-synthesis-weight: none;
}

h1, h2, h3, h4 {
	margin: 0;
	font-weight: 600;
	letter-spacing: -0.021em;
	line-height: 1.12;
}

h1 {
	font-size: clamp(26px, 3vw, 32px);
	font-weight: 700;
	letter-spacing: -0.024em;
}

/* Shelf titles, the size the store sets them at. */
h2 {
	font-size: 22px;
	font-weight: 600;
	letter-spacing: -0.016em;
}

h3 { font-size: 17px; }
h4 { font-size: 15px; }

p { margin: 0 0 12px; }
p:last-child { margin-bottom: 0; }

a {
	color: var(--accent);
	text-decoration: none;
	transition: opacity var(--fast) var(--ease);
}

a:hover { opacity: 0.75; }

img { max-width: 100%; display: block; }

hr {
	border: none;
	border-top: 1px solid var(--stroke-faint);
	margin: 24px 0;
}

code, pre, .mono {
	font-family: var(--font-mono);
	font-size: 12.5px;
}

::selection {
	background: var(--accent-quiet);
}

:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
	border-radius: 4px;
}

/* -- layout --------------------------------------------------------------- */

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

.container {
	width: 100%;
	max-width: var(--page-max);
	margin: 0 auto;
	padding: 0 24px;
}

.container--narrow { max-width: 560px; }
.container--medium { max-width: 860px; }
/* The store runs edge to edge: the sidebar sits at the left margin and the
   shelves reach almost to the right one. */
.container--store { max-width: none; padding: 0 28px; }

main {
	flex: 1;
	padding: 40px 0 80px;
	animation: page-in var(--medium) var(--ease);
}

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

/* Where the browser supports cross-document view transitions it does the page
   change itself, so the entrance animation above would play twice. */
@media (prefers-reduced-motion: no-preference) {
	@view-transition {
		navigation: auto;
	}
}

@supports (view-transition-name: none) {
	main { animation: none; }

	/* The chrome stays put while the content crossfades. */
	.site-header { view-transition-name: site-header; }
	.site-footer { view-transition-name: site-footer; }

	::view-transition-old(root),
	::view-transition-new(root) {
		animation-duration: var(--medium);
		animation-timing-function: var(--ease);
	}

	::view-transition-old(site-header),
	::view-transition-new(site-header),
	::view-transition-old(site-footer),
	::view-transition-new(site-footer) {
		animation: none;
		mix-blend-mode: normal;
	}
}

.stack { display: flex; flex-direction: column; gap: 24px; }
.stack--sm { gap: 12px; }
.stack--lg { gap: 40px; }

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

.row--between { justify-content: space-between; }
.row--wrap { flex-wrap: wrap; }
.spacer { flex: 1; }

.grid {
	display: grid;
	gap: 20px;
	grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

.grid--2 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* -- header --------------------------------------------------------------- */

.site-header {
	position: sticky;
	top: 0;
	z-index: 40;
	height: var(--header-height);
	display: flex;
	align-items: center;
	background: var(--bg-elevated);
	border-bottom: 1px solid var(--stroke-faint);
	transition: box-shadow var(--medium) var(--ease);
}

.site-header.is-scrolled { box-shadow: 0 1px 12px rgba(0, 0, 0, 0.05); }

@media (prefers-color-scheme: dark) {
	.site-header.is-scrolled { box-shadow: 0 1px 12px rgba(0, 0, 0, 0.5); }
}

.site-header .container {
	display: flex;
	align-items: center;
	gap: 8px;
	max-width: none;
	padding: 0 28px;
}

.brand {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	color: var(--text);
	font-weight: 600;
	letter-spacing: -0.015em;
	margin-right: 20px;
	white-space: nowrap;
}

.brand:hover { opacity: 1; }

/*
	An uploaded logo replaces the lettermark and the name. Height is fixed and
	width follows, so a wide wordmark and a square glyph both sit on the same
	baseline as the navigation next to them.
*/
.brand__logo {
	display: block;
	height: 26px;
	width: auto;
	max-width: 190px;
	object-fit: contain;
}

.brand__logo--footer { height: 30px; max-width: 160px; }

.brand .mark {
	width: 22px;
	height: 22px;
	border-radius: 6px;
	background: linear-gradient(160deg, var(--accent), #6a5cff);
	display: grid;
	place-items: center;
	color: #fff;
	font-size: 12px;
	font-weight: 700;
}

/* -- header search ---------------------------------------------------------- */

.header-search {
	position: relative;
	display: flex;
	align-items: center;
	margin-left: auto;
	width: clamp(160px, 22vw, 260px);
}

.header-search__icon {
	position: absolute;
	left: 11px;
	width: 15px;
	height: 15px;
	color: var(--text-tertiary);
	pointer-events: none;
}

.header-search input[type="search"] {
	width: 100%;
	height: 34px;
	padding: 0 12px 0 32px;
	font-size: 13.5px;
	border-radius: var(--radius-pill);
	background: var(--bg-sunken);
	border-color: transparent;
}

.header-search input[type="search"]:focus {
	background: var(--bg-elevated);
	border-color: var(--accent);
}

/* -- account menu ----------------------------------------------------------- */

.menu { position: relative; }

.menu > summary {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 4px 10px 4px 4px;
	border-radius: var(--radius-pill);
	font-size: 13.5px;
	color: var(--text);
	cursor: pointer;
	list-style: none;
	white-space: nowrap;
	transition: background var(--fast) var(--ease);
}

.menu > summary::-webkit-details-marker { display: none; }
.menu > summary:hover { background: var(--bg-hover); }

.menu__avatar {
	display: grid;
	place-items: center;
	width: 26px;
	height: 26px;
	border-radius: 50%;
	background: linear-gradient(160deg, var(--accent), #6a5cff);
	color: #fff;
	font-size: 11px;
	font-weight: 600;
}

.menu__caret {
	width: 9px;
	height: 9px;
	color: var(--text-tertiary);
	transition: transform var(--fast) var(--ease);
}

.menu[open] .menu__caret { transform: rotate(180deg); }

.menu__panel {
	position: absolute;
	top: calc(100% + 8px);
	right: 0;
	z-index: 50;
	min-width: 208px;
	padding: 6px;
	display: flex;
	flex-direction: column;
	gap: 1px;
	background: var(--bg-elevated);
	border: 1px solid var(--stroke);
	border-radius: var(--radius);
	box-shadow: var(--shadow-lg);
	animation: menu-in var(--fast) var(--ease);
}

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

.menu__head {
	padding: 8px 10px 10px;
	border-bottom: 1px solid var(--stroke-faint);
	margin-bottom: 5px;
	display: flex;
	flex-direction: column;
}

.menu__head strong { font-size: 13.5px; }
.menu__head span { font-size: 12px; color: var(--text-tertiary); }

.menu__panel a,
.menu__panel button {
	display: flex;
	align-items: center;
	width: 100%;
	padding: 8px 10px;
	border: none;
	border-radius: var(--radius-sm);
	background: transparent;
	font: inherit;
	font-size: 13.5px;
	color: var(--text);
	text-align: left;
	cursor: pointer;
}

.menu__panel a:hover,
.menu__panel button:hover { opacity: 1; background: var(--bg-hover); }
.menu__panel form { display: block; }
.menu__sep { height: 1px; background: var(--stroke-faint); margin: 5px 0; }

.nav {
	display: flex;
	align-items: center;
	gap: 2px;
	flex: 1;
	min-width: 0;
	overflow-x: auto;
	scrollbar-width: none;
}

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

.nav a {
	color: var(--text-secondary);
	font-size: 13.5px;
	padding: 6px 10px;
	border-radius: var(--radius-sm);
	white-space: nowrap;
	transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}

.nav a:hover {
	opacity: 1;
	color: var(--text);
	background: var(--bg-hover);
}

.nav a.is-active {
	color: var(--text);
	font-weight: 500;
}

.header-actions {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-left: 12px;
}

/* -- buttons -------------------------------------------------------------- */

.btn {
	--btn-bg: var(--bg-elevated);
	--btn-color: var(--text);
	--btn-border: var(--stroke);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 7px;
	font: inherit;
	font-size: 13.5px;
	font-weight: 500;
	line-height: 1;
	padding: 9px 16px;
	color: var(--btn-color);
	background: var(--btn-bg);
	border: 1px solid var(--btn-border);
	border-radius: var(--radius);
	cursor: pointer;
	white-space: nowrap;
	transition: transform var(--fast) var(--ease), background var(--fast) var(--ease),
		border-color var(--fast) var(--ease), opacity var(--fast) var(--ease);
}

.btn:hover {
	opacity: 1;
	border-color: var(--stroke-strong);
	background: var(--bg-hover);
}

.btn:active { transform: scale(0.975); }
.btn[disabled] { opacity: 0.45; pointer-events: none; }

.btn--primary {
	--btn-bg: var(--accent);
	--btn-color: var(--accent-text);
	--btn-border: transparent;
}

.btn--primary:hover {
	background: var(--accent-hover);
	border-color: transparent;
}

.btn--ghost {
	--btn-bg: transparent;
	--btn-border: transparent;
	color: var(--text-secondary);
}

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

.btn--danger {
	--btn-color: var(--danger);
	--btn-border: var(--stroke);
}

.btn--danger:hover {
	background: var(--danger-quiet);
	border-color: transparent;
}

.btn--sm { padding: 6px 11px; font-size: 12.5px; border-radius: var(--radius-sm); }
.btn--lg { padding: 12px 22px; font-size: 15px; border-radius: var(--radius); }
.btn--block { width: 100%; }

/* -- cards ---------------------------------------------------------------- */

.card {
	background: var(--bg-elevated);
	border: 1px solid var(--stroke);
	border-radius: var(--radius-lg);
	padding: 22px;
	box-shadow: var(--shadow-sm);
}

.card--flush { padding: 0; overflow: hidden; }
.card--quiet { background: var(--bg-sunken); box-shadow: none; }

.card-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 16px 22px;
	border-bottom: 1px solid var(--stroke-faint);
}

.card-header h3 { font-size: 15px; }
.card-body { padding: 22px; }
.card-footer {
	padding: 14px 22px;
	border-top: 1px solid var(--stroke-faint);
	background: var(--bg-sunken);
}

/* app cards */

.app-card {
	display: flex;
	flex-direction: column;
	position: relative;
	background: var(--bg-elevated);
	border: none;
	border-radius: var(--radius-lg);
	overflow: hidden;
	color: inherit;
	box-shadow: var(--shadow-sm);
	transition: transform var(--medium) var(--ease), box-shadow var(--medium) var(--ease);
}

.app-card::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb, 120, 120, 128), 0.32);
	pointer-events: none;
}

/* Nothing rises under the pointer; the shadow deepens and the button on the
   card does the rest. */
.app-card:hover {
	opacity: 1;
	box-shadow: var(--shadow);
}

.app-card:hover .app-card__cover img {
	transform: scale(1.02);
}

.app-card__cover {
	aspect-ratio: 16 / 9;
	background: var(--bg-sunken);
	display: grid;
	place-items: center;
	overflow: hidden;
}

.app-card__cover img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 420ms var(--ease);
}

/* Covers fade in when they arrive instead of popping into place - but only
   when JavaScript is there to mark them as loaded. */
html.js .app-card__cover img,
html.js .detail-cover img {
	opacity: 0;
	transition: opacity 320ms var(--ease), transform 420ms var(--ease);
}

html.js .app-card__cover img.is-loaded,
html.js .detail-cover img.is-loaded {
	opacity: 1;
}

.app-card__placeholder {
	font-size: 24px;
	font-weight: 600;
	color: var(--text-tertiary);
	letter-spacing: -0.02em;
	background: linear-gradient(150deg, var(--bg-sunken), var(--bg-hover));
	width: 100%;
	height: 100%;
	display: grid;
	place-items: center;
}

.app-card__placeholder span {
	display: grid;
	place-items: center;
	width: 56px;
	height: 56px;
	border-radius: 16px;
	border: 1px solid var(--stroke);
	background: var(--bg-elevated);
	box-shadow: var(--shadow-sm);
}

.app-card__body {
	padding: 16px 18px 18px;
	display: flex;
	flex-direction: column;
	gap: 6px;
	flex: 1;
}

.app-card__title {
	font-size: 15px;
	font-weight: 600;
	letter-spacing: -0.01em;
}

.app-card__summary {
	color: var(--text-secondary);
	font-size: 13.5px;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	/* Reserve both lines so cards in a row line up. */
	min-height: calc(2 * 1.55em);
}

.app-card__meta {
	margin-top: auto;
	padding-top: 10px;
	display: flex;
	align-items: center;
	gap: 10px;
	color: var(--text-tertiary);
	font-size: 12px;
}

/* Featured apps get a wider, shallower cover so the spotlight does not push
   the rest of the store off the screen. */
.spotlight .app-card__cover {
	aspect-ratio: 21 / 9;
}

@media (max-width: 640px) {
	.spotlight .app-card__cover { aspect-ratio: 16 / 9; }
}

/* -- badges & pills ------------------------------------------------------- */

.badge {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	padding: 3px 9px;
	border-radius: var(--radius-pill);
	font-size: 11.5px;
	font-weight: 500;
	line-height: 1.5;
	background: var(--bg-sunken);
	border: 1px solid var(--stroke-faint);
	color: var(--text-secondary);
	white-space: nowrap;
}

.badge--accent { background: var(--accent-quiet); color: var(--accent); border-color: transparent; }
.badge--positive { background: var(--positive-quiet); color: var(--positive); border-color: transparent; }
.badge--warning { background: var(--warning-quiet); color: var(--warning); border-color: transparent; }
.badge--danger { background: var(--danger-quiet); color: var(--danger); border-color: transparent; }

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

.pill-row {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.pill {
	display: inline-flex;
	align-items: center;
	padding: 6px 13px;
	border-radius: var(--radius-pill);
	border: 1px solid var(--stroke);
	background: var(--bg-elevated);
	color: var(--text-secondary);
	font-size: 13px;
	transition: background var(--fast) var(--ease), color var(--fast) var(--ease),
		border-color var(--fast) var(--ease);
}

.pill:hover { opacity: 1; color: var(--text); border-color: var(--stroke-strong); }

.pill.is-active {
	background: var(--text);
	border-color: var(--text);
	color: var(--bg-elevated);
}

/* -- forms ---------------------------------------------------------------- */

.field { display: flex; flex-direction: column; gap: 6px; }
.field + .field { margin-top: 18px; }

.field label,
.label {
	font-size: 13px;
	font-weight: 500;
	color: var(--text);
}

.field .hint {
	font-size: 12.5px;
	color: var(--text-tertiary);
}

.field .error {
	font-size: 12.5px;
	color: var(--danger);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="search"],
input[type="number"],
input[type="url"],
select,
textarea {
	font: inherit;
	font-size: 14px;
	width: 100%;
	padding: 10px 13px;
	color: var(--text);
	background: var(--bg-elevated);
	border: 1px solid var(--stroke);
	border-radius: var(--radius);
	transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
	appearance: none;
}

textarea { resize: vertical; min-height: 96px; line-height: 1.5; }

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

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

input.has-error,
textarea.has-error { border-color: var(--danger); }

select {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%2386868b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 13px center;
	padding-right: 34px;
}

.checkbox {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	padding: 12px 14px;
	border: 1px solid var(--stroke);
	border-radius: var(--radius);
	background: var(--bg-elevated);
	cursor: pointer;
	transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}

.checkbox:hover { border-color: var(--stroke-strong); }
.checkbox input { margin: 2px 0 0; width: 16px; height: 16px; accent-color: var(--accent); flex: none; }
.checkbox span { font-size: 13.5px; }
.checkbox .hint { display: block; color: var(--text-tertiary); font-size: 12.5px; }

.search-bar {
	display: flex;
	gap: 10px;
	flex-wrap: wrap;
}

.search-bar input[type="search"] { flex: 1; min-width: 200px; }
.search-bar select { width: auto; min-width: 150px; }

/* file drop */

.dropzone {
	position: relative;
	display: grid;
	place-items: center;
	gap: 8px;
	padding: 32px 24px;
	text-align: center;
	border: 1px dashed var(--stroke-strong);
	border-radius: var(--radius-lg);
	background: var(--bg-sunken);
	cursor: pointer;
	transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}

.dropzone:hover,
.dropzone.is-active {
	border-color: var(--accent);
	background: var(--accent-quiet);
}

/* A chosen file is acknowledged rather than silently swallowed. */
.dropzone.is-filled {
	border-style: solid;
	border-color: var(--positive);
	background: var(--positive-quiet);
}

.dropzone.is-filled .dropzone__title::before {
	content: "\2713\00a0";
	color: var(--positive);
	font-weight: 600;
}

.dropzone__title {
	transition: color var(--fast) var(--ease);
}

.dropzone input[type="file"] {
	position: absolute;
	inset: 0;
	opacity: 0;
	cursor: pointer;
}

.dropzone__title { font-weight: 500; }
.dropzone__hint { font-size: 12.5px; color: var(--text-tertiary); }

/* A bare file input is the one control browsers still draw themselves; give it
   the same shape as every other field so a form does not break character. */
input[type="file"] {
	width: auto;
	max-width: 100%;
	padding: 6px 10px 6px 6px;
	font-size: 13px;
	color: var(--text-secondary);
	background: var(--bg-sunken);
	border: 1px solid var(--stroke);
	border-radius: var(--radius);
	cursor: pointer;
}

input[type="file"]::file-selector-button {
	margin-right: 10px;
	padding: 6px 12px;
	font: inherit;
	font-size: 13px;
	font-weight: 500;
	color: var(--text);
	background: var(--bg-elevated);
	border: 1px solid var(--stroke);
	border-radius: var(--radius-sm);
	cursor: pointer;
	transition: background var(--fast) var(--ease);
}

input[type="file"]::file-selector-button:hover { background: var(--bg-hover); }

/* A short numbered procedure, the numbers set in their own column so the text
   lines up under itself rather than under the digit. */
.steps {
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: step;
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.steps li {
	counter-increment: step;
	position: relative;
	padding-left: 32px;
	font-size: 13.5px;
	color: var(--text-secondary);
}

.steps li::before {
	content: counter(step);
	position: absolute;
	left: 0;
	top: -1px;
	display: grid;
	place-items: center;
	width: 21px;
	height: 21px;
	border-radius: 50%;
	background: var(--bg-sunken);
	color: var(--text);
	font-size: 11.5px;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.steps li strong { color: var(--text); font-weight: 500; }
.steps .hint { display: block; margin-top: 3px; }

/* -- tables --------------------------------------------------------------- */

.table-wrap {
	overflow-x: auto;
	border: 1px solid var(--stroke);
	border-radius: var(--radius-lg);
	background: var(--bg-elevated);
}

table {
	width: 100%;
	border-collapse: collapse;
	font-size: 13.5px;
}

thead th {
	text-align: left;
	font-weight: 500;
	font-size: 12px;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--text-tertiary);
	padding: 12px 16px;
	border-bottom: 1px solid var(--stroke-faint);
	white-space: nowrap;
}

tbody td {
	padding: 12px 16px;
	border-bottom: 1px solid var(--stroke-faint);
	vertical-align: middle;
}

tbody tr:last-child td { border-bottom: none; }
tbody tr { transition: background var(--fast) var(--ease); }
tbody tr:hover { background: var(--bg-hover); }

.table-actions {
	display: flex;
	gap: 6px;
	justify-content: flex-end;
	flex-wrap: wrap;
}

/* -- stats ---------------------------------------------------------------- */

.stat {
	background: var(--bg-elevated);
	border: 1px solid var(--stroke);
	border-radius: var(--radius-lg);
	padding: 18px 20px;
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.stat__value {
	font-size: 26px;
	font-weight: 600;
	letter-spacing: -0.025em;
}

.stat__label {
	font-size: 12.5px;
	color: var(--text-secondary);
}

.stat__delta { font-size: 12px; color: var(--text-tertiary); }

/* chart */

.chart {
	display: flex;
	align-items: flex-end;
	gap: 4px;
	height: 120px;
	padding-top: 8px;
}

.chart__bar {
	flex: 1;
	min-width: 4px;
	border-radius: 4px 4px 2px 2px;
	background: var(--accent-quiet);
	position: relative;
	transition: background var(--fast) var(--ease);
}

.chart__bar::after {
	content: attr(data-value);
	position: absolute;
	top: -18px;
	left: 50%;
	transform: translateX(-50%);
	font-size: 11px;
	color: var(--text-tertiary);
	opacity: 0;
	transition: opacity var(--fast) var(--ease);
}

.chart__bar:hover { background: var(--accent); }
.chart__bar:hover::after { opacity: 1; }

.chart-labels {
	display: flex;
	gap: 4px;
	margin-top: 6px;
	font-size: 10.5px;
	color: var(--text-tertiary);
}

.chart-labels span { flex: 1; text-align: center; }

/* -- flash / toast -------------------------------------------------------- */

.flash-stack {
	position: fixed;
	top: calc(var(--header-height) + 12px);
	right: 20px;
	z-index: 60;
	display: flex;
	flex-direction: column;
	gap: 10px;
	max-width: min(380px, calc(100vw - 40px));
}

.flash {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	padding: 12px 14px;
	border-radius: var(--radius);
	border: 1px solid var(--stroke);
	background: var(--bg-elevated);
	box-shadow: var(--shadow);
	font-size: 13.5px;
	animation: flash-in var(--medium) var(--ease);
}

.flash.is-leaving {
	animation: flash-out var(--medium) var(--ease) forwards;
}

.flash__icon { flex: none; width: 8px; height: 8px; border-radius: 50%; margin-top: 7px; background: var(--text-tertiary); }
.flash--success .flash__icon { background: var(--positive); }
.flash--warning .flash__icon { background: var(--warning); }
.flash--danger .flash__icon,
.flash--error .flash__icon { background: var(--danger); }
.flash--info .flash__icon { background: var(--accent); }

.flash__close {
	background: none;
	border: none;
	color: var(--text-tertiary);
	cursor: pointer;
	font-size: 16px;
	line-height: 1;
	padding: 2px 4px;
	border-radius: 4px;
}

.flash__close:hover { color: var(--text); background: var(--bg-hover); }

@keyframes flash-in {
	from { opacity: 0; transform: translateY(-8px) scale(0.98); }
	to { opacity: 1; transform: none; }
}

@keyframes flash-out {
	to { opacity: 0; transform: translateY(-6px) scale(0.98); }
}

/* -- misc components ------------------------------------------------------ */

.page-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 16px;
	flex-wrap: wrap;
	margin-bottom: 28px;
}

.page-head__title { display: flex; flex-direction: column; gap: 6px; }
.page-head__title p { color: var(--text-secondary); margin: 0; }

.eyebrow {
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--text-tertiary);
}

.empty {
	display: grid;
	place-items: center;
	gap: 10px;
	padding: 64px 24px;
	text-align: center;
	border: 1px dashed var(--stroke);
	border-radius: var(--radius-lg);
	color: var(--text-secondary);
	background: var(--bg-sunken);
}

.empty h3 { color: var(--text); }

.key-display {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 14px;
	border-radius: var(--radius);
	border: 1px solid var(--stroke);
	background: var(--bg-sunken);
	font-family: var(--font-mono);
	font-size: 12.5px;
	word-break: break-all;
}

.meta-list {
	display: grid;
	gap: 0;
}

.meta-list__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	padding: 10px 0;
	border-bottom: 1px solid var(--stroke-faint);
	font-size: 13.5px;
}

.meta-list__row:last-child { border-bottom: none; }
.meta-list__label { color: var(--text-secondary); }
.meta-list__value { font-weight: 500; text-align: right; }

.prose { font-size: 14.5px; color: var(--text); white-space: pre-wrap; word-wrap: break-word; }

.divider { height: 1px; background: var(--stroke-faint); margin: 20px 0; }

/* A stack already spaces what it holds; a divider adding its own margin on top
   of the gap is what left those pools of empty space inside the cards. */
.stack > .divider { margin: 0; }

.text-secondary { color: var(--text-secondary); }
.text-tertiary { color: var(--text-tertiary); }
.text-danger { color: var(--danger); }
.text-sm { font-size: 13px; }
.text-xs { font-size: 12px; }
.text-center { text-align: center; }
.mono { font-family: var(--font-mono); }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.nowrap { white-space: nowrap; }
.mt-0 { margin-top: 0; }
.mt-8 { margin-top: 8px; }
.mt-16 { margin-top: 16px; }
.mt-24 { margin-top: 24px; }
.mb-0 { margin-bottom: 0; }
.hidden { display: none !important; }

/* -- instance tree viewer -------------------------------------------------- */

.tree {
	font-family: var(--font-mono);
	font-size: 12.5px;
	line-height: 1.7;
	max-height: 460px;
	overflow: auto;
	padding: 4px 2px;
}

.tree ul {
	list-style: none;
	margin: 0;
	padding-left: 18px;
	border-left: 1px solid var(--stroke-faint);
}

.tree > ul { padding-left: 2px; border-left: none; }
.tree li { padding: 1px 0; }

.tree__node {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 1px 6px;
	border-radius: 6px;
	cursor: default;
}

.tree__node:hover { background: var(--bg-hover); }

.tree__toggle {
	border: none;
	background: none;
	color: var(--text-tertiary);
	cursor: pointer;
	padding: 0 2px;
	font-size: 10px;
	width: 14px;
	transition: transform var(--fast) var(--ease);
}

.tree__toggle[aria-expanded="false"] { transform: rotate(-90deg); }
.tree__class { color: var(--accent); }
.tree__name { color: var(--text); }
.tree__count { color: var(--text-tertiary); font-size: 11px; }

/* -- modal ---------------------------------------------------------------- */

dialog {
	border: 1px solid var(--stroke);
	border-radius: var(--radius-lg);
	padding: 0;
	background: var(--bg-elevated);
	color: var(--text);
	box-shadow: var(--shadow-lg);
	max-width: min(460px, calc(100vw - 32px));
	width: 100%;
}

dialog::backdrop {
	background: rgba(0, 0, 0, 0.32);
	backdrop-filter: blur(2px);
	animation: fade-in var(--fast) var(--ease);
}

dialog[open] { animation: modal-in var(--medium) var(--ease); }

.modal__body { padding: 24px; display: flex; flex-direction: column; gap: 10px; }
.modal__actions { display: flex; justify-content: flex-end; gap: 8px; padding: 14px 24px; border-top: 1px solid var(--stroke-faint); background: var(--bg-sunken); }

@keyframes modal-in {
	from { opacity: 0; transform: translateY(8px) scale(0.98); }
	to { opacity: 1; transform: none; }
}

@keyframes fade-in {
	from { opacity: 0; }
	to { opacity: 1; }
}

/* -- pagination ------------------------------------------------------------ */

.pagination {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	margin-top: 32px;
	font-size: 13.5px;
	color: var(--text-secondary);
}

/* -- footer ---------------------------------------------------------------- */

.site-footer .container { max-width: none; padding: 0 28px; }

.site-footer {
	border-top: 1px solid var(--stroke-faint);
	padding: 28px 0;
	color: var(--text-tertiary);
	font-size: 12.5px;
	background: var(--bg-sunken);
}

.site-footer a { color: var(--text-secondary); }

/* -- hero ------------------------------------------------------------------ */

.hero {
	padding: 24px 0 34px;
	display: flex;
	flex-direction: column;
	gap: 10px;
	max-width: 640px;
}

.hero h1 { font-size: 40px; letter-spacing: -0.03em; }
.hero p { font-size: 17px; color: var(--text-secondary); }

/* -- detail page ----------------------------------------------------------- */

.detail-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 320px;
	gap: 28px;
	align-items: start;
}

.detail-cover {
	border-radius: var(--radius-xl);
	overflow: hidden;
	border: 1px solid var(--stroke);
	background: var(--bg-sunken);
	aspect-ratio: 16 / 9;
}

.detail-cover img { width: 100%; height: 100%; object-fit: cover; }

.sticky-side { position: sticky; top: calc(var(--header-height) + 24px); }

/* -- admin sub navigation --------------------------------------------------- */

.subnav {
	display: flex;
	gap: 4px;
	padding: 4px;
	background: var(--bg-sunken);
	border: 1px solid var(--stroke-faint);
	border-radius: var(--radius);
	margin-bottom: 28px;
	overflow-x: auto;
}

.subnav a {
	padding: 7px 14px;
	border-radius: var(--radius-sm);
	font-size: 13.5px;
	color: var(--text-secondary);
	white-space: nowrap;
	transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}

.subnav a:hover { opacity: 1; color: var(--text); background: var(--bg-hover); }

.subnav a.is-active {
	background: var(--bg-elevated);
	color: var(--text);
	font-weight: 500;
	box-shadow: var(--shadow-sm);
}

/* -- developer page --------------------------------------------------------- */

.dev-head {
	display: flex;
	align-items: center;
	gap: 20px;
	flex-wrap: wrap;
	margin-bottom: 30px;
}

.dev-head__mark {
	flex: none;
	display: grid;
	place-items: center;
	width: 72px;
	height: 72px;
	border-radius: 20px;
	background: linear-gradient(155deg, hsl(var(--hue) 68% 58%), hsl(calc(var(--hue) + 35) 68% 42%));
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
	color: #fff;
	font-size: 24px;
	font-weight: 600;
	letter-spacing: -0.02em;
}

.dev-head__text { flex: 1 1 240px; min-width: 0; }

.dev-head__bio {
	margin: 6px 0 0;
	max-width: 62ch;
	font-size: 14px;
	color: var(--text-secondary);
}

.dev-head__stats {
	display: flex;
	gap: 28px;
	flex: none;
}

.dev-head__value {
	display: block;
	font-size: 20px;
	font-weight: 600;
	letter-spacing: -0.015em;
	font-variant-numeric: tabular-nums;
}

.dev-head__label { font-size: 12px; color: var(--text-tertiary); }

.app-hero__author {
	color: inherit;
	text-decoration: underline;
	text-decoration-color: rgba(255, 255, 255, 0.4);
	text-underline-offset: 2px;
}

.app-hero__author:hover { opacity: 1; text-decoration-color: currentColor; }

@media (max-width: 620px) {
	.dev-head__mark { width: 56px; height: 56px; border-radius: 16px; font-size: 19px; }
	.dev-head__stats { gap: 20px; }
	.dev-head__value { font-size: 17px; }
}

/* -- admin category list ---------------------------------------------------- */

.cat-admin {
	display: flex;
	flex-direction: column;
}

.cat-admin__row {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 10px 0;
	border-bottom: 1px solid var(--stroke-faint);
}

.cat-admin__row:last-child { border-bottom: none; }

.cat-admin__dot {
	flex: none;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: hsl(var(--hue, 210) 70% 52%);
}

.cat-admin__edit {
	display: flex;
	flex: 1 1 auto;
	gap: 8px;
	min-width: 0;
}

.cat-admin__edit input { min-width: 0; }
.cat-admin__edit input:first-of-type { flex: 0 1 220px; font-weight: 500; }
.cat-admin__edit input:last-of-type { flex: 1 1 auto; }

.cat-admin__count {
	flex: none;
	min-width: 34px;
	padding: 3px 9px;
	border-radius: 999px;
	background: var(--bg-sunken);
	color: var(--text-secondary);
	font-size: 12.5px;
	font-variant-numeric: tabular-nums;
	text-align: center;
}

.cat-admin__actions {
	display: flex;
	flex: none;
	gap: 6px;
}

@media (max-width: 720px) {
	.cat-admin__row { flex-wrap: wrap; }
	.cat-admin__edit { flex: 1 1 100%; flex-wrap: wrap; order: 1; }
	.cat-admin__edit input:first-of-type,
	.cat-admin__edit input:last-of-type { flex: 1 1 100%; }
	.cat-admin__actions { order: 2; margin-left: auto; }
}

/* -- responsive ------------------------------------------------------------ */

@media (max-width: 900px) {
	.detail-grid { grid-template-columns: minmax(0, 1fr); }
	.sticky-side { position: static; }
}

@media (max-width: 640px) {
	.container { padding: 0 16px; }
	h1 { font-size: 27px; }
	.hero h1 { font-size: 31px; }
	main { padding: 24px 0 56px; }
	.page-head { margin-bottom: 20px; }
	.flash-stack { top: 12px; right: 12px; left: 12px; max-width: none; }

	/* Two rows instead of one cramped, clipped line. */
	.site-header {
		position: static;
		height: auto;
		padding: 8px 0 6px;
	}

	.site-header .container {
		flex-wrap: wrap;
		row-gap: 4px;
	}

	.brand { margin-right: 8px; }
	.header-actions { margin-left: auto; }

	.nav {
		order: 3;
		/* flex-basis 100% forces the nav onto its own line instead of being
		   squeezed to nothing next to the brand. */
		flex: 0 0 100%;
		width: 100%;
		padding-bottom: 2px;
	}

	.nav a { padding: 6px 8px; }
	.btn { padding: 8px 13px; }
}



/* ==========================================================================
   Store layout: sidebar, editorial heroes, rails, category tiles
   ========================================================================== */

.container--wide { max-width: 1440px; }

.store-layout {
	display: grid;
	grid-template-columns: 216px minmax(0, 1fr);
	gap: 34px;
	align-items: start;
}

.store-sidebar {
	position: sticky;
	top: calc(var(--header-height) + 22px);
	display: flex;
	flex-direction: column;
	gap: 3px;
	/* Grid items refuse to shrink below their content unless told to, which is
	   what lets the rails scroll inside the page instead of widening it. */
	min-width: 0;
}

.store-main { min-width: 0; }

.store-search {
	position: relative;
	display: flex;
	align-items: center;
	margin-bottom: 14px;
}

.store-search__icon {
	position: absolute;
	left: 11px;
	width: 15px;
	height: 15px;
	color: var(--text-tertiary);
	pointer-events: none;
}

.store-search input[type="search"] {
	width: 100%;
	height: 34px;
	padding: 0 12px 0 32px;
	font-size: 13.5px;
	border-radius: var(--radius-pill);
	background: var(--bg-sunken);
	border-color: transparent;
}

.store-search input[type="search"]:focus {
	background: var(--bg-elevated);
	border-color: var(--accent);
}

.store-nav {
	display: flex;
	flex-direction: column;
	gap: 1px;
}

.store-nav a {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 7px 10px;
	border-radius: var(--radius-sm);
	font-size: 13.5px;
	color: var(--text-secondary);
	transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}

.store-nav a:hover { opacity: 1; color: var(--text); background: var(--bg-hover); }

.store-nav a.is-active {
	background: var(--accent-quiet);
	color: var(--accent);
	font-weight: 500;
}

.store-nav__dot {
	flex: none;
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: hsl(var(--hue) 70% 52%);
}

.store-nav__count {
	margin-left: auto;
	font-size: 11.5px;
	color: var(--text-tertiary);
	font-variant-numeric: tabular-nums;
}

.store-nav__label {
	margin: 20px 0 6px;
	padding: 0 10px;
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--text-tertiary);
}

.store-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 30px;
}

.store-note {
	margin: 0 0 20px;
	padding: 12px 16px;
	border-radius: var(--radius);
	border: 1px solid var(--stroke-faint);
	background: var(--bg-sunken);
	font-size: 13.5px;
	color: var(--text-secondary);
}

/* -- hero ------------------------------------------------------------------ */

.hero-grid {
	display: grid;
	grid-template-columns: 1.5fr 1fr;
	gap: 20px;
}

.hero-grid--single { grid-template-columns: minmax(0, 1fr); }

.hero-card {
	position: relative;
	display: flex;
	flex-direction: column;
	isolation: isolate;
}

/* The banner again, large and blurred behind the card, so its colour spills
   out past the edges. Purely decorative: it is the same picture that is
   already visible, so nothing is hidden behind the blur. */
.hero-card__glow {
	position: absolute;
	/* Inset, not outset: the blur spreads outward from inside the card, so the
	   light has no edge of its own. Sized past the card it stayed a rectangle
	   with straight sides, which read as a second, square frame. */
	inset: 12% 8% 4%;
	z-index: -1;
	background-size: cover;
	background-position: center;
	filter: blur(64px) saturate(190%);
	/* Restrained on a light page, where a dark blur reads as a smudge rather
	   than a glow. */
	opacity: 0.32;
	pointer-events: none;
}

@media (prefers-color-scheme: dark) {
	.hero-card__glow { opacity: 0.7; }
}

.hero-card__media {
	position: relative;
	display: block;
	flex: 1;
	min-height: 380px;
	border-radius: var(--radius-xl);
	overflow: hidden;
	color: #fff;
	background: rgb(var(--accent-rgb, 92, 112, 148));
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.22);
}

/* The keyline takes the banner's own colour rather than a neutral grey. */
.hero-card__media::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb, 92, 112, 148), 0.55);
	pointer-events: none;
}

.hero-card__media:hover { opacity: 1; }

/* The direct child only: the lockup inside the artwork carries an app icon,
   and a descendant selector would stretch that across the whole card. */
.hero-card__media > img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.hero-card__scrim {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0.05) 0%, rgba(0, 0, 0, 0.30) 48%, rgba(0, 0, 0, 0.82) 100%);
}

.hero-card__text {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	display: flex;
	flex-direction: column;
	gap: 7px;
	/* The carousel dots sit inside the card, so the lockup keeps clear of them. */
	padding: 26px 28px 38px;
	max-width: 560px;
}

.hero-card__eyebrow {
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.72);
}

.hero-card__title {
	font-size: 32px;
	font-weight: 700;
	letter-spacing: -0.026em;
	line-height: 1.1;
	color: #fff;
	text-wrap: balance;
}

.hero-card__summary {
	font-size: 14px;
	line-height: 1.45;
	color: rgba(255, 255, 255, 0.78);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.hero-card__rule {
	height: 1px;
	margin: 11px 0 3px;
	background: rgba(255, 255, 255, 0.22);
}

/* The app itself sits under the hairline, on the artwork - not on a strip
   below it. */
.hero-card__lockup {
	display: flex;
	align-items: center;
	gap: 12px;
}

.hero-card__meta {
	display: flex;
	flex-direction: column;
	min-width: 0;
	line-height: 1.35;
}

.hero-card__meta strong { font-size: 14px; color: #fff; font-weight: 600; }
.hero-card__meta span { font-size: 12.5px; color: rgba(255, 255, 255, 0.65); }

/* Written against .btn--pill, which is defined later and would otherwise win
   and paint this blue on top of the artwork. */
.hero-card__view.btn--pill {
	margin-left: auto;
	background: rgba(255, 255, 255, 0.22);
	color: #fff;
	border-color: transparent;
}

.hero-card__media:hover .hero-card__view.btn--pill {
	background: var(--accent);
	color: #fff;
}

.hero-card--large .hero-card__title { font-size: 36px; }
.hero-card--large .hero-card__media { min-height: 440px; }

/* -- app icon -------------------------------------------------------------- */

.app-icon {
	flex: none;
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	border-radius: 12px;
	overflow: hidden;
	font-size: 14px;
	font-weight: 600;
	letter-spacing: -0.01em;
	color: #fff;
	background: linear-gradient(155deg, hsl(var(--hue) 68% 58%), hsl(calc(var(--hue) + 35) 68% 42%));
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
}

.app-icon img { width: 100%; height: 100%; object-fit: cover; }
.app-icon--sm { width: 36px; height: 36px; border-radius: 10px; font-size: 12px; }
.app-icon--md { width: 48px; height: 48px; border-radius: 13px; font-size: 15px; }

.btn--pill {
	border-radius: var(--radius-pill);
	background: var(--accent-quiet);
	border-color: transparent;
	color: var(--accent);
	font-weight: 600;
	padding: 7px 17px;
}

.btn--pill:hover {
	background: var(--accent);
	border-color: transparent;
	color: #fff;
}

/* -- rails ----------------------------------------------------------------- */

.rail { margin-top: 14px; }

.rail__head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 14px;
	padding-top: 26px;
	border-top: 1px solid var(--stroke-faint);
}

.rail:first-of-type .rail__head { padding-top: 34px; }

.rail__controls {
	display: flex;
	align-items: center;
	gap: 8px;
}

.rail__link {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	font-size: 13.5px;
	font-weight: 500;
	color: var(--accent);
	white-space: nowrap;
}

.rail__link::after {
	content: "\203A";
	font-size: 16px;
	line-height: 1;
	transition: transform var(--fast) var(--ease);
}

.rail__link:hover { opacity: 1; }
.rail__link:hover::after { transform: translateX(2px); }

.rail__arrow {
	display: grid;
	place-items: center;
	width: 28px;
	height: 28px;
	padding: 0;
	border-radius: 50%;
	border: 1px solid var(--stroke);
	background: var(--bg-elevated);
	color: var(--text-secondary);
	font-size: 16px;
	line-height: 1;
	cursor: pointer;
	transition: background var(--fast) var(--ease), color var(--fast) var(--ease), opacity var(--fast) var(--ease);
}

.rail__arrow:hover { background: var(--bg-hover); color: var(--text); }
.rail__arrow[disabled] { opacity: 0.3; cursor: default; }
.rail__arrow:not([data-ready]) { display: none; }

.rail__track {
	display: flex;
	gap: 16px;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	scroll-behavior: smooth;
	scrollbar-width: none;
	padding-bottom: 4px;
}

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

.rail__track--list {
	display: grid;
	grid-auto-flow: column;
	grid-template-rows: repeat(3, auto);
	/* Fills the row when a few apps fit, scrolls once they do not. */
	grid-auto-columns: minmax(260px, 1fr);
	gap: 4px 28px;
}

.rail-card {
	flex: 0 0 clamp(210px, 23vw, 268px);
	scroll-snap-align: start;
	display: flex;
	flex-direction: column;
	gap: 10px;
	color: inherit;
	border-radius: var(--radius-lg);
	transition: transform var(--medium) var(--ease);
}

.rail-card:hover { opacity: 1; }

.rail-card__cover {
	position: relative;
	display: block;
	aspect-ratio: 16 / 10;
	border-radius: var(--radius-lg);
	overflow: hidden;
	background: linear-gradient(155deg, hsl(var(--hue) 55% 30%), hsl(calc(var(--hue) + 40) 55% 16%));
}

.rail-card__cover::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb, 120, 120, 128), 0.32);
	pointer-events: none;
}

.rail-card__cover img { width: 100%; height: 100%; object-fit: cover; }

.rail-card__monogram {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	font-size: 26px;
	font-weight: 600;
	color: rgba(255, 255, 255, 0.9);
}

.rail-card__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.rail-card__eyebrow {
	font-size: 11.5px;
	font-weight: 500;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--text-tertiary);
}

.rail-card__title {
	font-size: 14px;
	font-weight: 600;
	letter-spacing: -0.01em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.rail-card__summary {
	font-size: 12.5px;
	color: var(--text-secondary);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* -- ranked list ----------------------------------------------------------- */

.list-row {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 8px 10px;
	border-radius: var(--radius);
	color: inherit;
	transition: background var(--fast) var(--ease);
}

.list-row + .list-row { box-shadow: 0 -1px 0 var(--stroke-faint); }
.list-row:hover { opacity: 1; background: var(--bg-hover); }

.list-row__rank {
	width: 16px;
	text-align: center;
	font-size: 13px;
	color: var(--text-tertiary);
	font-variant-numeric: tabular-nums;
}

.list-row__text {
	display: flex;
	flex-direction: column;
	min-width: 0;
	line-height: 1.35;
}

.list-row__text strong {
	font-size: 13.5px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.list-row__text span { font-size: 12px; color: var(--text-tertiary); }
.list-row .btn { margin-left: auto; }

/* -- category tiles -------------------------------------------------------- */

.category-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
	gap: 12px;
}

.category-tile {
	display: flex;
	flex-direction: column;
	gap: 2px;
	padding: 16px 18px;
	border-radius: var(--radius-lg);
	border: 1px solid var(--stroke);
	background: linear-gradient(150deg, hsl(var(--hue) 78% 92%), var(--bg-elevated) 72%);
	color: var(--text);
	transition: transform var(--medium) var(--ease), border-color var(--medium) var(--ease);
}

.category-tile:hover { opacity: 1; border-color: var(--stroke-strong); }
.category-tile__name { font-size: 14px; font-weight: 600; letter-spacing: -0.01em; }
.category-tile__count { font-size: 12px; color: var(--text-tertiary); }

@media (prefers-color-scheme: dark) {
	.category-tile { background: linear-gradient(150deg, hsl(var(--hue) 42% 18%), var(--bg-elevated) 70%); }
}

/* -- footer ---------------------------------------------------------------- */

.site-footer { padding: 0; }

.footer-columns {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: 28px;
	padding: 40px 0 30px;
}

.footer-col h3 {
	margin-bottom: 12px;
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--text-tertiary);
}

.footer-col a,
.footer-col .footer-version {
	display: block;
	padding: 4px 0;
	font-size: 13px;
	color: var(--text-secondary);
}

.footer-col a:hover { opacity: 1; color: var(--text); }
.footer-col .footer-version { color: var(--text-tertiary); }

.footer-bottom {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 18px;
	padding: 22px 0 32px;
	border-top: 1px solid var(--stroke-faint);
}

.footer-brand {
	display: flex;
	align-items: center;
	gap: 10px;
}

.footer-brand .mark {
	display: grid;
	place-items: center;
	width: 30px;
	height: 30px;
	border-radius: 9px;
	background: linear-gradient(160deg, var(--accent), #6a5cff);
	color: #fff;
	font-size: 13px;
	font-weight: 700;
}

.footer-brand div { display: flex; flex-direction: column; line-height: 1.4; }
.footer-brand strong { font-size: 13.5px; color: var(--text); }
.footer-brand span { font-size: 12.5px; color: var(--text-tertiary); }

.footer-legal {
	margin: 0;
	max-width: 56ch;
	font-size: 12px;
	line-height: 1.5;
	color: var(--text-tertiary);
}

/* -- store responsive ------------------------------------------------------ */

@media (max-width: 980px) {
	/* The sidebar lies down into a strip above the page. */
	.store-layout { grid-template-columns: minmax(0, 1fr); gap: 18px; }

	.store-sidebar {
		position: static;
		gap: 10px;
	}

	.store-nav__label { display: none; }

	.store-nav {
		flex-direction: row;
		gap: 4px;
		overflow-x: auto;
		scrollbar-width: none;
		padding-bottom: 2px;
	}

	.store-nav::-webkit-scrollbar { display: none; }
	.store-nav a { white-space: nowrap; flex: none; border-radius: var(--radius-pill); }
	.store-nav__count { margin-left: 4px; }

	.hero-grid { grid-template-columns: minmax(0, 1fr); }
	.hero-card, .hero-card--large { min-height: 340px; }
	.hero-card--large .hero-card__title { font-size: 26px; }
	.rail__track--list { grid-auto-columns: min(84vw, 340px); }
}

/* ==========================================================================
   App detail: hero, key figures, screenshots
   ========================================================================== */

.app-hero {
	position: relative;
	display: flex;
	align-items: flex-end;
	min-height: 280px;
	border-radius: var(--radius-xl);
	border: 1px solid var(--stroke);
	overflow: hidden;
	background: linear-gradient(150deg, hsl(var(--hue) 58% 30%), hsl(calc(var(--hue) + 40) 58% 15%));
}

/* The banner, blurred, doubles as the backdrop - the app brings its own colour. */
.app-hero__backdrop {
	position: absolute;
	inset: -60px;
	background-size: cover;
	background-position: center;
	filter: blur(46px) saturate(1.5) brightness(1.2);
	transform: scale(1.15);
	/* The hue gradient underneath keeps dark banners from turning the header
	   into a black rectangle. */
	opacity: 0.88;
}

.app-hero__veil {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0.22) 0%, rgba(0, 0, 0, 0.58) 100%);
}

.app-hero__body {
	position: relative;
	display: flex;
	align-items: flex-end;
	gap: 26px;
	width: 100%;
	padding: 32px;
}

.app-hero__text { min-width: 0; }
.app-hero__text h1 { font-size: 38px; color: #fff; letter-spacing: -0.025em; }

.app-hero__summary {
	margin: 8px 0 0;
	font-size: 16px;
	color: rgba(255, 255, 255, 0.88);
	max-width: 60ch;
}

.app-hero__meta {
	margin: 6px 0 0;
	font-size: 13px;
	color: rgba(255, 255, 255, 0.66);
}

.app-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin-top: 18px;
}

.app-icon--xl {
	width: 148px;
	height: 148px;
	border-radius: 33px;
	font-size: 44px;
	box-shadow: 0 14px 34px rgba(0, 0, 0, 0.38);
}

.btn--glass {
	background: rgba(255, 255, 255, 0.16);
	border-color: rgba(255, 255, 255, 0.3);
	color: #fff;
}

.btn--glass:hover {
	background: rgba(255, 255, 255, 0.26);
	border-color: rgba(255, 255, 255, 0.4);
}

/* -- key figures ----------------------------------------------------------- */

.stat-strip {
	display: grid;
	grid-template-columns: repeat(6, minmax(0, 1fr));
	margin-top: 24px;
	padding: 18px 0;
	border-top: 1px solid var(--stroke-faint);
	border-bottom: 1px solid var(--stroke-faint);
}

.stat-strip__item {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 3px;
	padding: 2px 12px;
	text-align: center;
}

.stat-strip__item + .stat-strip__item { border-left: 1px solid var(--stroke-faint); }

.stat-strip__label {
	font-size: 10.5px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-tertiary);
}

.stat-strip__value {
	font-size: 22px;
	font-weight: 600;
	letter-spacing: -0.02em;
	font-variant-numeric: tabular-nums;
}

.stat-strip__value--small { font-size: 18px; }
.stat-strip__caption { font-size: 11.5px; color: var(--text-tertiary); }

/* -- screenshots ----------------------------------------------------------- */

.shot-rail { gap: 14px; }

.shot-frame {
	position: relative;
	flex: 0 0 clamp(280px, 38vw, 460px);
	aspect-ratio: 16 / 9;
	display: block;
	padding: 0;
	overflow: hidden;
	border: none;
	border-radius: var(--radius-lg);
	/* Portrait shots keep their shape; the frame supplies the side bars. */
	background: var(--shot-matte);
	cursor: zoom-in;
	scroll-snap-align: start;
	transition: transform var(--medium) var(--ease), border-color var(--medium) var(--ease);
}

.shot-frame::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb, 120, 120, 128), 0.32);
	pointer-events: none;
}

.shot-frame:hover { opacity: 1; }

/* Absolute, so a tall screenshot is fitted into the frame instead of
   stretching it - which is what leaves the bars at the sides. */
.shot-frame img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.lightbox {
	max-width: none;
	/* fit-content, not auto: a modal dialog is fixed with inset 0, so an auto
	   width stretches to the viewport and margin auto can no longer centre it. */
	width: fit-content;
	height: fit-content;
	padding: 0;
	border: none;
	background: transparent;
	overflow: visible;
}

.lightbox::backdrop { background: rgba(0, 0, 0, 0.86); }

.lightbox img {
	display: block;
	max-width: 94vw;
	max-height: 88vh;
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-lg);
}

.lightbox__close {
	position: fixed;
	top: 18px;
	right: 22px;
	width: 36px;
	height: 36px;
	display: grid;
	place-items: center;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.25);
	background: rgba(0, 0, 0, 0.5);
	color: #fff;
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
}

.lightbox__close:hover { background: rgba(0, 0, 0, 0.75); }

/* -- artwork fields in the upload form ------------------------------------- */

.artwork-grid {
	display: grid;
	grid-template-columns: 2fr 1fr;
	gap: 18px;
}

.artwork-preview {
	margin-top: 10px;
	width: 100%;
	height: auto;
	border-radius: var(--radius);
	border: 1px solid var(--stroke);
}

.artwork-preview--icon {
	width: 88px;
	height: 88px;
	border-radius: 20px;
	object-fit: cover;
}

/* A logo is its own shape, and its transparency is the point: no frame. */
.artwork-preview--logo {
	width: auto;
	max-width: 220px;
	border: none;
	border-radius: 0;
}

.shot-manager {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
	gap: 10px;
	margin-top: 12px;
}

.shot-manager__item {
	display: block;
	overflow: hidden;
	border: 1px solid var(--stroke);
	border-radius: var(--radius);
	background: var(--bg-sunken);
	transition: border-color var(--fast) var(--ease), opacity var(--fast) var(--ease);
}

.shot-manager__item img {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	object-fit: contain;
	background: var(--shot-matte);
}

.shot-manager__remove {
	display: flex;
	align-items: center;
	gap: 7px;
	padding: 7px 9px;
	font-size: 12px;
	color: var(--text-secondary);
	background: var(--bg-elevated);
	border-top: 1px solid var(--stroke-faint);
	cursor: pointer;
}

.shot-manager__remove input { width: auto; accent-color: var(--danger); }
.shot-manager__item:has(input:checked) { opacity: 0.55; border-color: var(--danger); }

/* An id is short: the field is too, so what follows it stays on the same row. */
.input--narrow { max-width: 260px; }

/* -- decal ids -------------------------------------------------------------- */

/*
	Studio will not fetch a picture over HTTP, so every image here also carries
	the id of the same picture on Roblox. The field sits directly under the
	image it belongs to, small enough to read as a caption rather than as
	another thing to fill in.
*/

.asset-field {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 8px;
}

/* A tile is narrow: the label goes above the field, not beside it. */
.shot-manager__item .asset-field {
	flex-direction: column;
	align-items: stretch;
	gap: 3px;
	margin: 0;
	padding: 8px 9px 0;
}

.asset-field__label {
	flex: none;
	font-size: 11px;
	letter-spacing: -0.01em;
	color: var(--text-tertiary);
	white-space: nowrap;
}

.asset-field input[type="text"] {
	min-width: 0;
	padding: 6px 9px;
	font-family: var(--font-mono);
	font-size: 12px;
	border-radius: var(--radius-sm);
}

@media (max-width: 900px) {
	.app-hero__body { flex-direction: column; align-items: flex-start; gap: 18px; padding: 24px; }
	.app-hero__text h1 { font-size: 28px; }
	.app-icon--xl { width: 104px; height: 104px; border-radius: 24px; font-size: 32px; }
	.stat-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px 0; }
	.stat-strip__item:nth-child(3n + 1) { border-left: none; }
	.artwork-grid { grid-template-columns: minmax(0, 1fr); }
}

/* -- featured carousel ------------------------------------------------------ */

.hero-carousel { position: relative; }

.hero-carousel__track {
	display: flex;
	gap: 18px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	scrollbar-width: none;
}

.hero-carousel__track::-webkit-scrollbar { display: none; }

.hero-carousel__track .hero-card {
	flex: 0 0 100%;
	scroll-snap-align: center;
	min-height: 440px;
}

.hero-carousel__track .hero-card__title { font-size: 34px; }

.hero-carousel__dots {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 14px;
	z-index: 3;
	display: flex;
	justify-content: center;
	gap: 7px;
}

.hero-carousel__dot {
	width: 7px;
	height: 7px;
	padding: 0;
	border: none;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.35);
	cursor: pointer;
	transition: background var(--fast) var(--ease), transform var(--fast) var(--ease);
}

/* Shown on hover, over the artwork, the way the store does it - the dots stay
   for touch, where there is no hover to reveal anything. */
.hero-carousel__arrow {
	position: absolute;
	top: 50%;
	z-index: 4;
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	margin-top: -20px;
	padding: 0 0 2px;
	border: none;
	border-radius: 50%;
	background: rgba(0, 0, 0, 0.45);
	color: #fff;
	font-size: 22px;
	line-height: 1;
	cursor: pointer;
	opacity: 0;
	transition: opacity var(--fast) var(--ease), background var(--fast) var(--ease);
}

.hero-carousel__arrow--prev { left: 14px; }
.hero-carousel__arrow--next { right: 14px; }

.hero-carousel:hover .hero-carousel__arrow,
.hero-carousel__arrow:focus-visible { opacity: 1; }

.hero-carousel__arrow:hover { background: rgba(0, 0, 0, 0.68); }
.hero-carousel__arrow[disabled] { opacity: 0; pointer-events: none; }

@media (hover: none) {
	.hero-carousel__arrow { display: none; }
}

.hero-carousel__dot:hover { background: rgba(255, 255, 255, 0.6); }

.hero-carousel__dot.is-active {
	background: #fff;
	transform: scale(1.25);
}

/* -- mobile navigation ------------------------------------------------------ */

.nav-toggle {
	display: none;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	padding: 0;
	border-radius: var(--radius-sm);
	border: 1px solid var(--stroke);
	background: var(--bg-elevated);
	color: var(--text);
	cursor: pointer;
}

.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
	display: block;
	width: 16px;
	height: 1.5px;
	border-radius: 2px;
	background: currentColor;
	transition: transform var(--medium) var(--ease), opacity var(--fast) var(--ease);
}

.nav-toggle__bars::before,
.nav-toggle__bars::after {
	content: "";
	position: absolute;
}

.nav-toggle__bars::before { transform: translateY(-5px); }
.nav-toggle__bars::after { transform: translateY(5px); }

.nav-toggle[aria-expanded="true"] .nav-toggle__bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before { transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after { transform: rotate(-45deg); }

@media (max-width: 980px) {
	.hero-carousel__track .hero-card { min-height: 340px; }
	.hero-carousel__track .hero-card__title { font-size: 25px; }
}

@media (max-width: 760px) {
	.nav-toggle { display: inline-flex; position: relative; }

	/* The header keeps only the brand and the menu button; everything else,
	   search included, moves into the sheet the button opens. */
	.site-header .nav,
	.site-header .header-search,
	.site-header .header-actions { display: none; }

	.site-header.is-open .nav,
	.site-header.is-open .header-search,
	.site-header.is-open .header-actions {
		display: flex;
		flex: 0 0 100%;
		flex-wrap: wrap;
		padding-top: 8px;
	}

	.site-header.is-open .header-search { width: 100%; margin: 0; order: 0; }
	.site-header.is-open .header-search input[type="search"] { height: 38px; }

	.site-header.is-open .nav { flex-direction: column; align-items: stretch; gap: 2px; }
	.site-header.is-open .nav a { padding: 10px 12px; border-radius: var(--radius-sm); }
	.site-header.is-open .nav a:hover { background: var(--bg-hover); }

	.site-header.is-open .header-actions {
		border-top: 1px solid var(--stroke-faint);
		margin-top: 8px;
		gap: 8px;
	}

	.site-header.is-open .header-actions > * { flex: 1 1 auto; }
	.site-header.is-open .header-actions .btn { width: 100%; justify-content: center; }
	.site-header.is-open .header-actions form { flex: 1 1 100%; }

	.site-header .container { flex-wrap: wrap; row-gap: 0; }
	.brand { margin-right: auto; }

	/* The sheet lists search, then the sections, then the account actions. */
	.site-header.is-open .nav { order: 1; }
	.site-header.is-open .header-actions { order: 2; }

	/* The account menu is already a menu; inside the sheet it just lists. */
	.site-header.is-open .menu { width: 100%; }
	.site-header.is-open .menu > summary { justify-content: flex-start; }
	.site-header.is-open .menu__panel { position: static; box-shadow: none; margin-top: 6px; }

	.hero-carousel__track .hero-card { min-height: 300px; }
	.site-header.is-open .header-actions .btn--ghost { justify-content: flex-start; }

	/* The header's own search covers it at this width, and the browse page
	   brings a search field of its own. */
	.store-sidebar .store-search { display: none; }

	/* The two dropdowns share a row instead of stepping down the page. */
	.search-bar select { flex: 1 1 0; min-width: 0; }
	.search-bar input[type="search"] { flex: 1 1 100%; min-width: 0; }
	.search-bar .btn { flex: 1 1 100%; justify-content: center; }

	/* Heading first, count underneath - side by side they squeeze each other
	   against the edges. */
	.store-head {
		flex-direction: column;
		align-items: flex-start;
		gap: 2px;
		margin-bottom: 18px;
	}

	.store-head h1 { font-size: 26px; }

	/* Rails are scrolled with a finger here, so the arrows only cost room. */
	.rail__head { padding-top: 22px; gap: 12px; }
	.rail:first-of-type .rail__head { padding-top: 26px; }
	.rail__head h2 { font-size: 19px; }
	.rail__arrow { display: none; }
}

@media print {
	.site-header, .site-footer, .btn, .flash-stack { display: none !important; }
}

/* -- staggered entrances --------------------------------------------------- */

/* Content settles in instead of appearing all at once. Deliberately limited to
   cards and stat tiles: form fields inside a grid should just be there. Kept to
   the first handful of items, after which the delay would be noticeable rather
   than pleasant. */
@media (prefers-reduced-motion: no-preference) {
	.app-card,
	.stat,
	.stagger > * {
		animation: rise-in var(--medium) var(--ease) both;
	}

	.grid > .app-card:nth-child(1), .grid > .stat:nth-child(1), .stagger > *:nth-child(1) { animation-delay: 0ms; }
	.grid > .app-card:nth-child(2), .grid > .stat:nth-child(2), .stagger > *:nth-child(2) { animation-delay: 35ms; }
	.grid > .app-card:nth-child(3), .grid > .stat:nth-child(3), .stagger > *:nth-child(3) { animation-delay: 70ms; }
	.grid > .app-card:nth-child(4), .grid > .stat:nth-child(4), .stagger > *:nth-child(4) { animation-delay: 105ms; }
	.grid > .app-card:nth-child(5), .stagger > *:nth-child(5) { animation-delay: 140ms; }
	.grid > .app-card:nth-child(6), .stagger > *:nth-child(6) { animation-delay: 175ms; }
	.grid > .app-card:nth-child(7), .stagger > *:nth-child(7) { animation-delay: 200ms; }
	.grid > .app-card:nth-child(n + 8), .stagger > *:nth-child(n + 8) { animation-delay: 220ms; }
}

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

/* -- switches -------------------------------------------------------------- */

/* Used where a setting is toggled, not where a form is filled in. */
.switch {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 12px 14px;
	border: 1px solid var(--stroke);
	border-radius: var(--radius);
	background: var(--bg-elevated);
	cursor: pointer;
	transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}

.switch:hover { border-color: var(--stroke-strong); }

.switch input {
	position: absolute;
	opacity: 0;
	width: 0;
	height: 0;
}

.switch__track {
	position: relative;
	flex: none;
	width: 40px;
	height: 24px;
	margin-top: 1px;
	border-radius: var(--radius-pill);
	background: var(--stroke-strong);
	transition: background var(--medium) var(--ease), box-shadow var(--fast) var(--ease);
}

.switch__thumb {
	position: absolute;
	top: 2px;
	left: 2px;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
	transition: transform var(--medium) var(--ease);
}

.switch input:checked + .switch__track {
	background: var(--accent);
}

.switch input:checked + .switch__track .switch__thumb {
	transform: translateX(16px);
}

.switch input:focus-visible + .switch__track {
	box-shadow: 0 0 0 3.5px var(--accent-quiet);
}

.switch:active .switch__thumb { width: 23px; }

.switch__text { font-size: 13.5px; }
.switch__text .hint { display: block; color: var(--text-tertiary); font-size: 12.5px; }

/* -- small feedback -------------------------------------------------------- */

.btn.is-done {
	animation: pulse var(--medium) var(--ease);
	color: var(--positive);
}

@keyframes pulse {
	0% { transform: scale(1); }
	45% { transform: scale(1.06); }
	100% { transform: scale(1); }
}

/* Chart bars grow out of the baseline on first paint. */
@media (prefers-reduced-motion: no-preference) {
	.chart__bar {
		transform-origin: bottom;
		animation: grow-up 420ms var(--ease) both;
	}

	.chart__bar:nth-child(2n) { animation-delay: 25ms; }
	.chart__bar:nth-child(3n) { animation-delay: 45ms; }
}

@keyframes grow-up {
	from { transform: scaleY(0); opacity: 0.4; }
	to { transform: scaleY(1); opacity: 1; }
}

/* The instance tree opens and closes instead of snapping. */
.tree ul {
	overflow: hidden;
}

.tree ul.is-collapsing {
	animation: collapse 160ms var(--ease) forwards;
}

.tree ul.is-expanding {
	animation: expand 180ms var(--ease);
}

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

@keyframes collapse {
	from { opacity: 1; }
	to { opacity: 0; }
}

/* -- typography polish ----------------------------------------------------- */

h1, h2, h3, .hero p, .empty h3 {
	text-wrap: balance;
}

.hero { max-width: 560px; }
.hero p { max-width: 46ch; }

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}
}
