/* ── PT Mono for all headings ── */
h1,
h2,
h3,
h4,
h5,
h6 {
	font-family: 'PT Mono', monospace;
}

/* ── Type scale ──
   The scale is a token, not a hard-coded size: every theme is expected to
   override these to express its own voice (Bold goes enormous and tight,
   Win95 small and system-sized, Vaporwave airy). Display steps are fluid so
   a 4.5rem headline never overflows a phone, and the steps are deliberately
   far apart so hierarchy survives any family swap. ── */
:root {
	--t-h1: clamp(2.25rem, 1.35rem + 4.2vw, 4rem);
	--t-h2: clamp(1.55rem, 1.2rem + 1.7vw, 2.25rem);
	--t-h3: clamp(1.1rem, 1rem + 0.5vw, 1.35rem);
	--t-body: 1rem;
	--t-sm: 0.875rem;
	--t-xs: 0.75rem;
	--t-2xs: 0.6875rem;

	--t-lh-display: 1.06;
	--t-lh-heading: 1.2;
	--t-lh-body: 1.6;
	--t-track-display: -0.02em;
	--t-track-heading: -0.01em;

	/* ── Radius scale ──
	   Four steps, one pill and one circle — the same "token, not constant"
	   rule as the type scale, so a theme changes its corner language by
	   redefining six values instead of hunting per-component overrides.
	   Brutalist and Win95 zero the steps; Bold and Vaporwave retune them. ── */
	--r-xs: 0.3rem;
	--r-sm: 0.5rem;
	--r-md: 0.75rem;
	--r-lg: 1rem;
	--r-pill: 999px;
	--r-round: 50%;

	/* Accent colours are picked as FILLS. Painted as small text they fail
	   contrast badly (measured 1.03:1–4.3:1 across the themes), so every
	   accent used as TEXT is first blended toward the theme's own text
	   colour — which is by definition readable on that theme's surfaces.
	   One formula, correct in light and dark, hue preserved. Themes may
	   retune the ratio; lower = closer to the text colour = safer. */
	--ink-mix: 34%;
	--ink-l: 0.38;
}

:root[data-theme='dark'],
html[data-theme='dark'] {
	--ink-l: 0.82;
}
@media (prefers-color-scheme: dark) {
	:root:not([data-theme]) {
		--ink-l: 0.82;
	}
}

h1 {
	font-size: var(--t-h1);
	line-height: var(--t-lh-display);
	letter-spacing: var(--t-track-display);
	text-wrap: balance;
}
h2 {
	font-size: var(--t-h2);
	line-height: var(--t-lh-heading);
	letter-spacing: var(--t-track-heading);
	text-wrap: balance;
}
h3 {
	font-size: var(--t-h3);
	line-height: var(--t-lh-heading);
	text-wrap: balance;
}

/* ── Tailwind tokens — resolved at runtime from CSS vars ── */
@theme inline {
	--font-sans: 'IBM Plex Sans', system-ui, sans-serif;

	--color-c-bg: var(--c-bg);
	--color-c-surface: var(--c-surface);
	--color-c-border: var(--c-border);
	--color-c-muted: var(--c-muted);
	--color-c-text: var(--c-text);
	--color-c-text-sub: var(--c-text-sub);
	--color-c-nav-bg: var(--c-nav-bg);
	--color-c-accent: var(--c-accent);
	--color-c-accent-2: var(--c-accent-2);
	--color-c-accent-3: var(--c-accent-3);

	--color-p-accent-1: var(--p-accent-1);
	--color-p-accent-2: var(--p-accent-2);
	--color-p-accent-3: var(--p-accent-3);
	--color-p-accent-4: var(--p-accent-4);
	--color-p-accent-5: var(--p-accent-5);
	--color-p-accent-6: var(--p-accent-6);
	--color-p-accent-7: var(--p-accent-7);
	--color-p-accent-8: var(--p-accent-8);
}

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

