@import "tokens-HIwyuwy.css";

/* ---------- Fonts (self-hosted, see /DESIGN.md) ---------- */

@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url("../fonts/ibm-plex-sans/ibm-plex-sans-latin-400-normal-dCzU-sz.woff2") format('woff2');
}

@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url("../fonts/ibm-plex-sans/ibm-plex-sans-latin-500-normal-mSIWrNY.woff2") format('woff2');
}

@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url("../fonts/ibm-plex-sans/ibm-plex-sans-latin-600-normal-pA5FLX3.woff2") format('woff2');
}

@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url("../fonts/ibm-plex-mono/ibm-plex-mono-latin-400-normal-78NWkmx.woff2") format('woff2');
}

@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url("../fonts/ibm-plex-mono/ibm-plex-mono-latin-500-normal-QJNNIVc.woff2") format('woff2');
}

/* ---------- Reset ---------- */

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

body {
	margin: 0;
}

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

/* The `hidden` attribute must win over any component `display` rule (a `.notice` with
   `display: flex` used to show its "could not save" message all the time). */
[hidden] {
	display: none !important;
}

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

/* ---------- Base typography ---------- */

body {
	background: var(--color-bg);
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: var(--font-size-body);
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
	font-family: var(--font-sans);
	font-weight: 600;
	line-height: 1.2;
	margin: 0 0 var(--space-3);
	text-wrap: balance;
}

h1 {
	font-size: var(--font-size-h1);
}
h2 {
	font-size: var(--font-size-h2);
}
h3 {
	font-size: var(--font-size-h3);
}

p {
	margin: 0 0 var(--space-4);
	max-width: 65ch;
}

a {
	color: var(--color-accent);
}

a:hover {
	color: var(--color-accent-hover);
}

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

.text-small {
	font-size: var(--font-size-small);
}

.caption {
	font-size: var(--font-size-caption);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-ink-muted);
	font-weight: 500;
}

.font-mono {
	font-family: var(--font-mono);
}

.tabular-nums {
	font-variant-numeric: tabular-nums;
}

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

/* Text for screen readers only: an icon is visible, but "×" does not say what it does. */
.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* ---------- Layout ---------- */

/* Shell: the side menu on the left (a fixed rail), the content beside it. */
.app-shell {
	min-height: 100vh;
}

.app-content {
	min-width: 0;
	transition: margin-left 0.15s ease;
}

.has-sidebar .app-content {
	margin-left: var(--sidebar-rail);
}

:root[data-sidebar='open'] .has-sidebar .app-content {
	margin-left: var(--sidebar-width);
}

/* The side menu (#47). Closed: a rail of icons. Hover or keyboard focus widens it over
   the content and it shrinks back on leave; the hamburger pins it open and pushes the
   content instead. See DESIGN.md, "Menú lateral". */
.sidebar {
	position: fixed;
	top: 0;
	bottom: 0;
	left: 0;
	z-index: 20;
	width: var(--sidebar-rail);
	overflow: hidden auto;
	background: var(--color-surface);
	border-right: 1px solid var(--color-border);
	transition: width 0.15s ease, box-shadow 0.15s ease;
}

.sidebar__list {
	list-style: none;
	margin: 0;
	padding: var(--space-2);
	display: flex;
	flex-direction: column;
	gap: var(--space-1);
	min-width: var(--sidebar-width);
}

.sidebar__link {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	height: var(--tap-target);
	padding: 0 calc((var(--sidebar-rail) - var(--space-4) - 20px) / 2);
	border-radius: var(--radius-sm);
	color: var(--color-ink-muted);
	text-decoration: none;
	white-space: nowrap;
	transition: background-color 0.12s ease, color 0.12s ease;
}

.sidebar__link:hover {
	background: color-mix(in srgb, var(--color-accent) 6%, var(--color-surface));
	color: var(--color-ink);
}

.sidebar__link.is-current {
	background: color-mix(in srgb, var(--color-accent) 10%, var(--color-surface));
	color: var(--color-accent);
	font-weight: 500;
}

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

.sidebar__icon {
	flex: none;
	display: inline-flex;
	width: 20px;
	height: 20px;
}

/* Labels are always in the DOM (screen readers, the pinned state); visually they fade
   in with the width. */
.sidebar__label {
	opacity: 0;
	transition: opacity 0.12s ease;
}

.sidebar__group {
	margin-top: var(--space-3);
	padding: 0 var(--space-3);
	height: 20px;
	overflow: hidden;
}

.sidebar__group-label {
	font-size: var(--font-size-caption);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-ink-muted);
	font-weight: 500;
	white-space: nowrap;
	opacity: 0;
	transition: opacity 0.12s ease;
}

/* Widened states: pinned open, keyboard focus inside, or the pointer over it (only on
   devices that really hover, so a tap on a tablet does not leave it stuck open). */
:root[data-sidebar='open'] .sidebar,
.sidebar:focus-within {
	width: var(--sidebar-width);
}

@media (hover: hover) {
	.sidebar:hover {
		width: var(--sidebar-width);
	}

	.sidebar:hover .sidebar__label,
	.sidebar:hover .sidebar__group-label {
		opacity: 1;
	}

	/* Hovered but not pinned: it floats over the content, so it casts the overlay shadow. */
	:root:not([data-sidebar='open']) .sidebar:hover {
		box-shadow: var(--shadow-overlay);
	}
}

