/* ================================================================
   SmartGym · app.css — the design system
   Consumes tokens from brand.css only. No brand values here.
   ================================================================ */

/* --- Reset --- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
img, svg { display: block; max-width: 100%; }

html, body, #app { height: 100%; }

body {
	font-family: var(--font-body);
	font-size: 15px;
	line-height: 1.55;
	color: var(--ink);
	background: var(--surface-page);
	-webkit-font-smoothing: antialiased;
}

/* --- Type --- */
h1, h2, h3, .display {
	font-family: var(--font-display);
	font-stretch: var(--display-stretch);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.015em;
	line-height: 1.05;
	text-wrap: balance;
}

h1 { font-size: clamp(1.7rem, 1.2rem + 2vw, 2.6rem); }
h2 { font-size: clamp(1.1rem, 1rem + 0.6vw, 1.35rem); }
h3 { font-size: 1.02rem; }

.eyebrow {
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--primary);
}

a { color: var(--primary-strong); }

:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
	border-radius: 6px;
}

::selection { background: var(--primary-soft); }

/* --- Page scaffold --- */
.page {
	max-width: 1180px;
	margin-inline: auto;
	padding: clamp(16px, 3vw, 36px);
	display: grid;
	gap: clamp(16px, 2vw, 26px);
	/* "backwards", not "both": a forward fill leaves a transform applied for the
	   life of the page, and an element with a transform becomes the containing
	   block for every position:fixed descendant — which would anchor modal
	   scrims to the page instead of the viewport, dropping tall dialogs off the
	   top of a long page. The last keyframe is the element's resting state
	   anyway, so nothing about the animation changes. */
	animation: page-rise 0.45s ease backwards;
}

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

/* --- The swell: dark hero band every page opens with --- */
.swell {
	position: relative;
	overflow: hidden;
	border-radius: var(--r-card);
	padding: clamp(22px, 3.5vw, 40px);
	background: var(--hero-grad);
	color: var(--hero-ink);
}

.swell .eyebrow { color: var(--glow); }
.swell p { color: var(--hero-ink-2); }
.swell h1, .swell h2 { color: var(--hero-ink); }

.swell__wave {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	pointer-events: none;
	color: var(--glow);
}

.swell__content { position: relative; }

/* Phones: every hero band slims down — tighter padding, smaller headline. */
@media (max-width: 575px) {
	.swell {
		padding: 20px 18px;
	}

	.swell h1 {
		font-size: 1.5rem;
	}

	.admin-hero__description {
		display: none;
	}
}

/* --- Cards --- */
.card {
	background: var(--surface-card);
	border: 1px solid var(--hairline);
	border-radius: var(--r-card);
	box-shadow: var(--shadow-card);
	padding: clamp(16px, 2.4vw, 26px);
}

.card-header {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 16px;
}

.card-subtitle { color: var(--ink-3); font-size: 0.85rem; }

/* --- Buttons --- */
.btn {
	font-family: var(--font-body);
	font-size: 0.9rem;
	font-weight: 700;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 10px 20px;
	border-radius: 8px;
	border: 1px solid transparent;
	cursor: pointer;
	text-decoration: none;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.1s ease;
}

.btn:active { transform: translateY(1px); }

.btn--primary {
	background: var(--primary);
	color: #ffffff;
}

.btn--primary:hover { background: var(--primary-strong); }

.btn--accent {
	background: var(--accent);
	color: var(--accent-ink);
}

.btn--accent:hover { filter: brightness(1.05); }

.btn--ghost {
	background: transparent;
	border-color: var(--hairline);
	color: var(--ink);
}

.btn--ghost:hover { background: var(--surface-sunken); border-color: var(--ink-3); }

/* Ghost button placed on the dark swell band */
.swell .btn--ghost {
	border-color: rgba(255, 255, 255, 0.35);
	color: var(--hero-ink);
}

.swell .btn--ghost:hover { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.6); }

.btn--subtle {
	background: var(--primary-soft);
	color: var(--primary-strong);
}

.btn--subtle:hover { background: var(--primary); color: #fff; }

.btn--block { width: 100%; }

.btn[disabled], .btn.disabled { opacity: 0.55; cursor: not-allowed; }

/* Icon-only button (nav toggles, calendar arrows) */
.btn--icon {
	padding: 8px;
	border-radius: 10px;
	background: transparent;
	border-color: var(--hairline);
	color: var(--ink-2);
}

.btn--icon:hover { background: var(--surface-sunken); color: var(--ink); }

/* --- Form fields --- */
.field { display: grid; gap: 6px; text-align: left; }

.field__label {
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--ink-2);
}

.control {
	font-family: var(--font-body);
	font-size: 0.95rem;
	color: var(--ink);
	width: 100%;
	padding: 10px 14px;
	background: var(--surface-card);
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.control:focus-visible {
	border-color: var(--primary);
	box-shadow: var(--focus-ring);
	outline: none;
}

.control::placeholder { color: var(--ink-3); }

.control[readonly] { background: var(--surface-sunken); color: var(--ink-2); }

textarea.control { resize: vertical; min-height: 68px; }

select.control { appearance: none; }

.field--select { position: relative; }

.field--select::after {
	content: "";
	position: absolute;
	right: 14px;
	bottom: 17px;
	width: 8px;
	height: 8px;
	border-right: 2px solid var(--ink-3);
	border-bottom: 2px solid var(--ink-3);
	transform: rotate(45deg);
	pointer-events: none;
}

/* Blazor validation */
.invalid, .control.invalid { border-color: var(--danger); }
.validation-message { color: var(--danger); font-size: 0.82rem; }

/* --- Chips & badges --- */
.chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px 12px;
	border-radius: var(--r-pill);
	font-size: 0.78rem;
	font-weight: 700;
	background: var(--primary-soft);
	color: var(--primary-strong);
}