body {
	background-color: var(--c-bg);
	color: var(--c-text);
	font-family: 'IBM Plex Sans', system-ui, sans-serif;
	line-height: var(--t-lh-body);
	-webkit-font-smoothing: antialiased;
	transition:
		background-color 0.3s ease,
		color 0.3s ease;
}

/* ── Animations ── */
@keyframes fade-up {
	from {
		opacity: 0;
		transform: translateY(24px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

.animate-fade-up {
	animation: fade-up 0.7s ease forwards;
}

.delay-100 {
	animation-delay: 0.1s;
	opacity: 0;
}
.delay-200 {
	animation-delay: 0.2s;
	opacity: 0;
}
.delay-300 {
	animation-delay: 0.3s;
	opacity: 0;
}
.delay-400 {
	animation-delay: 0.4s;
	opacity: 0;
}
.delay-500 {
	animation-delay: 0.5s;
	opacity: 0;
}
.delay-600 {
	animation-delay: 0.6s;
	opacity: 0;
}

/* Reduced motion: skip the entrance entirely. The .delay-* classes hold
   content at opacity:0 until the animation paints it, so these MUST restore
   opacity — cancelling only the animation would leave the content invisible. */
@media (prefers-reduced-motion: reduce) {
	.animate-fade-up {
		animation: none;
		opacity: 1;
		transform: none;
	}

	.delay-100,
	.delay-200,
	.delay-300,
	.delay-400,
	.delay-500,
	.delay-600 {
		animation-delay: 0s;
		opacity: 1;
	}
}

.section-label {
	font-size: var(--t-2xs);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	font-weight: 600;
}

/* ── Gradient headline (background-clip not expressible in Tailwind) ── */
.gradient-text {
	background: linear-gradient(
		120deg,
		var(--c-grad-h1-from) 0%,
		var(--c-grad-h1-mid) 50%,
		var(--c-grad-h1-to) 100%
	);
	-webkit-background-clip: text;
	-webkit-text-fill-color: transparent;
	background-clip: text;
}

/* ── Dot grid (radial-gradient bg-image, no Tailwind equivalent) ── */
.dot-grid {
	background-image: radial-gradient(circle, var(--c-dot) 1px, transparent 1px);
	background-size: 28px 28px;
}

/* ── Tag pills ── */
.tag {
	font-size: var(--t-2xs);
	letter-spacing: 0.15em;
	text-transform: uppercase;
	padding: 0.2rem 0.65rem;
	border-radius: var(--r-pill);
	border-width: 1px;
	border-style: solid;
	/* No blanket opacity here: the .tag-* ink below is computed to clear AA at
	   full strength, and fading the whole pill would blend that ink back toward
	   the page and undo it. Softness belongs in the colour, not in alpha. */
}

/* ── Cards ── */
.card {
	border: 1px solid var(--c-border);
	background: var(--c-surface);
	transition:
		transform 0.25s ease,
		box-shadow 0.25s ease;
}

.card:hover {
	transform: translateY(-2px);
	box-shadow: 0 8px 32px -8px rgba(0, 0, 0, 0.12);
}

html[data-theme='dark'] .card:hover {
	box-shadow: 0 8px 32px -8px rgba(0, 0, 0, 0.5);
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme]) .card:hover {
		box-shadow: 0 8px 32px -8px rgba(0, 0, 0, 0.5);
	}
}

/* ── Link cards ── */
.link-card {
	border: 1px solid var(--c-border);
	background: var(--c-surface);
	transition:
		border-color 0.25s ease,
		transform 0.25s ease,
		box-shadow 0.25s ease;
}

.link-card:hover {
	transform: translateY(-2px);
	box-shadow: 0 8px 24px -8px rgba(0, 0, 0, 0.1);
}

/* ── Font size scale ── */
html[data-font-size='s'] {
	font-size: 14px;
}
html[data-font-size='m'],
html:not([data-font-size]) {
	font-size: 16px;
}
html[data-font-size='l'] {
	font-size: 18px;
}

/* ── On mobile, always use 'm' (16px) regardless of setting ── */
@media (max-width: 640px) {
	html[data-font-size='s'],
	html[data-font-size='l'] {
		font-size: 16px;
	}
}

/* ══ Button system ══════════════════════════════════════════ */

/* Form-associated elements do NOT inherit font from their ancestors — the UA
   sheet gives <button>/<input>/<select> their own `font: 400 13.333px Arial`.
   Without this, a `<button class="btn-primary">` renders in Arial at an
   off-scale size in every theme, while the same class on an `<a>` renders
   correctly. Reset the whole family once so the theme's voice actually reaches
   its controls, and so the `em`-based margins below measure against the
   theme's own size. */
.btn-primary,
.btn-outlined,
.btn-ghost,
.btn-icon,
.theme-toggle,
.checkbox,
.radio,
.switch {
	font-family: inherit;
}

/* The text buttons name their own step from the scale; these carry no text, so
   they take the inherited size — which is also what their `em`-based margins
   measure against (at the UA's 13.333px the gap next to a checkbox label came
   out ~17% tight). */
.btn-icon,
.theme-toggle,
.checkbox,
.radio,
.switch {
	font-size: inherit;
}

/* Primary — filled accent */
.btn-primary {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.375rem;
	padding: 0.625rem 1.5rem;
	border-radius: var(--r-pill);
	border: 2px solid transparent;
	background: var(--c-accent);
	/* Never --c-bg: a bright accent (cyan, orange) needs a foreground picked
	   for contrast against the accent itself, not against the page. */
	color: var(--c-on-accent);
	font-size: var(--t-sm);
	font-weight: 500;
	letter-spacing: 0.025em;
	text-decoration: none;
	cursor: pointer;
	transition:
		opacity 0.2s ease,
		transform 0.2s ease,
		box-shadow 0.2s ease;
}

.btn-primary:hover {
	opacity: 0.88;
}

/* Outlined — border, bg matches page */
.btn-outlined {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.375rem;
	padding: 0.625rem 1.5rem;
	border-radius: var(--r-pill);
	border: 1px solid var(--c-border);
	background: var(--c-bg);
	color: var(--c-text);
	font-size: var(--t-sm);
	font-weight: 500;
	letter-spacing: 0.025em;
	text-decoration: none;
	cursor: pointer;
	transition:
		border-color 0.2s ease,
		color 0.2s ease,
		transform 0.2s ease,
		box-shadow 0.2s ease;
}

.btn-outlined:hover {
	border-color: var(--c-accent);
	color: var(--c-accent);
}

/* Small size modifier */
.btn-sm {
	padding: 0.375rem 1rem;
	font-size: var(--t-xs);
}

/* Ghost — no border, no bg */
.btn-ghost {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.375rem;
	padding: 0;
	background: transparent;
	border: none;
	color: var(--c-muted);
	font-size: var(--t-sm);
	font-weight: 500;
	text-decoration: none;
	cursor: pointer;
	transition:
		color 0.2s ease,
		transform 0.2s ease,
		box-shadow 0.2s ease;
}

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

/* Icon button (square aspect, no fixed padding) */
.btn-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--c-border);
	background: var(--c-surface);
	color: var(--c-text-sub);
	text-decoration: none;
	cursor: pointer;
	transition:
		border-color 0.2s ease,
		color 0.2s ease,
		transform 0.2s ease,
		box-shadow 0.2s ease;
}