:root[data-sidebar='open'] .sidebar__label,
:root[data-sidebar='open'] .sidebar__group-label,
.sidebar:focus-within .sidebar__label,
.sidebar:focus-within .sidebar__group-label {
	opacity: 1;
}

.sidebar__backdrop {
	display: none;
}

/* Narrow screens: no rail; the menu slides over the page with a backdrop. */
@media (max-width: 767px) {
	.has-sidebar .app-content,
	:root[data-sidebar='open'] .has-sidebar .app-content {
		margin-left: 0;
	}

	.sidebar {
		width: var(--sidebar-width);
		transform: translateX(-100%);
		transition: transform 0.15s ease;
	}

	:root[data-sidebar='open'] .sidebar {
		transform: none;
		box-shadow: var(--shadow-overlay);
	}

	.sidebar__label,
	.sidebar__group-label {
		opacity: 1;
	}

	:root[data-sidebar='open'] .sidebar__backdrop {
		display: block;
		position: fixed;
		inset: 0;
		z-index: 15;
		background: rgba(0, 0, 0, 0.45);
	}
}

.sidebar-toggle {
	flex: none;
}

.app-header {
	display: flex;
	align-items: center;
	gap: var(--space-4);
	height: 60px;
	padding: 0 var(--space-5);
	background: var(--color-surface);
	border-bottom: 1px solid var(--color-border);
}

.app-header__brand {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	font-weight: 600;
	color: var(--color-ink);
	text-decoration: none;
	white-space: nowrap;
}

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

.app-header__actions {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	margin-left: auto;
}

.app-header__user {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	min-height: 40px;
	padding: 0 var(--space-2);
	border-radius: var(--radius-sm);
	font-size: var(--font-size-small);
	color: var(--color-ink-muted);
	text-decoration: none;
}

.app-header__user:hover,
.app-header__user.is-current {
	color: var(--color-accent);
}

/* "Mi cuenta" data list */
.account-data {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
	gap: var(--space-3);
	margin: 0;
}

.account-data dt {
	font-size: var(--font-size-small);
	color: var(--color-ink-muted);
}

.account-data dd {
	margin: 0;
	font-weight: 500;
}

@media (max-width: 767px) {
	.app-header {
		gap: var(--space-3);
		padding: 0 var(--space-4);
	}

	/* Narrow screens: the account link keeps its icon, the name and "Cerrar sesión" go
	   (both live in "Mi cuenta" too). */
	.app-header__user-name,
	.app-header__logout {
		display: none;
	}
}

.page {
	padding: var(--space-6) var(--space-5);
}

.page-work {
	max-width: 720px;
	margin: 0 auto;
	padding: var(--space-6) var(--space-5);
}

.page-wide {
	max-width: 1100px;
	margin: 0 auto;
	padding: var(--space-6) var(--space-5);
}

.page-header {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--space-4);
	margin-bottom: var(--space-5);
}

.page-header__actions {
	display: flex;
	gap: var(--space-2);
}

.stack {
	display: flex;
	flex-direction: column;
	gap: var(--space-4);
}

.cluster {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--space-3);
}

.section-title {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	margin-bottom: var(--space-4);
}

.section-title h2,
.section-title h3 {
	margin: 0;
}

.section-title > .btn:last-child {
	margin-left: auto;
}

.login-shell {
	min-height: calc(100vh - 60px);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--space-5);
}

.login-card {
	width: 100%;
	max-width: 360px;
}

.login-card h1 {
	font-size: var(--font-size-h2);
	margin-bottom: var(--space-1);
}

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

.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-2);
	height: 40px;
	padding: 0 var(--space-4);
	border-radius: var(--radius-sm);
	border: 1px solid transparent;
	font-family: var(--font-sans);
	font-size: var(--font-size-small);
	font-weight: 500;
	cursor: pointer;
	text-decoration: none;
	transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

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

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

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

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

.btn-ghost {
	background: transparent;
	color: var(--color-accent);
	height: auto;
	padding: 0;
}

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

.btn-icon {
	width: 40px;
	padding: 0;
	background: transparent;
	border-color: var(--color-border);
	color: var(--color-ink-muted);
}

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

/* Anything tapped standing on the court grows to the touch minimum (see DESIGN.md). */
.btn-tap {
	min-height: var(--tap-target);
	min-width: var(--tap-target);
	touch-action: manipulation;
}

/* End of a list: the control stays visible but inert, so the row does not jump. */
.btn.is-disabled,
.btn:disabled {
	opacity: 0.45;
	pointer-events: none;
}

/* ---------- Forms ---------- */

.field {
	display: flex;
	flex-direction: column;
	gap: var(--space-2);
}

/* A group (label + control + help) is 8px apart inside, so it needs clearly more air
   outside or the help text reads as belonging to the next field. Summed with the
   16px gap of .stack this gives 24px, a 3:1 ratio. See DESIGN.md, "Espaciado". */
.field + .field {
	margin-top: var(--space-2);
}

/* Except when fields sit side by side, where the top margin would misalign them. */
.cluster > .field + .field {
	margin-top: 0;
}