.chip--accent { background: var(--accent); color: var(--accent-ink); }

.chip--outline {
	background: transparent;
	border: 1px solid var(--hairline);
	color: var(--ink-2);
}

/* An exercise the member added for themselves. Marked with the highlighter
   rather than the brand colour, because "nobody else can see this" is the
   exception worth catching the eye on a list of the gym's own. */
.chip--mine { background: var(--accent); color: var(--accent-ink); }

/* --- Progress: the crest gradient --- */
.progress-track {
	height: 10px;
	border-radius: var(--r-pill);
	background: rgba(255, 255, 255, 0.16);
	overflow: hidden;
}

.card .progress-track { background: var(--surface-sunken); }

.progress-fill {
	height: 100%;
	border-radius: var(--r-pill);
	background: linear-gradient(90deg, var(--primary) 0%, var(--glow) 100%);
	transition: width 0.6s ease;
}

/* --- Tables --- */
.table-wrapper { overflow-x: auto; }

.table {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.9rem;
}

.table th {
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--ink-3);
	text-align: left;
	padding: 10px 12px;
	border-bottom: 1px solid var(--hairline);
	white-space: nowrap;
}

.table td {
	padding: 12px;
	border-bottom: 1px solid var(--viz-grid);
	font-variant-numeric: tabular-nums;
}

.table tr:last-child td { border-bottom: none; }

/* Stackable table: on small screens each row becomes a label/value card.
   Cells need a data-label attribute to keep their column heading. */
@media (max-width: 720px) {
	.table--stack thead { display: none; }

	.table--stack,
	.table--stack tbody,
	.table--stack tr,
	.table--stack td { display: block; }

	.table--stack tr {
		border: 1px solid var(--hairline);
		border-radius: var(--r-ctl);
		padding: 6px 14px;
		margin-bottom: 10px;
		background: var(--surface-card);
	}

	.table--stack tr:last-child { margin-bottom: 0; }

	.table--stack td {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 16px;
		padding: 8px 0;
		border-bottom: none;
		text-align: right;
	}

	.table--stack td[data-label]::before {
		content: attr(data-label);
		font-size: 0.72rem;
		font-weight: 700;
		text-transform: uppercase;
		letter-spacing: 0.1em;
		color: var(--ink-3);
		text-align: left;
		flex-shrink: 0;
	}

	/* A cell with no value (e.g. missing phone number) adds nothing on mobile. */
	.table--stack td[data-label]:empty { display: none; }
}

/* --- Empty states --- */
.empty-state {
	padding: 28px;
	border: 1px dashed var(--hairline);
	border-radius: var(--r-card);
	color: var(--ink-2);
	text-align: center;
	font-size: 0.92rem;
}

/* --- Spinner --- */
.spinner {
	width: 34px;
	height: 34px;
	border-radius: 50%;
	border: 3px solid var(--primary-soft);
	border-top-color: var(--primary);
	animation: spin 0.7s linear infinite;
}

.spinner--sm { width: 18px; height: 18px; border-width: 2px; }

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

.loader {
	display: grid;
	place-items: center;
	min-height: 40vh;
}

.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}

/* --- Blazor boot & error UI --- */
/* Boot screen: "loading the bar". Blazor sets --blazor-load-percentage on
   <html> while resources download; each plate pair drops onto the barbell
   once the load passes its --at threshold. All colors come from brand.css. */
.boot {
	position: fixed;
	inset: 0;
	display: grid;
	place-items: center;
	background: var(--hero-grad);
}

.boot__stage {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.4rem;
}

.boot__stage::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 26rem;
	height: 26rem;
	transform: translate(-50%, -58%);
	background: radial-gradient(closest-side, color-mix(in srgb, var(--glow) 13%, transparent), transparent 72%);
	animation: boot-glow 3.4s ease-in-out infinite;
	pointer-events: none;
}

.boot__barbell {
	position: relative;
	display: flex;
	justify-content: space-between;
	align-items: center;
	width: min(21rem, 78vw);
	height: 5.4rem;
	animation: boot-bob 2.6s ease-in-out infinite;
}

.boot__bar {
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 0.5rem;
	transform: translateY(-50%);
	border-radius: var(--r-pill);
	background: linear-gradient(180deg, var(--hero-ink), var(--hero-ink-2));
}

.boot__side {
	position: relative;
	display: flex;
	align-items: center;
	gap: 0.22rem;
}

.boot__collar {
	width: 0.32rem;
	height: 1.15rem;
	border-radius: 0.16rem;
	background: var(--hero-ink-2);
}