.btn-icon:hover {
	border-color: var(--c-accent);
	color: var(--c-accent);
}

/* Theme toggle button */
.theme-toggle {
	width: 2rem;
	height: 2rem;
	border-radius: var(--r-round);
	border: 1px solid var(--c-border);
	background: var(--c-surface);
	color: var(--c-text-sub);
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	transition:
		border-color 0.2s ease,
		color 0.2s ease;
}

.theme-toggle:hover {
	border-color: var(--c-accent);
	color: var(--c-accent);
}

/* ════════════════════════════════════════════════════════════
   STANDALONE HELPERS
   Layered on top of the styled classes above so every element
   can be built from classes alone — no inline `style` and no
   utility framework required. All additive: existing classes
   keep their behaviour, these just fill in structure + variants.
   ════════════════════════════════════════════════════════════ */

/* ── Text colour helpers ── */
.text-accent {
	color: color-mix(in srgb, var(--c-accent) var(--ink-mix), var(--c-text));
}
.text-accent-2 {
	color: var(--c-accent-2);
}
.text-accent-3 {
	color: var(--c-accent-3);
}
.text-sub {
	color: var(--c-text-sub);
}
.text-muted {
	color: var(--c-muted);
}

/* ── Layout helpers ── */
.row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem;
}
.row-mt {
	margin-top: 1.25rem;
}