.field label {
	font-size: var(--font-size-small);
	font-weight: 500;
}

.field .help {
	font-size: var(--font-size-caption);
	color: var(--color-ink-muted);
}

.field input,
.field select,
.field textarea {
	height: 40px;
	padding: 0 var(--space-3);
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: var(--font-size-body);
}

.field input[type='file'] {
	padding: var(--space-2) var(--space-3);
	height: auto;
	font-size: var(--font-size-small);
}

.field textarea {
	height: auto;
	/* ~6 lines: exercise descriptions and notes are real paragraphs, and the browser's
	   2-line default forces writing through a slit. */
	min-height: 144px;
	padding: var(--space-3);
	line-height: 1.5;
	/* Vertical only: resizing sideways breaks out of the card. */
	resize: vertical;
}

input[type='checkbox'],
input[type='radio'] {
	height: 16px;
	width: 16px;
	accent-color: var(--color-accent);
}

.field input:focus,
.field select:focus,
.field textarea:focus {
	outline: 2px solid var(--color-accent);
	outline-offset: -1px;
	border-color: var(--color-accent);
}

.field-check {
	flex-direction: row;
	align-items: center;
	gap: var(--space-2);
}

/* ---------- Card ---------- */

.card {
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-md);
	padding: var(--space-5);
}

/* Detail pages stack cards straight inside <main>, a block with no gap; without this
   the borders of two neighbouring cards read as a single box split by a line. */
.card + .card {
	margin-top: var(--space-4);
}

/* When the container already spaces its children, it does it, not the card. */
.stack > .card + .card,
.cluster > .card + .card,
.nav-grid > .card + .card {
	margin-top: 0;
}

/* A card that is also a link: no underline, inherits the text color and answers the
   pointer with the same 4% accent tint the table rows use. Cards that need another
   layout (.player-card is flex) override `display` on the base class only. */
.card-link {
	display: block;
	text-decoration: none;
	color: inherit;
	transition: background-color 0.12s ease, color 0.12s ease;
}

/* Only the color is repeated on hover (the global a:hover would tint the whole card):
   never `display` here, or a flex card (player cards) would snap to block on hover. */
.card-link:hover {
	text-decoration: none;
	color: inherit;
}

.card-link:hover {
	background: color-mix(in srgb, var(--color-accent) 4%, var(--color-surface));
}

/* The title does take the accent: together with the tint it is what makes the whole
   card read as a link rather than as a content panel. */
.card-link:hover h3 {
	color: var(--color-accent-hover);
}

.card-link p:last-child {
	margin-bottom: 0;
}

.nav-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: var(--space-4);
}

.nav-group + .nav-group {
	margin-top: var(--space-5);
}

.nav-group__title {
	font-size: var(--font-size-caption);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-ink-muted);
	font-weight: 500;
	margin: 0 0 var(--space-3);
}

/* ---------- Table ---------- */

.table-wrap {
	overflow-x: auto;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-md);
}

table.table-data {
	width: 100%;
	border-collapse: collapse;
	background: var(--color-surface);
}

.table-data th,
.table-data td {
	padding: var(--space-3) var(--space-4);
	text-align: left;
	border-bottom: 1px solid var(--color-border);
	font-size: var(--font-size-small);
}

.table-data th {
	font-size: var(--font-size-caption);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-ink-muted);
	font-weight: 500;
	position: sticky;
	top: 0;
	background: var(--color-surface);
}

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

.table-data tbody tr:hover {
	background: color-mix(in srgb, var(--color-accent) 4%, var(--color-surface));
}

/* Secondary line inside a cell, qualifying the main value. Not a pill (reserved for
   status) and not a tooltip (hidden from touch and keyboard). */
.table-data .cell-detail {
	display: block;
	margin-top: var(--space-1);
	font-family: var(--font-sans);
	font-size: var(--font-size-caption);
	color: var(--color-ink-muted);
	font-variant-numeric: normal;
}

.table-data td.numeric,
.table-data th.numeric {
	text-align: right;
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
}

/* ---------- Listing search and filters ---------- */

.listing-filters {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: var(--space-4);
	margin-bottom: var(--space-4);
}

.listing-filters__search {
	flex: 1 1 220px;
	min-width: 200px;
}

.listing-filters .field + .field {
	margin-top: 0;
}

.listing-filters__active {
	margin-bottom: var(--space-4);
}

/* An active criterion with its own cross to remove it. Fully rounded like the status
   pills — it is a loose tag, not a block — but bordered instead of filled so it is not
   mistaken for a status. */
.filter-chip {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	padding: var(--space-1) var(--space-3);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-pill);
	font-size: var(--font-size-small);
	color: var(--color-ink);
	text-decoration: none;
	transition: background-color 0.12s ease, border-color 0.12s ease;
}

.filter-chip:hover {
	background: color-mix(in srgb, var(--color-accent) 6%, var(--color-surface));
	border-color: var(--color-accent);
	color: var(--color-ink);
}

/* ---------- Pagination ---------- */

.pagination {
	display: flex;
	align-items: center;
	gap: var(--space-4);
	margin-top: var(--space-4);
}

/* The status sits in the middle and pushes both controls to the edges, so "Anterior"
   and "Siguiente" never move even when the text between them changes width. */