.boot__plate {
	--at: 0%;
	border-radius: 0.28rem;
	box-shadow: inset 0 2px 0 color-mix(in srgb, #fff 22%, transparent);
	opacity: clamp(0%, calc((var(--blazor-load-percentage, 0%) - var(--at)) * 8), 100%);
	transform: translateY(clamp(-140%, calc((var(--blazor-load-percentage, 0%) - var(--at)) * 11.2 - 140%), 0%));
	transition: opacity 0.3s ease-out, transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.boot__plate--fortyfive {
	--at: 5%;
	width: 0.85rem;
	height: 4.7rem;
	background: var(--primary);
}

.boot__plate--twentyfive {
	--at: 38%;
	width: 0.75rem;
	height: 3.4rem;
	background: var(--glow);
}

.boot__plate--ten {
	--at: 68%;
	width: 0.65rem;
	height: 2.2rem;
	background: var(--accent);
}

.loading-progress-text {
	margin-top: 0.6rem;
	font-family: var(--font-display);
	font-stretch: var(--display-stretch);
	font-size: 1.9rem;
	font-weight: 750;
	color: var(--hero-ink);
	font-variant-numeric: tabular-nums;
}

.loading-progress-text::after {
	content: var(--blazor-load-percentage-text, "Loading");
}

.boot__hint {
	font-family: var(--font-body);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.24em;
	text-transform: uppercase;
	color: var(--hero-ink-2);
}

@keyframes boot-bob {
	0%,
	100% {
		transform: translateY(0);
	}

	50% {
		transform: translateY(4px);
	}
}

@keyframes boot-glow {
	0%,
	100% {
		opacity: 0.7;
	}

	50% {
		opacity: 1;
	}
}

@media (prefers-reduced-motion: reduce) {
	.boot__barbell,
	.boot__stage::before {
		animation: none;
	}

	.boot__plate {
		transform: none;
		transition: opacity 0.2s linear;
	}
}

#blazor-error-ui {
	background: var(--ink);
	color: #fff;
	bottom: 0;
	box-shadow: 0 -1px 4px rgba(0, 0, 0, 0.25);
	display: none;
	left: 0;
	padding: 0.7rem 2.5rem 0.7rem 1.25rem;
	position: fixed;
	width: 100%;
	z-index: 1000;
}

#blazor-error-ui .dismiss {
	cursor: pointer;
	position: absolute;
	right: 0.75rem;
	top: 0.5rem;
}

/* Send, in the chat composer. Lives here rather than in ChatPanel.razor.css
   because it is a class handed to the <Button> component, and scoped styles
   never reach a child component's markup. */
.chat__send {
	margin-left: auto;
}

/* --- Modal shell ---
   The scrim and dialog box a modal sits in. Lives here rather than in a page's
   scoped CSS because scoped styles only reach markup written in their own
   .razor file — the chat composer's picker is a second feature needing the same
   shell, and copying it would leave two to keep in step. The Log workout page
   still carries its own .lift-modal rules; migrating those onto this is a
   tidy-up for another day. */

.modal__scrim {
	position: fixed;
	inset: 0;
	background: rgba(5, 36, 44, 0.45);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 20px;
	z-index: 1000;
}

.modal {
	background: var(--surface-card);
	border-radius: var(--r-card);
	box-shadow: 0 24px 60px -18px rgba(5, 36, 44, 0.5);
	width: min(500px, 100%);
	max-height: 100%;
	overflow-y: auto;
	padding: 20px 22px 22px;
}

.modal__head {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	margin-bottom: 14px;
}

	.modal__head > div:first-child {
		flex: 1 1 auto;
	}

	.modal__head h2 {
		margin: 0;
	}

.modal__close {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	border: none;
	border-radius: 50%;
	background: var(--surface-sunken);
	color: var(--ink-2);
	cursor: pointer;
}

	.modal__close:hover {
		color: var(--ink);
	}

/* --- Exercise picker ---
   Search box, body-part shortcuts and the matching rows. Shared by the Log
   workout picker (adding an exercise) and the Progress picker (choosing a lift)
   — the library is far too long to scroll, so both search it instead. The
   result list is a fixed-height scroller so whatever sits below it stays put
   however the search narrows. */

.exercise-search {
	position: relative;
	display: flex;
	align-items: center;
	margin-top: 10px;
	color: var(--ink-3);
}

	.exercise-search svg {
		position: absolute;
		left: 12px;
		pointer-events: none;
	}

	.exercise-search input {
		width: 100%;
		padding-left: 38px;
	}

	/* Only drawn once there's something to clear, so it never sits there dead. */
	.exercise-search__clear {
		position: absolute;
		right: 8px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: 26px;
		height: 26px;
		padding: 0;
		border: 0;
		border-radius: 50%;
		background: transparent;
		color: var(--ink-3);
		cursor: pointer;
	}

		.exercise-search__clear:hover { background: var(--surface-sunken); color: var(--ink); }

		.exercise-search__clear:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* How much of the library is on screen, between the search and the list. */
.exercise-count {
	margin: 12px 0 0;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ink-3);
}

.body-parts {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 10px;
}

.body-part {
	padding: 5px 11px;
	border: 1px solid var(--hairline);
	border-radius: 999px;
	background: var(--surface-card);
	font: inherit;
	font-size: 0.76rem;
	font-weight: 600;
	color: var(--ink-2);
	cursor: pointer;
	transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}

	.body-part:hover {
		border-color: var(--primary);
		color: var(--ink);
	}

	.body-part:focus-visible {
		outline: none;
		box-shadow: var(--focus-ring);
	}

.body-part--on {
	border-color: var(--primary);
	background: var(--primary-soft);
	color: var(--primary-strong);
}

.exercise-results {
	display: flex;
	flex-direction: column;
	gap: 6px;
	max-height: 268px;
	overflow-y: auto;
	margin-top: 10px;
	padding-right: 4px;
}