/* ── Palette accent selector ──
   Sets --card-color, the hook read by .card's edge
   and .link-icon's fill. Add one to a card / link / icon. ── */
.accent-1 {
	--card-color: var(--p-accent-1);
}
.accent-2 {
	--card-color: var(--p-accent-2);
}
.accent-3 {
	--card-color: var(--p-accent-3);
}
.accent-4 {
	--card-color: var(--p-accent-4);
}
.accent-5 {
	--card-color: var(--p-accent-5);
}
.accent-6 {
	--card-color: var(--p-accent-6);
}
.accent-7 {
	--card-color: var(--p-accent-7);
}
.accent-8 {
	--card-color: var(--p-accent-8);
}

/* ── Tag colour variants ──
   Base .tag becomes inline-block (so it can animate) with a
   neutral border; add .tag-<color> to tint it. ── */
.tag {
	display: inline-block;
	border-color: var(--c-border);
}
.tag-accent-1 {
	--slot: var(--p-accent-1);
}
.tag-accent-2 {
	--slot: var(--p-accent-2);
}
.tag-accent-3 {
	--slot: var(--p-accent-3);
}
.tag-accent-4 {
	--slot: var(--p-accent-4);
}
.tag-accent-5 {
	--slot: var(--p-accent-5);
}
.tag-accent-6 {
	--slot: var(--p-accent-6);
}
.tag-accent-7 {
	--slot: var(--p-accent-7);
}
.tag-accent-8 {
	--slot: var(--p-accent-8);
}

/* One ink treatment for every accent slot. Blending an accent toward the
   theme's neutral text colour is contrast-safe but strips chroma — the tags
   go grey. Where relative colour is supported we instead pin only the
   LIGHTNESS (--ink-l) and keep the accent's own chroma and hue, so the tag
   stays unmistakably its colour and still clears AA. The color-mix line is
   the fallback for browsers without relative colour. */
.tag[class*='tag-accent-'] {
	color: color-mix(in srgb, var(--slot) var(--ink-mix), var(--c-text));
	border-color: color-mix(in srgb, var(--slot) 38%, transparent);
	background: color-mix(in srgb, var(--slot) 14%, transparent);
}
@supports (color: oklch(from white l c h)) {
	.tag[class*='tag-accent-'] {
		color: oklch(from var(--slot) var(--ink-l) c h);
	}
	.card .section-label,
	.card .card-subtitle,
	.link-icon {
		color: oklch(from var(--card-color, var(--c-accent)) var(--ink-l) c h);
	}
	.text-accent {
		color: oklch(from var(--c-accent) var(--ink-l) c h);
	}
}


/* ── Card — standalone structure ──
   base.css already styles the surface + accent edge; these add
   the padding/radius and lay out the card's contents. ── */
.card {
	padding: 1.5rem;
	border-radius: var(--r-lg);
	max-width: 22rem;
}
.card .section-label {
	margin: 0 0 0.5rem;
	color: color-mix(in srgb, var(--card-color, var(--c-accent)) var(--ink-mix), var(--c-text));
}
.card h3 {
	margin: 0;
	font-size: var(--t-body);
}
.card .card-subtitle {
	margin: 0.25rem 0 0.75rem;
	font-size: var(--t-sm);
	font-weight: 500;
	color: color-mix(in srgb, var(--card-color, var(--c-accent)) var(--ink-mix), var(--c-text));
}
.card .card-text {
	margin: 0;
	font-size: var(--t-sm);
	/* Leading is part of a theme's voice, not a constant — Win95 runs tight
	   at 1.45, Minimal and Vaporwave open up to 1.7/1.65. */
	line-height: var(--t-lh-body);
	color: var(--c-text-sub);
}