.pagination__status {
	flex: 1;
	margin: 0;
	text-align: center;
	font-size: var(--font-size-small);
}

/* ---------- Collapsible block (native <details>) ---------- */

.collapse {
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-md);
	overflow: hidden;
}

.collapse + .collapse {
	margin-top: var(--space-3);
}

.collapse__summary {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	padding: var(--space-3) var(--space-4);
	cursor: pointer;
	font-weight: 500;
	list-style: none;
}

.collapse__summary::-webkit-details-marker {
	display: none;
}

/* A triangle drawn with borders — not an emoji, not an icon font (see DESIGN.md). */
.collapse__summary::before {
	content: '';
	flex: none;
	width: 0;
	height: 0;
	border-left: 5px solid var(--color-ink-muted);
	border-top: 4px solid transparent;
	border-bottom: 4px solid transparent;
	transition: transform 0.12s ease;
}

.collapse[open] > .collapse__summary::before {
	transform: rotate(90deg);
}

.collapse__summary:hover {
	background: color-mix(in srgb, var(--color-accent) 4%, var(--color-surface));
}

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

.collapse__meta {
	margin-left: auto;
	font-size: var(--font-size-small);
	color: var(--color-ink-muted);
	font-weight: 400;
}

.collapse__body {
	border-top: 1px solid var(--color-border);
}

.collapse__empty {
	padding: var(--space-4);
	margin: 0;
	color: var(--color-ink-muted);
	font-size: var(--font-size-small);
}

/* ---------- Status pill ---------- */

.pill {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	height: 24px;
	padding: 0 var(--space-3);
	border-radius: var(--radius-pill);
	font-size: var(--font-size-caption);
	font-weight: 500;
	letter-spacing: 0.02em;
	white-space: nowrap;
}

.pill::before {
	content: '';
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: currentColor;
}

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

.pill-warning {
	background: var(--color-warning-bg);
	color: var(--color-warning);
}

.pill-critical {
	background: var(--color-critical-bg);
	color: var(--color-critical);
}

.pill-neutral {
	background: var(--color-bg);
	color: var(--color-ink-muted);
	border: 1px solid var(--color-border);
}

.pill-neutral::before {
	display: none;
}

/* Inline validation / flash message: a pill that is allowed to wrap. */
.notice {
	display: block;
	height: auto;
	white-space: normal;
	padding: var(--space-3) var(--space-4);
	border-radius: var(--radius-sm);
	font-size: var(--font-size-small);
	font-weight: 400;
	letter-spacing: 0;
}

.notice::before {
	display: none;
}

/* ---------- Avatar ---------- */

/* Player photo or team crest. A circle by sporting convention, not decoration; without
   a picture, the initials sit on the border color. */
.avatar {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 40px;
	height: 40px;
	border-radius: var(--radius-pill);
	background: var(--color-border);
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-weight: 500;
	font-size: var(--font-size-small);
	overflow: hidden;
	user-select: none;
}

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

.avatar--32 {
	width: 32px;
	height: 32px;
	font-size: var(--font-size-caption);
}

.avatar--64 {
	width: 64px;
	height: 64px;
	font-size: var(--font-size-h3);
}

.avatar--96 {
	width: 96px;
	height: 96px;
	font-size: var(--font-size-h2);
}

/* ---------- Player cards (squad listing) ---------- */

/* Cards rather than a table: the photo is what identifies a player at a glance on the
   court, and the whole card is the link to the player. */
.player-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
	gap: var(--space-4);
}

.player-grid > .card + .card {
	margin-top: 0;
}

.player-card {
	display: flex;
	align-items: center;
	gap: var(--space-4);
	min-height: var(--tap-target);
}

.player-card__body h3 {
	margin: 0 0 var(--space-1);
	font-size: var(--font-size-body);
	font-weight: 500;
}

/* ---------- Exercise cards and gallery editing ---------- */

.exercise-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
	gap: var(--space-4);
}

.exercise-grid > .card + .card {
	margin-top: 0;
}

.exercise-card {
	padding: 0;
	overflow: hidden;
}

.exercise-card__thumb {
	aspect-ratio: 4 / 3;
	background: var(--color-bg);
	border-bottom: 1px solid var(--color-border);
	display: flex;
	align-items: center;
	justify-content: center;
}

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

.exercise-card__body {
	padding: var(--space-4);
}

.exercise-card__body h3 {
	font-size: var(--font-size-body);
	margin-bottom: var(--space-1);
}

.exercise-card__excerpt {
	margin-bottom: var(--space-2);
}

/* Current images while editing: number, thumbnail, remove box, Up/Down. */
.image-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
}

.image-list__item {
	display: grid;
	grid-template-columns: 32px 96px 1fr auto;
	align-items: center;
	gap: var(--space-4);
	padding: var(--space-3) 0;
	border-top: 1px solid var(--color-border);
}

.image-list__item:first-child {
	border-top: 0;
}

.image-list__thumb {
	display: block;
	width: 96px;
	aspect-ratio: 4 / 3;
	border-radius: var(--radius-sm);
	border: 1px solid var(--color-border);
	overflow: hidden;
	background: var(--color-bg);
}

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

.image-list__remove {
	margin: 0;
}