.exercise-option {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto auto;
	gap: 10px;
	align-items: center;
	width: 100%;
	padding: 9px 12px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
	background: var(--surface-sunken);
	font: inherit;
	text-align: left;
	color: var(--ink-3);
	cursor: pointer;
	transition: border-color 0.15s ease, background 0.15s ease;
}

	.exercise-option:hover {
		border-color: var(--primary);
		background: var(--primary-soft);
	}

	.exercise-option:focus-visible {
		outline: none;
		box-shadow: var(--focus-ring);
	}

/* The lift already being charted, when the picker is used to switch between. */
.exercise-option--on {
	border-color: var(--primary);
	background: var(--primary-soft);
}

.exercise-option__name {
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--ink);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

	/* Small enough to ride along with the name without pushing the body part
	   off the row — it's a footnote, not a second label. */
	.exercise-option__mine {
		margin-left: 6px;
		padding: 1px 7px;
		border-radius: var(--r-pill);
		background: var(--accent);
		color: var(--accent-ink);
		font-size: 0.62rem;
		font-weight: 800;
		letter-spacing: 0.06em;
		text-transform: uppercase;
		vertical-align: 1px;
	}

.exercise-option__group {
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--ink-3);
	white-space: nowrap;
}

/* Sessions logged for the lift — the number that says which have history worth charting. */
.exercise-option__count {
	min-width: 22px;
	padding: 1px 6px;
	border-radius: 999px;
	background: var(--surface-card);
	font-size: 0.72rem;
	font-weight: 700;
	color: var(--ink-2);
	text-align: center;
}

.exercise-results__empty,
.exercise-results__more {
	margin-top: 10px;
	font-size: 0.78rem;
	color: var(--ink-3);
}

/* The <ExercisePicker /> modal. The result list scrolls inside the dialog
   rather than stretching it, so the "name your own" fallback below stays
   reachable however many exercises match. */
.picker-modal .exercise-results {
	max-height: min(46vh, 340px);
}

.picker-modal__custom {
	margin-top: 16px;
	padding-top: 14px;
	border-top: 1px solid var(--hairline);
}

.picker-modal__custom-label {
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ink-3);
}

.picker-modal__custom-row {
	display: flex;
	align-items: flex-end;
	gap: 8px;
	margin-top: 10px;
}

	.picker-modal__custom-row .field {
		flex: 1 1 auto;
		margin: 0;
	}

	/* "New exercise" has no field beside it — just the button under its label. */
	.picker-modal__custom > .btn { margin-top: 10px; }

/* What each way out of "it isn't there" actually does — one keeps the exercise,
   the other doesn't. The difference is the whole reason both are offered. */
.picker-modal__custom-note {
	margin: 6px 0 0;
	font-size: 0.76rem;
	color: var(--ink-3);
}

	/* The second option needs air between it and the first. */
	.picker-modal__custom-note + .picker-modal__custom-row { margin-top: 14px; }

/* The line under the head when the modal has turned into the new-exercise form,
   saying where what you're about to type ends up. */
.picker-modal__hint {
	margin: 10px 0 16px;
	font-size: 0.82rem;
	color: var(--ink-2);
}

/* --- Tabs --- */
.tabs {
	display: flex;
	gap: 28px;
	max-width: 100%;
	overflow-x: auto;
	border-bottom: 1px solid var(--hairline);
}

.tab {
	font-family: var(--font-display);
	font-size: 0.95rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	padding: 10px 2px;
	border: none;
	border-bottom: 2px solid transparent;
	background: transparent;
	color: var(--ink-2);
	cursor: pointer;
	white-space: nowrap;
	transition: color 0.15s ease, border-color 0.15s ease;
}

.tab:hover { color: var(--ink); }

.tab--active,
.tab--active:hover {
	color: var(--ink);
	border-bottom-color: var(--primary);
}

/* Phones: tighten the strip so a short set of tabs fits without scrolling,
   and let a long one (the admin console's seven) scroll without a scrollbar. */
@media (max-width: 575px) {
	.tabs {
		gap: 16px;
		scrollbar-width: none;
	}

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

	/* Taller than it looks — a tab needs to survive a thumb. */
	.tab {
		font-size: 0.82rem;
		letter-spacing: 0.02em;
		padding: 14px 2px;
	}
}

/* --- Admin console --- */
.admin-hero__description { max-width: 52ch; }

.admin-form { display: grid; gap: 16px; max-width: 560px; }

.admin-form__actions { display: flex; gap: 10px; flex-wrap: wrap; }

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

.admin-colour__swatch {
	width: 44px;
	height: 34px;
	padding: 2px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
	background: var(--surface-card);
	cursor: pointer;
}

.admin-colour__value { font-size: 0.88rem; color: var(--ink-2); }

.admin-settings__hint { font-size: 0.82rem; color: var(--ink-3); }
.admin-settings__error { color: var(--danger); font-size: 0.88rem; }
.admin-settings__saved { color: var(--ok); font-size: 0.88rem; }