/* ── Link card — standalone structure ── */
.link-card {
	display: flex;
	align-items: center;
	gap: 1.25rem;
	padding: 1.5rem;
	border-radius: var(--r-lg);
	text-decoration: none;
	max-width: 22rem;
}
.link-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 2.75rem;
	height: 2.75rem;
	border-radius: var(--r-md);
	font-weight: 700;
	background: color-mix(in srgb, var(--card-color, var(--c-accent)) 12%, transparent);
	color: color-mix(in srgb, var(--card-color, var(--c-accent)) var(--ink-mix), var(--c-text));
}
.link-body {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
}
.link-card strong {
	color: var(--c-text);
	font-size: var(--t-sm);
}
.link-sub {
	color: var(--c-text-sub);
	font-size: var(--t-xs);
}

/* ── Icon button — default square size ── */
.btn-icon {
	width: 2.25rem;
	height: 2.25rem;
	border-radius: var(--r-sm);
}

/* ── Ambient effect stage ──
   A sized, rounded backdrop for .dot-grid + .halo blobs. ── */
.effect-stage {
	position: relative;
	overflow: hidden;
	height: 11rem;
	border: 1px solid var(--c-border);
	border-radius: var(--r-lg);
}
.effect-caption {
	position: relative;
	margin: 0;
	padding-top: 4.5rem;
	text-align: center;
	color: var(--c-text-sub);
	font-size: var(--t-sm);
}
.halo {
	position: absolute;
	border-radius: var(--r-round);
	filter: blur(48px);
	opacity: 0.32;
	pointer-events: none;
}
.halo-a {
	top: -2rem;
	left: 8%;
	width: 10rem;
	height: 10rem;
}
.halo-b {
	right: 10%;
	bottom: -3rem;
	width: 12rem;
	height: 12rem;
}
.halo-accent-1 {
	background: var(--p-accent-1);
}
.halo-accent-2 {
	background: var(--p-accent-2);
}
.halo-accent-3 {
	background: var(--p-accent-3);
}
.halo-accent-4 {
	background: var(--p-accent-4);
}
.halo-accent-5 {
	background: var(--p-accent-5);
}

/* ══ Form controls ═══════════════════════════════════════════ */

/* ── Field wrapper ── */
.field {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	max-width: 22rem;
}
.field-label {
	font-size: var(--t-sm);
	font-weight: 500;
	color: var(--c-text);
}
.field-hint {
	font-size: var(--t-xs);
	color: var(--c-muted);
}

/* ── Text input / textarea ── */
.input {
	display: block;
	width: 100%;
	padding: 0.625rem 0.875rem;
	border: 1px solid var(--c-border);
	border-radius: var(--r-sm);
	background: var(--c-surface);
	color: var(--c-text);
	font-family: inherit;
	font-size: var(--t-sm);
	line-height: 1.4;
	transition:
		border-color 0.2s ease,
		box-shadow 0.2s ease;
}
textarea.input {
	min-height: 6rem;
	resize: vertical;
}
.input::placeholder {
	color: var(--c-muted);
}
.input:hover {
	border-color: var(--c-muted);
}
.input:focus-visible {
	outline: none;
	border-color: var(--c-accent);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 35%, transparent);
}
.input:disabled {
	opacity: 0.6;
	cursor: not-allowed;
	background: color-mix(in srgb, var(--c-border) 35%, var(--c-surface));
}