.field__label {
	font-size: var(--font-size-small);
	font-weight: 500;
}

/* ---------- Roll call (tablet) ---------- */

.attendance {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
}

.attendance__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--space-3);
	padding: var(--space-3) 0;
	border-top: 1px solid var(--color-border);
}

.attendance__row:first-child {
	border-top: 0;
}

.attendance__player {
	display: inline-flex;
	align-items: center;
	gap: var(--space-3);
	min-height: var(--tap-target);
	color: var(--color-ink);
	text-decoration: none;
	font-weight: 500;
}

.attendance__notice {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	margin-bottom: var(--space-4);
}

.attendance__notice .btn {
	margin-left: auto;
	border-color: currentColor;
	color: inherit;
}

/* Three-way choice as one control: the selected segment takes its semantic color, the
   others stay quiet. Every segment is a full touch target. */
.segmented {
	display: inline-flex;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	overflow: hidden;
}

.segmented__button {
	min-height: var(--tap-target);
	min-width: var(--tap-target);
	padding: 0 var(--space-4);
	border: 0;
	border-left: 1px solid var(--color-border);
	background: var(--color-surface);
	color: var(--color-ink-muted);
	font-family: var(--font-sans);
	font-size: var(--font-size-small);
	font-weight: 500;
	cursor: pointer;
	touch-action: manipulation;
	transition: background-color 0.12s ease, color 0.12s ease;
}

.segmented__button:first-child {
	border-left: 0;
}

.segmented__button:hover {
	background: color-mix(in srgb, var(--color-ink) 4%, var(--color-surface));
}

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

.segmented__button--present.is-on {
	background: var(--color-success-bg);
	color: var(--color-success);
}

.segmented__button--absent.is-on {
	background: var(--color-critical-bg);
	color: var(--color-critical);
}

.segmented__button--excused.is-on {
	background: var(--color-warning-bg);
	color: var(--color-warning);
}

@media (max-width: 767px) {
	.segmented {
		width: 100%;
	}

	.segmented__button {
		flex: 1;
		padding: 0 var(--space-2);
	}
}

/* ---------- Half-court map (shot zones) ---------- */

/* See DESIGN.md, "Mapa de pista", and design/mockups/shot-chart.html. Units inside the
   SVG are court centimetres (viewBox 1500 × 1400); font sizes are in those units too. */
.court {
	width: 100%;
	height: auto;
	display: block;
	user-select: none;
	touch-action: manipulation;
	-webkit-tap-highlight-color: transparent;
}

.court *:focus {
	outline: none;
}

.court__floor {
	fill: var(--color-surface);
}

.court__shape {
	fill: color-mix(in srgb, var(--color-ink) 2%, var(--color-surface));
	stroke: var(--color-ink);
	stroke-opacity: 0.35;
	stroke-width: 5;
	stroke-linejoin: round;
	transition: fill 0.12s ease;
}

.court__zone[role='button'] .court__shape {
	cursor: pointer;
}

.court__zone[role='button']:hover .court__shape {
	fill: color-mix(in srgb, var(--color-accent) 7%, var(--color-surface));
}

.court__zone.has-value .court__shape {
	fill: var(--heat);
}

/* The selection border is the only signal on tap; the browser's own focus ring is
   suppressed (see DESIGN.md) and the keyboard gets a dashed accent stroke instead. */
.court__zone.is-selected .court__shape {
	stroke: var(--color-accent);
	stroke-opacity: 1;
	stroke-width: 14;
}

.court__zone:focus-visible .court__shape {
	stroke: var(--color-accent);
	stroke-opacity: 1;
	stroke-width: 12;
	stroke-dasharray: 28 14;
}

.court__lines {
	fill: none;
	stroke: var(--color-ink);
	stroke-opacity: 0.75;
	stroke-width: 8;
	stroke-linecap: round;
	stroke-linejoin: round;
	pointer-events: none;
}

.court__board {
	stroke-width: 12;
}

.court__rim {
	fill: none;
	stroke: var(--color-accent);
	stroke-width: 8;
	pointer-events: none;
}

.court__labels {
	pointer-events: none;
}

.court__name {
	font-family: var(--font-sans);
	font-size: 34px;
	font-weight: 500;
	fill: var(--color-ink-muted);
	text-anchor: middle;
	text-transform: uppercase;
	letter-spacing: 1px;
}

.court__value {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: 64px;
	font-weight: 500;
	fill: var(--color-ink);
	text-anchor: middle;
}

.court__pct {
	font-family: var(--font-mono);
	font-size: 40px;
	fill: var(--color-ink-muted);
	text-anchor: middle;
}

.court__label.is-small .court__value {
	font-size: 44px;
}

.court__label.is-small .court__pct {
	font-size: 30px;
}

.court__label.is-small .court__name {
	font-size: 26px;
}

.court__label.is-inline .court__value {
	font-size: 36px;
}

.court__label.is-inline .court__name {
	font-size: 26px;
}

/* ---------- Shot chart recording (tablet) ---------- */

.shot-status {
	margin-left: auto;
	display: flex;
	align-items: center;
	gap: var(--space-4);
	font-size: var(--font-size-small);
}

.shot-saved {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	color: var(--color-success);
}