.admin-invite__hint { font-size: 0.88rem; color: var(--ink-2); }
.admin-invite__result { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.admin-invite__result input { flex: 1 1 220px; min-width: 0; }
.admin-invite__expiry { font-size: 0.82rem; color: var(--ink-3); }

/* Exercise library */
.exercise-list {
	display: grid;
	gap: 10px;
	margin-top: 20px;
	border-top: 1px solid var(--hairline);
	padding-top: 20px;
}

/* Thumb · name and meta · actions. The third column folds under the other two
   on phones, so the name always gets the full width of the card to wrap in. */
.exercise-row {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	align-items: center;
	gap: 14px;
	padding: 12px 14px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
	background: var(--surface-card);
}

.exercise-row__thumb {
	width: 76px;
	height: 48px;
	display: grid;
	place-items: center;
	border-radius: 8px;
	overflow: hidden;
	background: var(--surface-sunken);
	color: var(--ink-3);
}

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

/* Children stretch to the column: a shrink-wrapped meta row is sized to its
   widest possible line, so its chips would never wrap. */
.exercise-row__body { min-width: 0; display: grid; gap: 4px; overflow-wrap: anywhere; }
.exercise-row__name { line-height: 1.3; }
.exercise-row__body p { font-size: 0.85rem; color: var(--ink-2); }

/* Body part and video state sit side by side rather than stacking */
.exercise-row__meta { display: flex; flex-wrap: wrap; gap: 6px; }

.exercise-row__actions {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
	justify-content: flex-end;
}

/* Edit and delete travel as a pair so they never split across two lines */
.exercise-row__tools { display: flex; gap: 8px; margin-left: auto; }

/* Phones: the row becomes a card — thumb and name up top, actions on a
   full-width line under a hairline, with targets big enough for a thumb. */
@media (max-width: 575px) {
	.exercise-list { gap: 12px; }

	.exercise-row {
		grid-template-columns: auto minmax(0, 1fr);
		align-items: start;
		gap: 12px;
		padding: 12px;
	}

	.exercise-row__thumb { width: 60px; height: 60px; }

	/* Two lines of coaching notes is enough to recognise the lift by */
	.exercise-row__body p {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.exercise-row__actions {
		grid-column: 1 / -1;
		justify-content: flex-start;
		padding-top: 12px;
		border-top: 1px solid var(--hairline);
	}

	/* The video action stretches; edit and delete keep the right edge */
	.exercise-row__actions > .btn--subtle { flex: 1 1 auto; }

	.exercise-row__tools .btn--icon { min-width: 44px; min-height: 44px; }
}

.exercise-edit {
	padding: 14px;
	border: 1px dashed var(--hairline);
	border-radius: var(--r-ctl);
	background: var(--surface-sunken);
}

.exercise-video iframe {
	width: 100%;
	aspect-ratio: 16 / 9;
	border: none;
	border-radius: var(--r-ctl);
	background: #000;
}

/* Workout schedules */
.schedule-list { display: grid; gap: 10px; }

.schedule-row {
	display: flex;
	align-items: flex-start;
	gap: 14px;
	padding: 14px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
}

.schedule-row__body { flex: 1; min-width: 0; display: grid; gap: 6px; justify-items: start; }
.schedule-row__body p { font-size: 0.85rem; color: var(--ink-2); }
.schedule-row__meta { display: flex; gap: 8px; flex-wrap: wrap; }
.schedule-row__actions { display: flex; gap: 8px; }

/* --- Schedule editor ---
   Wider than the plain admin form: the week needs a rail of days beside the
   day being edited. Single-column fields — name, dates, assignment — stay at
   form width; only the week is allowed the whole card. */
.schedule-form { display: grid; gap: 18px; max-width: 1080px; }

	.schedule-form > .field,
	.schedule-form > .admin-form__actions {
		max-width: 560px;
	}

	.schedule-form > .field--wide { max-width: none; }

.week-editor {
	display: grid;
	grid-template-columns: 236px minmax(0, 1fr);
	gap: 16px;
	align-items: start;
}

/* The seven days, always all of them — the shape of the week reads without
   opening anything, and adding an exercise no longer asks which day. */
.day-rail { display: grid; gap: 6px; }

.day-rail__day {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 10px 12px;
	border: 1px solid transparent;
	border-radius: var(--r-ctl);
	background: transparent;
	font: inherit;
	text-align: left;
	color: var(--ink);
	cursor: pointer;
	transition: background 0.15s ease, border-color 0.15s ease;
}

	.day-rail__day:hover { background: var(--surface-sunken); }

	.day-rail__day:focus-visible { outline: none; box-shadow: var(--focus-ring); }

	.day-rail__day[aria-current="true"] {
		background: var(--primary-soft);
		border-color: var(--primary);
	}

.day-rail__stripe {
	flex: none;
	width: 3px;
	align-self: stretch;
	border-radius: var(--r-pill);
	background: var(--primary);
}

.day-rail__stripe--rest { background: var(--hairline); }

.day-rail__text { flex: 1; min-width: 0; display: grid; gap: 1px; }

.day-rail__weekday { font-size: 0.92rem; font-weight: 700; }

.day-rail__meta {
	font-size: 0.78rem;
	color: var(--ink-3);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.day-rail__day[aria-current="true"] .day-rail__meta { color: var(--primary-strong); }

.day-rail__count {
	flex: none;
	min-width: 24px;
	padding: 2px 6px;
	border-radius: var(--r-pill);
	background: var(--surface-sunken);
	font-size: 0.78rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	color: var(--ink-2);
	text-align: center;
}

.day-rail__day[aria-current="true"] .day-rail__count {
	background: var(--surface-card);
	color: var(--primary-strong);
}

/* The day being edited: what it's called, then what's in it. */
.day-detail {
	display: grid;
	align-content: start;
	gap: 14px;
	padding: 18px;
	min-height: 240px;
	border: 1px solid var(--hairline);
	border-radius: 14px;
}

/* The day's title row: which weekday, and how much is on it. */
.day-detail__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	flex-wrap: wrap;
}

/* The session name gets the panel's full width — it's the day's headline,
   and it's what members and the TV screen read. */
.day-detail__title {
	display: grid;
	gap: 6px;
	padding: 14px;
	border-radius: var(--r-ctl);
	background: var(--surface-sunken);
}

	.day-detail__title .control { background: var(--surface-card); }

.day-detail__weekday {
	font-family: var(--font-display);
	font-size: 1.2rem;
	font-weight: 800;
}

/* What the day adds up to, with a word on whether the last Done was written. */
.day-detail__state {
	display: flex;
	align-items: baseline;
	gap: 10px;
}

.day-detail__saved { font-size: 0.82rem; color: var(--ok); }
.day-detail__unsaved { font-size: 0.82rem; color: var(--ink-3); }

.day-detail__rest { font-size: 0.88rem; color: var(--ink-3); }

.day-detail__add { justify-self: start; }

/* One exercise in the day. The order buttons come first: reordering is a
   column you run your eye down, not something hidden behind a menu. */
.slots { display: grid; gap: 8px; }

.slot {
	display: grid;
	grid-template-columns: auto auto minmax(120px, 1fr) auto auto;
	align-items: center;
	gap: 14px;
	padding: 10px 14px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
}

.slot--editing { border-color: var(--primary); background: var(--primary-soft); }

.slot__order { display: grid; gap: 3px; }

.slot__index {
	font-size: 0.8rem;
	font-weight: 700;
	color: var(--ink-3);
	font-variant-numeric: tabular-nums;
	min-width: 1.2em;
	text-align: right;
}

.slot__name {
	font-size: 0.92rem;
	font-weight: 600;
	min-width: 0;
	line-height: 1.35;
	overflow-wrap: anywhere;
}

.slot__group { display: block; font-size: 0.76rem; color: var(--ink-3); font-weight: 500; }

/* The coaching note, echoed on the collapsed row so it isn't hidden behind an
   editor nobody has a reason to open. */
.slot__note {
	display: block;
	margin-top: 2px;
	font-size: 0.78rem;
	font-weight: 500;
	font-style: italic;
	color: var(--ink-2);
}

.slot__dose {
	font: inherit;
	font-size: 0.85rem;
	font-weight: 700;
	color: var(--ink-2);
	font-variant-numeric: tabular-nums;
	background: var(--surface-sunken);
	border: 1px solid transparent;
	border-radius: var(--r-pill);
	padding: 4px 12px;
	white-space: nowrap;
	cursor: pointer;
}

	.slot__dose:hover { border-color: var(--primary); color: var(--primary-strong); }

	.slot__dose:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.slot__tools { display: flex; gap: 4px; }

/* Sets and reps for one exercise: how many sets, and whether the reps repeat
   or change down them. */
.dose {
	grid-column: 1 / -1;
	display: grid;
	gap: 14px;
	margin-top: 4px;
	padding: 14px;
	background: var(--surface-card);
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
}

.dose__row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }

.dose__row--foot { justify-content: space-between; }

/* One note for the whole exercise — it's the cue, not a per-set qualifier. */
.dose__row--notes > .field { flex: 1; min-width: 200px; }

.dose__label {
	font-size: 0.76rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--ink-2);
	min-width: 46px;
}