/* ── Select — custom chevron drawn from two currentColor gradients ── */
.select {
	appearance: none;
	-webkit-appearance: none;
	-moz-appearance: none;
	display: block;
	width: 100%;
	padding: 0.625rem 2.25rem 0.625rem 0.875rem;
	border: 1px solid var(--c-border);
	border-radius: var(--r-sm);
	background-color: var(--c-surface);
	background-image:
		linear-gradient(45deg, transparent 50%, currentColor 50%),
		linear-gradient(135deg, currentColor 50%, transparent 50%);
	background-position:
		calc(100% - 1.15rem) center,
		calc(100% - 0.85rem) center;
	background-size:
		0.4rem 0.4rem,
		0.4rem 0.4rem;
	background-repeat: no-repeat;
	color: var(--c-text);
	font-family: inherit;
	font-size: var(--t-sm);
	cursor: pointer;
	transition:
		border-color 0.2s ease,
		box-shadow 0.2s ease;
}
.select:hover {
	border-color: var(--c-muted);
}
.select:focus-visible {
	outline: none;
	border-color: var(--c-accent);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 35%, transparent);
}
.select:disabled {
	opacity: 0.6;
	cursor: not-allowed;
	background-color: color-mix(in srgb, var(--c-border) 35%, var(--c-surface));
}

/* ── Checkbox — appearance:none, checkmark drawn with clip-path ── */
.checkbox {
	appearance: none;
	-webkit-appearance: none;
	display: inline-grid;
	place-content: center;
	flex-shrink: 0;
	width: 1.15rem;
	height: 1.15rem;
	margin: 0 0.5em 0 0;
	vertical-align: middle;
	border: 1.5px solid var(--c-border);
	border-radius: var(--r-xs);
	background: var(--c-surface);
	cursor: pointer;
	transition:
		background 0.15s ease,
		border-color 0.15s ease,
		box-shadow 0.15s ease;
}
.checkbox::before {
	content: '';
	width: 0.68rem;
	height: 0.68rem;
	clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
	background: var(--c-on-accent);
	transform: scale(0);
	transition: transform 0.12s ease;
}
.checkbox:checked {
	background: var(--c-accent);
	border-color: var(--c-accent);
}
.checkbox:checked::before {
	transform: scale(1);
}
.checkbox:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 35%, transparent);
}
.checkbox:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

/* ── Radio — appearance:none, dot fill ── */
.radio {
	appearance: none;
	-webkit-appearance: none;
	display: inline-grid;
	place-content: center;
	flex-shrink: 0;
	width: 1.15rem;
	height: 1.15rem;
	margin: 0 0.5em 0 0;
	vertical-align: middle;
	border: 1.5px solid var(--c-border);
	border-radius: var(--r-round);
	background: var(--c-surface);
	cursor: pointer;
	transition:
		border-color 0.15s ease,
		box-shadow 0.15s ease;
}
.radio::before {
	content: '';
	width: 0.55rem;
	height: 0.55rem;
	border-radius: var(--r-round);
	background: var(--c-accent);
	transform: scale(0);
	transition: transform 0.12s ease;
}
.radio:checked {
	border-color: var(--c-accent);
}
.radio:checked::before {
	transform: scale(1);
}
.radio:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 35%, transparent);
}
.radio:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

/* ── Switch — pill track, sliding thumb ── */
.switch {
	appearance: none;
	-webkit-appearance: none;
	position: relative;
	flex-shrink: 0;
	width: 2.75rem;
	height: 1.5rem;
	margin: 0 0.5em 0 0;
	vertical-align: middle;
	border: 1px solid var(--c-border);
	border-radius: var(--r-pill);
	background: var(--c-border);
	cursor: pointer;
	transition:
		background 0.2s ease,
		border-color 0.2s ease,
		box-shadow 0.2s ease;
}
.switch::before {
	content: '';
	position: absolute;
	top: 0.19rem;
	left: 0.2rem;
	width: 1.1rem;
	height: 1.1rem;
	border-radius: var(--r-round);
	background: var(--c-surface);
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
	transition: transform 0.2s ease;
}
.switch:checked {
	background: var(--c-accent);
	border-color: var(--c-accent);
}
.switch:checked::before {
	transform: translateX(1.25rem);
}
.switch:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 35%, transparent);
}
.switch:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

/* ══ Feedback ═════════════════════════════════════════════════ */