/* Map on the left, panel on the right; stacked on a tablet in portrait. */
.shot-record {
	display: grid;
	grid-template-columns: minmax(0, 1.15fr) minmax(300px, 0.85fr);
	gap: var(--space-5);
	align-items: start;
	margin-top: var(--space-4);
}

.shot-record > .card + .card {
	margin-top: 0;
}

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

.court-card {
	padding: var(--space-4);
}

.shot-entry {
	display: flex;
	flex-direction: column;
	gap: var(--space-5);
}

.shot-entry .field + .field {
	margin-top: 0;
}

.shot-entry__zone {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: var(--space-3);
}

.shot-entry__name {
	font-size: var(--font-size-h3);
	font-weight: 600;
}

.shot-entry__new {
	margin-left: auto;
}

.shot-entry__presets {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2);
}

.shot-entry__presets .btn.is-on {
	border-color: var(--color-accent);
	color: var(--color-accent);
	background: color-mix(in srgb, var(--color-accent) 6%, var(--color-surface));
}

.counter--small .counter__button {
	width: var(--tap-target);
	height: var(--tap-target);
	font-size: 1.25rem;
}

.counter--small .counter__value {
	min-width: 64px;
	font-size: var(--font-size-h2);
}

.shot-entry__result {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	padding-top: var(--space-4);
	border-top: 1px solid var(--color-border);
}

.shot-entry__pct {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: var(--font-size-h2);
	font-weight: 500;
}

.shot-entries__title {
	font-size: var(--font-size-body);
	margin: var(--space-5) 0 0;
}

.shot-entries {
	list-style: none;
	margin: var(--space-3) 0 0;
	padding: 0;
}

.shot-entries__item {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto auto auto auto;
	align-items: center;
	gap: var(--space-3);
	padding: var(--space-2) 0;
	border-top: 1px solid var(--color-border);
	min-height: var(--tap-target);
}

.shot-entries__item.is-current {
	background: color-mix(in srgb, var(--color-accent) 4%, var(--color-surface));
	margin: 0 calc(var(--space-5) * -1);
	padding-left: var(--space-5);
	padding-right: var(--space-5);
}

.shot-entries__name {
	text-align: left;
	background: none;
	border: 0;
	padding: 0;
	min-height: var(--tap-target);
	font-family: var(--font-sans);
	font-size: var(--font-size-body);
	font-weight: 500;
	color: var(--color-ink);
	cursor: pointer;
}

.shot-entries__name small {
	display: block;
	font-weight: 400;
	font-size: var(--font-size-caption);
	color: var(--color-ink-muted);
}

.shot-entries__ratio {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
}

.shot-entries__pct {
	font-family: var(--font-mono);
	color: var(--color-ink-muted);
	min-width: 64px;
	text-align: right;
}

.shot-entries__delete {
	width: var(--tap-target);
	height: var(--tap-target);
	padding: 0;
}

.shot-entries__edit {
	height: var(--tap-target);
}

.shot-entries__edit:disabled {
	opacity: 1;
	border-color: var(--color-accent);
	color: var(--color-accent);
	background: color-mix(in srgb, var(--color-accent) 6%, var(--color-surface));
}

.shot-entries__empty {
	padding: var(--space-2) 0;
}

.player-chip__count {
	font-family: var(--font-mono);
	font-size: var(--font-size-caption);
	color: var(--color-ink-muted);
	margin-left: var(--space-1);
}

/* Summary of a chart: series rows carry a correction form. */
.shot-entries__item--edit {
	grid-template-columns: minmax(0, 1fr) auto auto auto;
}

.shot-entries__input {
	width: 72px;
	height: 40px;
	padding: 0 var(--space-2);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	background: var(--color-surface);
	color: var(--color-ink);
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: var(--font-size-body);
	text-align: right;
}

.table-data tr.is-selected td {
	background: color-mix(in srgb, var(--color-accent) 6%, var(--color-surface));
}

.table-data th a {
	color: inherit;
	text-decoration: none;
}

.table-data th a[aria-current='true'] {
	color: var(--color-accent);
}

@media (max-width: 767px) {
	.shot-entries__item--edit {
		grid-template-columns: 1fr auto;
	}

	.shot-entries__item--edit form.cluster {
		grid-column: 1 / -1;
	}
}

/* ---------- Player chip (tablet) ---------- */

/* Row of players above the shot chart: one tap selects who is shooting. */
.player-chips {
	display: flex;
	gap: var(--space-2);
	overflow-x: auto;
	padding-bottom: var(--space-2);
	scrollbar-width: thin;
}

.player-chip {
	flex: none;
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	min-height: var(--tap-target);
	padding: var(--space-1) var(--space-3) var(--space-1) var(--space-1);
	border: 2px solid var(--color-border);
	border-radius: var(--radius-pill);
	background: var(--color-surface);
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: var(--font-size-body);
	cursor: pointer;
	user-select: none;
	touch-action: manipulation;
	transition: border-color 0.12s ease, background-color 0.12s ease;
}

.player-chip:hover {
	border-color: var(--color-ink-muted);
}

/* With a saturated red, more than 6% tints the chip too much. */
.player-chip.is-selected {
	border-color: var(--color-accent);
	background: color-mix(in srgb, var(--color-accent) 6%, var(--color-surface));
}