.dose__summary { font-size: 0.85rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }

.stepper {
	display: inline-flex;
	align-items: center;
	border: 1px solid var(--hairline);
	border-radius: var(--r-pill);
	background: var(--surface-card);
	overflow: hidden;
}

	.stepper button {
		width: 32px;
		height: 32px;
		border: 0;
		background: transparent;
		font: inherit;
		font-size: 1.05rem;
		line-height: 1;
		color: var(--ink-2);
		cursor: pointer;
	}

	.stepper button:hover:not(:disabled) { background: var(--surface-sunken); color: var(--ink); }

	.stepper button:disabled { opacity: 0.35; cursor: not-allowed; }

.stepper__value {
	min-width: 34px;
	text-align: center;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

/* Same every set / reps per set — and reps / lengths / time, which is three
   options wide and wraps rather than pushing the row off a phone. */
.seg {
	display: inline-flex;
	flex-wrap: wrap;
	gap: 3px;
	padding: 3px;
	background: var(--surface-sunken);
	border-radius: var(--r-pill);
}

	.seg button {
		border: 0;
		background: transparent;
		font: inherit;
		font-size: 0.82rem;
		font-weight: 700;
		color: var(--ink-2);
		padding: 6px 14px;
		border-radius: var(--r-pill);
		cursor: pointer;
	}

	.seg button[aria-pressed="true"] {
		background: var(--surface-card);
		color: var(--primary-strong);
		box-shadow: var(--shadow-card);
	}

	.seg button:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* Reps or time on one part of a block, where a full-size toggle would push the
   numbers off the row. */
.seg--tight button { padding: 5px 11px; font-size: 0.78rem; }

.reps { display: flex; gap: 8px; flex-wrap: wrap; }

.rep { display: grid; gap: 4px; justify-items: center; }

.rep__label {
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ink-3);
}

.rep__input {
	width: 62px;
	padding: 8px 6px;
	text-align: center;
	font: inherit;
	font-size: 0.95rem;
	font-weight: 700;
	color: var(--ink);
	background: var(--surface-card);
	border: 1px solid var(--hairline);
	border-radius: 10px;
	font-variant-numeric: tabular-nums;
}

	.rep__input:focus-visible { outline: none; border-color: var(--primary); box-shadow: var(--focus-ring); }

/* The unit beside a field, so "20" reads as twenty seconds of work. */
.rep__unit { font-size: 0.78rem; font-weight: 700; color: var(--ink-3); padding-bottom: 10px; }