/* ── Alert — tinted via color-mix like .tag-* does. Body copy and the
   title stay on --c-text: the vivid --p-* palette is not reliable as a
   TEXT colour (e.g. cyan/yellow on a light surface fall well under 4.5:1),
   so the palette only tints the background/border and marks a left edge,
   never the readable text itself. ── */
.alert {
	padding: 0.875rem 1.1rem;
	border: 1px solid var(--c-border);
	border-radius: var(--r-md);
	background: var(--c-surface);
	color: var(--c-text);
	font-size: var(--t-sm);
	line-height: var(--t-lh-body);
}
.alert > *:first-child {
	margin-top: 0;
}
.alert > *:last-child {
	margin-bottom: 0;
}
.alert-title {
	display: block;
	margin: 0 0 0.2rem;
	font-weight: 600;
	color: var(--c-text);
}
.alert-info {
	background: color-mix(in srgb, var(--p-info) 10%, var(--c-surface));
	border-color: color-mix(in srgb, var(--p-info) 40%, var(--c-border));
}
.alert-success {
	background: color-mix(in srgb, var(--p-success) 10%, var(--c-surface));
	border-color: color-mix(in srgb, var(--p-success) 40%, var(--c-border));
}
.alert-warn {
	background: color-mix(in srgb, var(--p-warn) 12%, var(--c-surface));
	border-color: color-mix(in srgb, var(--p-warn) 45%, var(--c-border));
}
.alert-error {
	background: color-mix(in srgb, var(--p-danger) 10%, var(--c-surface));
	border-color: color-mix(in srgb, var(--p-danger) 40%, var(--c-border));
}

/* ── Badge — solid fill counter/status pill ── */
.badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 1.35rem;
	height: 1.35rem;
	padding: 0 0.45rem;
	border-radius: var(--r-pill);
	background: var(--c-accent);
	color: var(--c-on-accent);
	font-size: var(--t-2xs);
	font-weight: 700;
	line-height: 1;
	white-space: nowrap;
}
/* Palette variants: fg verified at #0a0a0a (not the #111 the spec floated —
   #111 measures 4.42:1 / 4.46:1 on --p-accent-2 / --p-accent-4, just under AA
   4.5:1; #0a0a0a clears 4.5:1 against all 8 palette colours). */