.player-chip .pill {
	margin-left: var(--space-1);
}

/* ---------- Counter (tablet) ---------- */

/* [−] [made / attempts] [+]. Buttons at the counter touch size; the figure large enough
   to read standing up with the tablet in one hand. Driven by counter_controller.js (#13). */
.counter {
	display: inline-flex;
	align-items: center;
	gap: var(--space-3);
}

.counter__button {
	width: var(--tap-target-counter);
	height: var(--tap-target-counter);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	background: var(--color-surface);
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: 1.5rem;
	line-height: 1;
	cursor: pointer;
	touch-action: manipulation;
	transition: background-color 0.12s ease, border-color 0.12s ease;
}

.counter__button:hover {
	background: color-mix(in srgb, var(--color-accent) 6%, var(--color-surface));
	border-color: var(--color-accent);
}

/* Disabled at 0 and at the attempts cap: faded, never removed, so the buttons never move. */
.counter__button:disabled {
	opacity: 0.4;
	cursor: default;
	background: var(--color-surface);
	border-color: var(--color-border);
}

.counter__value {
	min-width: 120px;
	text-align: center;
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: var(--font-size-counter);
	font-weight: 500;
	line-height: 1;
	user-select: none;
}

.counter__value small {
	font-size: var(--font-size-h3);
	font-weight: 400;
	color: var(--color-ink-muted);
}

/* One row per zone on the recording screen: thumbnail, title, counter. */
.zone-row {
	display: grid;
	grid-template-columns: 96px 1fr auto;
	align-items: center;
	gap: var(--space-5);
	padding: var(--space-4) 0;
	border-top: 1px solid var(--color-border);
	user-select: none;
}

.zone-row:first-child {
	border-top: 0;
}

/* Not yet recorded for this player: flagged with the warning tint, plus a text label. */
.zone-row.is-unrecorded {
	background: var(--color-warning-bg);
	margin: 0 calc(var(--space-5) * -1);
	padding-left: var(--space-5);
	padding-right: var(--space-5);
}

.zone-row__image {
	width: 96px;
	aspect-ratio: 4 / 3;
	border-radius: var(--radius-md);
	border: 1px solid var(--color-border);
	background: var(--color-bg);
	overflow: hidden;
}

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

.zone-row__title {
	font-weight: 500;
}

.zone-row__meta {
	margin: 0;
	font-size: var(--font-size-small);
	color: var(--color-ink-muted);
}

@media (max-width: 767px) {
	.zone-row {
		grid-template-columns: 72px 1fr;
		row-gap: var(--space-3);
	}

	.zone-row .counter {
		grid-column: 1 / -1;
		justify-content: flex-end;
	}
}

/* ---------- Exercise sequence ---------- */

/* An ordered list where the number is real information: the order of the session. */
.sequence {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
}

.sequence__item {
	display: grid;
	grid-template-columns: 40px 1fr auto auto;
	align-items: center;
	gap: var(--space-4);
	padding: var(--space-3) 0;
	border-top: 1px solid var(--color-border);
}

.sequence__item:first-child {
	border-top: 0;
}

.sequence__item.is-dragging {
	opacity: 0.5;
}

.sequence__number {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	color: var(--color-ink-muted);
}

.sequence__title {
	font-weight: 500;
}

.sequence__title a {
	color: inherit;
	text-decoration: none;
}

.sequence__title a:hover {
	color: var(--color-accent);
}

.sequence__meta {
	margin: 0;
	font-size: var(--font-size-small);
	color: var(--color-ink-muted);
}

.sequence__duration {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	color: var(--color-ink-muted);
	white-space: nowrap;
}

/* Drag handle plus always-visible Up/Down buttons: drag is unreliable on touch, so the
   buttons are first-class, not a hidden fallback. */
.sequence__controls {
	display: flex;
	gap: var(--space-1);
}

.sequence__controls .btn {
	width: var(--tap-target);
	height: var(--tap-target);
	padding: 0;
}

.sequence__handle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: var(--tap-target);
	height: var(--tap-target);
	color: var(--color-ink-muted);
	cursor: grab;
	touch-action: none;
}

@media (max-width: 767px) {
	.sequence__item {
		grid-template-columns: 32px 1fr;
		row-gap: var(--space-2);
	}

	.sequence__duration,
	.sequence__controls {
		grid-column: 2;
		justify-self: end;
	}
}

/* Dragging a row (sortable controller): the row being moved fades, the drop target
   shows a top border in accent. */
.sequence__item[draggable='true'] {
	cursor: default;
}

.sequence__item.is-drop-target {
	box-shadow: inset 0 3px 0 var(--color-accent);
}

/* Per-row notes/duration editor, a native <details> under the title. */
.sequence__editor {
	grid-column: 2 / -1;
}

.sequence__editor summary {
	cursor: pointer;
	font-size: var(--font-size-small);
	color: var(--color-accent);
	list-style: none;
}

.sequence__editor summary::-webkit-details-marker {
	display: none;
}

.sequence__editor form {
	margin-top: var(--space-3);
}

.sequence__editor .field input[type='number'] {
	max-width: 120px;
}

.sequence__summary {
	font-size: var(--font-size-small);
	color: var(--color-ink-muted);
}