/* A stack of controls under a label that would otherwise squash them onto one
   line — the round-by-round intervals, the parts of a block, the alternate. */
.dose__row--stack { align-items: flex-start; }

	.dose__row--stack > .dose__label { padding-top: 4px; }

.dose__body { flex: 1; min-width: 0; display: grid; gap: 10px; justify-items: start; }

/* How a block is dosed — rounds or a clock — beside the number it takes. */
.dose__pick { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }

.dose__hint { font-size: 0.78rem; color: var(--ink-3); margin: 0; max-width: 62ch; }

/* Adds the thing the row is about — a part, an alternate, another round. */
.dose__add {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 7px 12px;
	border: 1px dashed var(--hairline);
	border-radius: var(--r-ctl);
	background: transparent;
	font: inherit;
	font-size: 0.8rem;
	font-weight: 700;
	color: var(--primary-strong);
	cursor: pointer;
}

	.dose__add:hover { border-color: var(--primary); background: var(--primary-soft); }

	.dose__add:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* --- Timed work: rounds of work and rest --- */

.rounds { display: grid; gap: 6px; }

.round {
	display: grid;
	grid-template-columns: 64px auto auto 1fr auto;
	align-items: center;
	gap: 10px;
	padding: 7px 10px;
	border: 1px solid var(--hairline);
	border-radius: 10px;
	background: var(--surface-card);
}

.round__num {
	font-size: 0.68rem;
	font-weight: 800;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ink-3);
}

.round__pair { display: inline-flex; align-items: center; gap: 6px; }

	.round__pair span {
		font-size: 0.74rem;
		font-weight: 700;
		text-transform: uppercase;
		letter-spacing: 0.06em;
		color: var(--ink-3);
	}

.round__input {
	width: 54px;
	padding: 6px;
	text-align: center;
	font: inherit;
	font-size: 0.9rem;
	font-weight: 700;
	color: var(--ink);
	background: var(--surface-card);
	border: 1px solid var(--hairline);
	border-radius: 8px;
	font-variant-numeric: tabular-nums;
}

	.round__input:focus-visible { outline: none; border-color: var(--primary); box-shadow: var(--focus-ring); }

.round__unit {
	font-size: 0.74rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--ink-3);
}

.round__total { font-size: 0.76rem; color: var(--ink-3); font-variant-numeric: tabular-nums; text-align: right; }

/* --- The alternate: one easier option, done instead --- */

.swap {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 8px 12px;
	border: 1px dashed var(--hairline);
	border-radius: 10px;
	background: var(--surface-sunken);
}

.swap__badge {
	font-size: 0.66rem;
	font-weight: 800;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--accent-ink);
	background: var(--accent);
	border-radius: var(--r-pill);
	padding: 2px 8px;
}

.swap__name { font-size: 0.88rem; font-weight: 700; }

/* The alternate is dosed on its own row, with the same controls a part gets. */
.swap__fields { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }

.swap__spacer { flex: 1; }

/* Echoed on the collapsed row, so the fallback reads without opening anything. */
.slot__alt { display: flex; align-items: center; gap: 6px; margin-top: 4px; font-size: 0.78rem; color: var(--ink-2); }

.slot__alt-badge {
	font-size: 0.62rem;
	font-weight: 800;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--accent-ink);
	background: var(--accent);
	border-radius: var(--r-pill);
	padding: 1px 7px;
}

/* --- Multi-part: exercises done as well, in order, every round --- */

.parts { display: grid; gap: 6px; width: 100%; }

.part {
	display: grid;
	grid-template-columns: 22px minmax(100px, 1fr) auto auto;
	align-items: center;
	gap: 12px;
	padding: 8px 10px;
	border: 1px solid var(--hairline);
	border-radius: 10px;
	background: var(--surface-card);
}

.part__letter {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	border-radius: var(--r-pill);
	background: var(--primary-soft);
	color: var(--primary-strong);
	font-size: 0.72rem;
	font-weight: 800;
	text-transform: uppercase;
}

.part__name { font-size: 0.88rem; font-weight: 700; min-width: 0; }

.part__group { display: block; font-size: 0.72rem; font-weight: 500; color: var(--ink-3); }

.part__fields { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }

.part__swap-add {
	grid-column: 2 / -1;
	justify-self: start;
	display: inline-flex;
	align-items: center;
	gap: 5px;
	padding: 3px 9px;
	border: 1px dashed var(--hairline);
	border-radius: var(--r-pill);
	background: transparent;
	font: inherit;
	font-size: 0.74rem;
	font-weight: 700;
	color: var(--ink-3);
	cursor: pointer;
}

	.part__swap-add:hover { border-color: var(--primary); color: var(--primary-strong); }

	.part__swap-add:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.part .swap { grid-column: 2 / -1; }

/* The block's parts on the collapsed row — what it is, without opening it. */
.slot__parts { display: grid; gap: 3px; margin-top: 5px; }

.slot__part { display: flex; align-items: center; gap: 8px; font-size: 0.8rem; color: var(--ink-2); font-weight: 500; }

.slot__part-letter {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 18px;
	height: 18px;
	border-radius: var(--r-pill);
	background: var(--surface-sunken);
	color: var(--ink-2);
	font-size: 0.66rem;
	font-weight: 800;
	text-transform: uppercase;
}