.badge-accent-1 {
	background: var(--p-accent-1);
	color: var(--p-on-accent, #0a0a0a);
}
.badge-accent-2 {
	background: var(--p-accent-2);
	color: var(--p-on-accent, #0a0a0a);
}
.badge-accent-3 {
	background: var(--p-accent-3);
	color: var(--p-on-accent, #0a0a0a);
}
.badge-accent-4 {
	background: var(--p-accent-4);
	color: var(--p-on-accent, #0a0a0a);
}
.badge-accent-5 {
	background: var(--p-accent-5);
	color: var(--p-on-accent, #0a0a0a);
}
.badge-accent-6 {
	background: var(--p-accent-6);
	color: var(--p-on-accent, #0a0a0a);
}
.badge-accent-7 {
	background: var(--p-accent-7);
	color: var(--p-on-accent, #0a0a0a);
}
.badge-accent-8 {
	background: var(--p-accent-8);
	color: var(--p-on-accent, #0a0a0a);
}

/* ── Progress ── */
.progress {
	width: 100%;
	height: 0.5rem;
	border-radius: var(--r-pill);
	background: var(--c-border);
	overflow: hidden;
}
/* The fill is always full width and scaled down to the current value: a
   transform animates on the compositor, where `width` would relayout the
   track on every frame. The track's overflow:hidden supplies the rounded
   cap, so the bar carries no radius of its own to get squashed. */
.progress-bar {
	height: 100%;
	width: 100%;
	background: var(--c-accent);
	transform-origin: left center;
	transform: scaleX(var(--progress, 0));
	transition: transform 0.3s ease;
}
.progress-25 {
	--progress: 0.25;
}
.progress-50 {
	--progress: 0.5;
}
.progress-75 {
	--progress: 0.75;
}
.progress-100 {
	--progress: 1;
}
@media (prefers-reduced-motion: reduce) {
	.progress-bar {
		transition: none;
	}
}

/* ── Skeleton — shimmer placeholder; reduced-motion → static tint ── */
.skeleton {
	position: relative;
	overflow: hidden;
	background: var(--c-border);
	border-radius: var(--r-sm);
}
.skeleton::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(
		90deg,
		transparent,
		color-mix(in srgb, var(--c-surface) 65%, transparent),
		transparent
	);
	transform: translateX(-100%);
	animation: skeleton-shimmer 1.6s ease-in-out infinite;
}
@keyframes skeleton-shimmer {
	100% {
		transform: translateX(100%);
	}
}
.skeleton-text {
	width: 100%;
	height: 1em;
	border-radius: var(--r-xs);
}
.skeleton-circle {
	width: 2.75rem;
	height: 2.75rem;
	border-radius: var(--r-round);
}
.skeleton-rect {
	width: 100%;
	height: 6rem;
}
@media (prefers-reduced-motion: reduce) {
	.skeleton::after {
		animation: none;
		display: none;
	}
}

/* ── Spinner — reduced-motion → static ¾ arc (still visible) ── */
.spinner {
	display: inline-block;
	width: 1.25rem;
	height: 1.25rem;
	border: 2px solid var(--c-border);
	border-top-color: var(--c-accent);
	border-radius: var(--r-round);
	animation: spinner-spin 0.7s linear infinite;
}
@keyframes spinner-spin {
	100% {
		transform: rotate(360deg);
	}
}
@media (prefers-reduced-motion: reduce) {
	.spinner {
		animation: none;
		border-color: var(--c-accent);
		border-right-color: var(--c-border);
	}
}

/* ══ Navigation ═══════════════════════════════════════════════ */

/* ── Tabs ── */
.tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 1.5rem;
	border-bottom: 1px solid var(--c-border);
}
.tab {
	position: relative;
	padding: 0.625rem 0.125rem;
	background: none;
	border: none;
	color: var(--c-text-sub);
	font-family: inherit;
	font-size: var(--t-sm);
	font-weight: 500;
	text-decoration: none;
	cursor: pointer;
	transition: color 0.2s ease;
}
.tab::after {
	content: '';
	position: absolute;
	right: 0;
	bottom: -1px;
	left: 0;
	height: 2px;
	background: transparent;
	transition: background 0.2s ease;
}
.tab:hover {
	color: var(--c-text);
}
.tab-active {
	color: var(--c-text);
	font-weight: 600;
}
.tab-active::after {
	background: var(--c-accent);
}
.tab:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 35%, transparent);
}

/* ── Breadcrumbs — separator auto-inserted before every item but the first ── */
.breadcrumbs {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0;
	font-size: var(--t-xs);
}
.breadcrumbs a {
	color: var(--c-text-sub);
	text-decoration: none;
	transition: color 0.2s ease;
}
.breadcrumbs a:hover {
	color: var(--c-accent);
}
.breadcrumbs [aria-current='page'] {
	color: var(--c-text);
	font-weight: 600;
}
.breadcrumbs > * + * {
	position: relative;
	margin-left: 0.8rem;
	padding-left: 0.8rem;
}
.breadcrumbs > * + *::before {
	content: '/';
	position: absolute;
	left: 0;
	color: var(--c-muted);
}

/* ── Pagination ── */
.pagination {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.35rem;
}
.page {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2.1rem;
	height: 2.1rem;
	padding: 0 0.5rem;
	border: 1px solid var(--c-border);
	border-radius: var(--r-sm);
	background: var(--c-surface);
	color: var(--c-text);
	font-family: inherit;
	font-size: var(--t-xs);
	text-decoration: none;
	cursor: pointer;
	transition:
		border-color 0.2s ease,
		background 0.2s ease,
		color 0.2s ease;
}
.page:hover {
	border-color: var(--c-accent);
	color: var(--c-accent);
}
.page-active,
.page-active:hover {
	background: var(--c-accent);
	border-color: var(--c-accent);
	color: var(--c-on-accent);
}
.page:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 35%, transparent);
}