/* "Add exercise" dialog: a search box, results as tappable rows, and a "create new" form. */
.modal--picker {
	width: min(640px, calc(100vw - var(--space-6)));
	max-height: calc(100vh - var(--space-8));
	overflow-y: auto;
}

.picker__tabs {
	display: flex;
	gap: var(--space-2);
	margin-bottom: var(--space-4);
}

.picker__results {
	list-style: none;
	margin: var(--space-3) 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
}

.picker__result {
	display: grid;
	grid-template-columns: 64px 1fr auto;
	align-items: center;
	gap: var(--space-3);
	padding: var(--space-2) 0;
	border-top: 1px solid var(--color-border);
}

.picker__result:first-child {
	border-top: 0;
}

.picker__thumb {
	width: 64px;
	aspect-ratio: 4 / 3;
	border-radius: var(--radius-sm);
	border: 1px solid var(--color-border);
	background: var(--color-bg);
	overflow: hidden;
}

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

.picker__title {
	font-weight: 500;
}

.picker__excerpt {
	margin: 0;
	font-size: var(--font-size-caption);
	color: var(--color-ink-muted);
}

.picker__empty {
	margin: var(--space-3) 0 0;
	font-size: var(--font-size-small);
	color: var(--color-ink-muted);
}

/* ---------- Markdown: editor and rendered text ---------- */

/* Rendered Markdown. Everything the converter can emit gets a tidy default. */
.prose {
	max-width: 65ch;
}

.prose > :first-child {
	margin-top: 0;
}

.prose > :last-child {
	margin-bottom: 0;
}

.prose p,
.prose ul,
.prose ol {
	margin: 0 0 var(--space-3);
}

.prose ul,
.prose ol {
	padding-left: 1.25em;
}

.prose li + li {
	margin-top: var(--space-1);
}

.prose h1,
.prose h2,
.prose h3,
.prose h4 {
	font-size: var(--font-size-h3);
	margin: var(--space-4) 0 var(--space-2);
}

.prose code {
	font-family: var(--font-mono);
	font-size: 0.9em;
	background: color-mix(in srgb, var(--color-ink) 5%, var(--color-surface));
	padding: 0 var(--space-1);
	border-radius: var(--radius-sm);
}

.prose blockquote {
	margin: 0 0 var(--space-3);
	padding-left: var(--space-3);
	border-left: 3px solid var(--color-border);
	color: var(--color-ink-muted);
}

/* Inside a sequence row or a table cell: smaller, tighter. */
.prose--compact {
	font-size: var(--font-size-small);
	color: var(--color-ink-muted);
}

.prose--compact p,
.prose--compact ul,
.prose--compact ol {
	margin-bottom: var(--space-1);
}

/* The editor: tabs + toolbar above the textarea, preview in its place. */
.markdown-editor {
	display: flex;
	flex-direction: column;
	gap: var(--space-2);
}

.markdown-editor__bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--space-2);
}

.markdown-editor__tabs {
	margin-bottom: 0;
}

.markdown-editor__tabs .btn,
.markdown-editor__toolbar .btn {
	height: 36px;
	min-height: 36px;
}

.markdown-editor__toolbar {
	display: flex;
	gap: var(--space-1);
}

.markdown-editor__toolbar .btn {
	width: 36px;
	color: var(--color-ink);
}

.markdown-editor textarea {
	width: 100%;
	min-height: 120px;
	resize: vertical;
	overflow: hidden;
}

.markdown-editor__preview {
	min-height: 120px;
	padding: var(--space-3);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	background: color-mix(in srgb, var(--color-ink) 2%, var(--color-surface));
}

/* ---------- Gallery ---------- */

.gallery {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
	gap: var(--space-3);
}

.gallery__item {
	display: block;
	aspect-ratio: 4 / 3;
	border-radius: var(--radius-md);
	border: 1px solid var(--color-border);
	overflow: hidden;
	background: var(--color-bg);
	padding: 0;
	cursor: zoom-in;
}

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

/* ---------- Theme toggle ---------- */

.theme-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: var(--radius-sm);
	border: 1px solid var(--color-border);
	background: transparent;
	color: var(--color-ink-muted);
	cursor: pointer;
}

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

/* ---------- Modal (native <dialog>, driven by confirm_controller.js) ---------- */

.modal {
	width: min(420px, calc(100vw - var(--space-6)));
	padding: var(--space-5);
	background: var(--color-surface);
	color: var(--color-ink);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-md);
	/* A real floating element, so this is one of the few places we use a shadow. */
	box-shadow: var(--shadow-overlay);
}

.modal::backdrop {
	background: rgba(0, 0, 0, 0.45);
}

.modal-title {
	margin: 0 0 var(--space-3);
	font-size: var(--font-size-h3);
}

.modal-body {
	margin: 0 0 var(--space-5);
	color: var(--color-ink-muted);
}

.modal-actions {
	display: flex;
	justify-content: flex-end;
	gap: var(--space-3);
}

/* Full-size image viewer (gallery), same element, wider. */
.modal--image {
	width: min(1200px, calc(100vw - var(--space-6)));
	padding: var(--space-3);
}

.modal--image img {
	width: 100%;
	height: auto;
	border-radius: var(--radius-sm);
}