.slot__part-dose { font-weight: 700; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* Small square button used for the reorder arrows and row tools. */
.icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	border: 1px solid var(--hairline);
	border-radius: 9px;
	background: transparent;
	color: var(--ink-2);
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease;
}

	.icon-btn:hover:not(:disabled) { background: var(--surface-sunken); color: var(--ink); }

	.icon-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

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

	.icon-btn--danger:hover:not(:disabled) { color: var(--danger); }

.icon-btn--tiny { width: 26px; height: 17px; border-radius: 6px; }

@media (max-width: 760px) {
	.week-editor { grid-template-columns: minmax(0, 1fr); }

	.day-rail { grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); }

	/* The target and the row's tools drop onto a second line together,
	   rather than each taking one of their own. */
	.slot { grid-template-columns: auto auto minmax(0, 1fr); row-gap: 10px; }

	.slot__dose { grid-column: 2 / 3; justify-self: start; }

	.slot__tools { grid-column: 3 / -1; justify-self: end; }
}

@media (max-width: 640px) {
	/* Three ways to measure plus the number won't sit beside an exercise name on
	   a phone, so the fields take a line of their own under it. */
	.part { grid-template-columns: 22px minmax(0, 1fr) auto; row-gap: 8px; }

	.part > .slot__tools { grid-column: 3; grid-row: 1; }

	.part__fields { grid-column: 1 / -1; grid-row: 2; }

	.part__swap-add { grid-row: 3; }

	/* The alternate's row does the same, without a spacer holding the fields out
	   to the right where there's no longer room for them. */
	.swap { flex-wrap: wrap; }

	.swap__spacer { display: none; }
}

@media (max-width: 480px) {
	/* On a phone the label column costs more than it earns: it leaves a part's
	   fields about 140px, which is narrower than the three measures need. The
	   stacked rows put their label above and hand the controls the full width. */
	.dose__row--stack { flex-direction: column; gap: 8px; }

		.dose__row--stack > .dose__label { padding-top: 0; }

	.dose__body { width: 100%; }

	/* With the width back, the three measures fit on one line. */
	.seg--tight button { padding: 5px 9px; font-size: 0.74rem; }
}

/* --- Admin · video display --- */
.display-status { display: grid; gap: 12px; }

.display-status__screen {
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--primary-strong);
}

.display-status__line { display: flex; align-items: center; gap: 10px; color: var(--ink-2); }

.display-status__preview {
	width: 100%;
	max-width: 560px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
	background: #000;
}

/* Still of the chosen style, drawn by the renderer while the video is building */
.display-preview {
	display: grid;
	gap: 8px;
	max-width: 560px;
}

.display-preview__image {
	width: 100%;
	display: block;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
	background: #000;
}

.display-preview__caption {
	font-size: 0.82rem;
	color: var(--ink-2);
}

/* The code the TVs enter, beside the button that commits it */
.display-code {
	display: flex;
	align-items: flex-end;
	gap: 10px;
	flex-wrap: wrap;
}

	.display-code > .field { width: 140px; }

/* The finished MP4's address, spelled out — a TV or a USB stick is often set up
   from a phone that isn't signed in here, so the link alone isn't enough. */
.display-link { display: grid; gap: 6px; max-width: 560px; }

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

.display-link__url {
	flex: 1;
	min-width: 220px;
	font-size: 0.82rem;
	font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
	color: var(--ink-2);
}

/* --- Admin · the workout video library --- */
.video-list { display: grid; gap: 10px; }

.video-row {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 12px 14px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
}

.video-row--current { border-color: var(--primary); background: var(--primary-soft); }

.video-row__body { flex: 1; min-width: 0; display: grid; gap: 6px; justify-items: start; }

.video-row__meta { display: flex; gap: 8px; flex-wrap: wrap; }

.video-row__date { font-size: 0.8rem; color: var(--ink-3); }

.video-row__actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }

@media (max-width: 640px) {
	.video-row { flex-direction: column; align-items: stretch; }

	.video-row__actions { justify-content: flex-start; }
}

/* Start / finish date pair in the schedule editor */
.schedule-dates {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 10px;
}

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

.assign-all {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 0.92rem;
	cursor: pointer;
}

.member-picks {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
	gap: 8px;
	padding: 12px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
	background: var(--surface-sunken);
	max-height: 260px;
	overflow-y: auto;
}

.member-pick {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 0.9rem;
	cursor: pointer;
}

.member-picks__empty {
	padding: 16px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-ctl);
	background: var(--surface-sunken);
	font-size: 0.88rem;
	color: var(--ink-3);
	text-align: center;
}

/* Search over a long member list — the same shape as the exercise search. */
.member-search {
	position: relative;
	display: flex;
	align-items: center;
	color: var(--ink-3);
}

	.member-search svg {
		position: absolute;
		left: 12px;
		pointer-events: none;
	}

	.member-search input {
		width: 100%;
		padding-left: 38px;
	}

/* Who's already assigned, held above the list so a search can't hide them. */
.member-picked { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }

.member-picked__chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 6px 4px 12px;
	border-radius: var(--r-pill);
	font-size: 0.8rem;
	font-weight: 700;
	background: var(--primary-soft);
	color: var(--primary-strong);
}

	.member-picked__chip button {
		display: inline-flex;
		padding: 2px;
		border: 0;
		border-radius: 50%;
		background: transparent;
		color: inherit;
		cursor: pointer;
	}

	.member-picked__chip button:hover { background: var(--surface-card); }

	.member-picked__chip button:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* Trailing cell of a member row: admin chip + open button together */
.member-row__end {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 8px;
}

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