body {
	background: #17130e;
	margin: 0;
}

h1:focus {
	outline: none;
}

.valid.modified:not([type=checkbox]) {
	outline: 1px solid #26b050;
}

.invalid {
	outline: 1px solid #e50000;
}

.validation-message {
	color: #e50000;
}

.blazor-error-boundary {
	background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
	padding: 1rem 1rem 1rem 3.7rem;
	color: white;
}

	.blazor-error-boundary::after {
		content: "An error has occurred."
	}

.darker-border-checkbox.form-check-input {
	border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
	color: var(--bs-secondary-color);
	text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
	text-align: start;
}


/* ************************************************************ */
/* This is a complete copy of home.razor.css */
/* ************************************************************ */


/* NOTE: these custom properties live on .rbb-page (the component's real
   root element), not :root — Blazor's CSS isolation appends a scope
   attribute to rendered elements but never to <html>, so a `:root { }`
   rule in a scoped .razor.css file silently never matches anything and
   every var() using it would fall back to unset. Descendants still
   inherit these normally regardless of scoping. */
.rbb-page {
	--ink: #17130e;
	--ink-2: #1f1a12;
	--paper: #ede3ce;
	--paper-dim: #c9bc9e;
	--amber: #e8a33d;
	--amber-dim: #a97527;
	--rust: #c24a2b;
	--teal: #3f6e64;
	--sky: #7ec8e8;
	--line: rgba(237,227,206,0.14);
	--display: 'Anton', 'Barlow Condensed', sans-serif;
	--cond: 'Barlow Condensed', sans-serif;
	--body: 'Barlow', sans-serif;
	--mono: 'Space Mono', monospace;
	/* Nav + scrolling stack laid out as a flex column filling the viewport.
	   The nav is a `flex: 0 0 auto` item sized to whatever content it
	   needs (one row, two rows, however many) and .page-scroll is
	   `flex: 1 1 auto`, so it always gets exactly "the rest of the
	   screen" from the browser's own layout — no nav height is ever
	   measured or hardcoded anywhere. */
	display: flex;
	flex-direction: column;
	height: 100vh;
}

a {
	color: inherit;
	text-decoration: none;
}

::selection {
	background: var(--rust);
	color: var(--paper);
}

img {
	max-width: 100%;
	display: block;
}

/* ---------- utility ---------- */
.wrap {
	max-width: 1280px;
	margin: 0 auto;
	padding: 0 32px;
}

.eyebrow {
	font-family: var(--mono);
	font-size: 24px;
	letter-spacing: 0.28em;
	text-transform: uppercase;
	color: var(--amber);
}

.kicker-line {
	display: flex;
	align-items: center;
	gap: 14px;
	margin-bottom: 22px;
}

	.kicker-line::after {
		content: "";
		flex: 1;
		height: 1px;
		background: var(--line);
	}

.btn {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-family: var(--cond);
	font-weight: 700;
	font-size: 16px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	padding: 14px 26px;
	border: 2px solid var(--paper);
	color: var(--paper);
	background: transparent;
	cursor: pointer;
	transition: transform .15s ease, background .15s ease, color .15s ease;
}

	.btn:hover {
		transform: translateY(-2px);
	}

	.btn.solid {
		background: var(--rust);
		border-color: var(--rust);
		color: var(--paper);
	}

		.btn.solid:hover {
			background: #a83c21;
		}

/* ---------- nav ---------- */
/* A plain flex column item (see .rbb-page) sized to its own content —
   never scrolls, because scrolling happens inside .page-scroll below it,
   not on the page itself. Its height is whatever it needs to be (one row,
   two rows...); nothing else needs to know that number. */
.site-nav {
	flex: 0 0 auto;
	z-index: 99999;
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	row-gap: 8px;
	column-gap: 24px;
	padding: 18px 32px;
	background: linear-gradient(to bottom, rgba(23,19,14,0.94), rgba(23,19,14,0.8) 70%, transparent);
}

.brand-mark {
	font-family: var(--display);
	font-size: clamp(26px, 4.4vw, 60px);
	letter-spacing: 0.02em;
	color: var(--paper);
	/* Only wraps once its own content needs more than 40% of the nav's width;
     shorter content simply shrink-wraps and stays on one line. */
	flex: 0 1 40%;
	max-width: 40%;
	min-width: 0;
}

	.brand-mark a {
		display: flex;
		align-items: center;
		gap: 12px;
		line-height: 1.05;
		white-space: normal;
		overflow-wrap: break-word;
	}

/* Ensure the brand mark image and name sit on the same row */
.brand-mark {
	display: flex;
	align-items: center;
	gap: 12px;
}

	.brand-mark .brand-logo {
		height: clamp(26px, 4.4vw, 60px);
		width: auto;
		display: inline-block;
		vertical-align: middle;
	}

	.brand-mark span {
		color: var(--amber);
	}

/* nav-links always fits: individual links never break mid-word, the group
   wraps to new rows as whole links when space runs out. */
.nav-links {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	align-items: center;
	gap: 12px 28px;
	flex: 1 1 auto;
	min-width: 0;
	font-family: var(--cond);
	font-weight: 600;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	font-size: clamp(13px, 1.5vw, 15px);
}

	.nav-links a {
		white-space: nowrap;
		opacity: 0.85;
		border-bottom: 2px solid transparent;
		padding-bottom: 4px;
		transition: opacity .15s, border-color .15s;
	}

		.nav-links a:hover {
			opacity: 1;
			border-color: var(--amber);
		}

/* ---------- stacked-card scroll effect ----------
   Every top-level section is `position: sticky` and exactly one viewport
   tall. Because they all share the same normal-flow containing block, each
   one locks in place as it reaches the top, and the *next* section (later
   in the DOM, so it always paints above) slides up from below to cover it
   as the user keeps scrolling. Pure CSS, driven only by native scroll.
   Each section's `top` offset just needs to match the nav's real rendered
   height so a pinned section stops exactly below the nav rather than
   sliding underneath it. */
.page-scroll {
	flex: 1 1 auto;
	min-height: 0; /* required so a flex child can actually be a scroll container */
	overflow-y: auto;
	position: relative;
}

.sticky-section {
	position: sticky;
	top: 0;
	height: 100%;
	overflow-y: auto;
}

/* A zero-height, non-sticky marker placed right before each section, used
   as the actual `id` target for nav links instead of the section itself.
   Necessary because our sticky sections never truly "release" — an
   earlier section stays position:sticky (just visually covered by later
   ones) for as long as you keep scrolling, so its bounding box always
   reads as "already on screen" to the browser's/Blazor's scroll-into-view
   logic. That makes jumping to it a no-op once you've scrolled past it —
   exactly the "nav links only work going forward" bug. This marker is a
   plain, non-positioned element, so its position always reflects genuine
   scroll distance and scrolling to it works reliably in both directions. */
.section-anchor {
	display: block;
	height: 0;
}

/* Top-aligned, not centered: with justify-content:center, a section's
   content sits at a different vertical offset depending on how tall that
   section's own content happens to be relative to the viewport — About
   (short) and Booking (tall) would each start their title at a different
   height. Top-aligning makes every section's content begin at the same
   fixed offset below the nav, regardless of content length. Hero keeps
   its own centered treatment below, since it reads better as a banner. */
.sticky-section .wrap {
	min-height: 100%;
	display: flex;
	flex-direction: column;
	justify-content: flex-start;
	padding: 48px 32px;
}

.hero .wrap {
	justify-content: center;
}

/* ---------- hero ---------- */
.hero {
	/* No position here on purpose: .sticky-section already sets
     position:sticky, which is a perfectly valid containing block for the
     absolutely-positioned .hero-layer children below. This rule used to
     also set position:relative — same specificity as .sticky-section and
     later in the file, so it silently won and cancelled the sticky
     positioning entirely. overflow:hidden clips the layers' -10% bleed on
     every edge; hero's own content is short and always fits one screen,
     so it never needs to grow past min-height:100% the way About does. */
	overflow: hidden;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	isolation: isolate;
}

.hero-layer {
	position: absolute;
	inset: -10% -10%;
}

.layer-wash {
	background: radial-gradient(ellipse 60% 45% at 50% 34%, rgba(232,163,61,0.28), transparent 65%), linear-gradient(180deg, #201a12 0%, #17130e 55%, #100d09 100%);
	z-index: 0;
}

.layer-rays {
	z-index: 1;
	background: repeating-conic-gradient(from 200deg at 50% 8%, rgba(232,163,61,0.10) 0deg 6deg, transparent 6deg 16deg);
	mix-blend-mode: screen;
	opacity: 0.7;
}

.layer-smoke {
	z-index: 2;
	background: radial-gradient(ellipse 40% 30% at 20% 70%, rgba(60,50,38,0.55), transparent 70%), radial-gradient(ellipse 45% 32% at 85% 75%, rgba(60,50,38,0.5), transparent 70%);
	filter: blur(2px);
}

.layer-grain {
	z-index: 3;
	opacity: 0.05;
	background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

.hero-content {
	position: relative;
	z-index: 5;
	padding: 0 24px;
	width: 100%;
	max-width: 1280px; /* constrain hero content to the site's content width */
	margin: 0 auto;
	box-sizing: border-box;
}

.hero-eyebrow {
	font-family: var(--mono);
	font-size: 20px;
	letter-spacing: 0.3em;
	text-transform: uppercase;
	color: var(--amber);
	margin-bottom: 18px;
}

/* Carousel: always at least 70% of the viewport tall, images crossfade
   automatically via CSS animation (see the @keyframes in Home.razor,
   computed from the slide count) — no JavaScript. */
.hero-carousel {
	position: relative;
	width: 100%;
	max-width: 1280px; /* keep carousel within the global content width */
	height: 70vh;
	min-height: 70vh;
	margin: 0 auto;
	filter: drop-shadow(0 0 46px rgba(232,163,61,0.35));
}

.hero-slide {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
	object-position: center center;
	opacity: 0;
	pointer-events: none; /* only the active slide (see @keyframes) can be clicked */
	cursor: pointer;
	animation-name: rbb-hero-cycle;
	animation-iteration-count: infinite;
	animation-timing-function: ease-in-out;
}

.hero-sub {
	max-width: 1280px;
	margin: 26px auto 0;
	font-size: 22px;
	line-height: 1.6;
	color: var(--paper-dim);
}

/* ---------- section frame ---------- */
section {
	position: relative;
}

.section-title {
	font-family: var(--display);
	font-size: clamp(34px, 5vw, 56px);
	line-height: 1;
	margin-bottom: 8px;
	color: var(--paper);
}

	.section-title em {
		font-style: normal;
		color: var(--amber);
	}

.section-icon {
	display: inline-block;
	margin-right: 0.3em;
	font-size: 0.9em;
	vertical-align: baseline;
}

/* ---------- about ---------- */
.about {
	background: var(--ink);
}

.about-grid {
	display: grid;
	grid-template-columns: 1.1fr 0.9fr;
	gap: 56px;
	align-items: center;
	padding-bottom: 64px;
	border-bottom: 1px solid var(--line);
}

.experience-lede {
	font-family: var(--cond);
	font-weight: 600;
	font-size: clamp(22px, 2.6vw, 30px);
	line-height: 1.3;
	color: var(--paper);
}

.experience-body p {
	font-size: 20px;
	line-height: 1.8;
	color: var(--paper-dim);
	margin-bottom: 14px;
}

	.experience-body p:last-child {
		margin-bottom: 0;
		color: var(--amber);
		font-family: var(--cond);
		font-weight: 600;
		font-size: 24px;
	}

/* Stacked, crossfading images (same .hero-slide class/animation as the
   hero) need a sized, positioned container to anchor to, since absolutely
   positioned children don't otherwise contribute to a parent's height. */
.about-photo {
	position: relative;
	aspect-ratio: 4/3;
	min-height: 320px;
	filter: drop-shadow(0 20px 45px rgba(0,0,0,0.5)) drop-shadow(0 0 40px rgba(232,163,61,0.2));
}

/* ---------- players ---------- */
.players {
	background: var(--ink);
}

	.players .wrap {
		max-width: 1600px;
	}

/* Responsive player-card grid: 2x2 by default, drops to a single column
   (1x4) on narrow screens and can open up to a single row (4x1) on very
   wide ones, purely from available space. */
.passes {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
	gap: 32px;
}

.pass {
	position: relative;
	background: var(--paper);
	color: var(--ink);
	padding: 40px 30px 30px;
	box-shadow: 0 24px 50px rgba(0,0,0,0.4);
	cursor: pointer;
	transition: transform .2s ease;
}

	.pass:hover {
		transform: translateY(-4px);
	}

.pass-hole {
	position: absolute;
	top: 16px;
	left: 50%;
	transform: translateX(-50%);
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: var(--ink);
	box-shadow: 0 0 0 3px var(--paper-dim) inset;
}

.player-card-photo {
	position: relative;
	display: block;
	width: 100%;
	aspect-ratio: 4/3;
	border: 3px solid #1a1a1a;
	box-shadow: 4px 6px 12px rgba(0,0,0,0.5);
	overflow: hidden;
	background: #000;
	margin-bottom: 20px;
}
/* Same crossfade technique as .hero-slide (see rbb-player-cycle in
   Home.razor), but object-fit:cover instead of contain — these are
   portrait/candid shots meant to fill the card frame, not a banner where
   nothing can be cropped. */
.card-slide {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: top center; /* crop from the bottom, not the middle — most of these are tall portraits where centering cuts off faces */
	opacity: 0;
	pointer-events: none;
	cursor: pointer;
	animation-name: rbb-player-cycle;
	animation-iteration-count: infinite;
	animation-timing-function: ease-in-out;
}

.pass-name {
	font-family: var(--display);
	font-weight: 400;
	font-size: 44px;
	text-align: center;
	line-height: 1;
	margin-bottom: 8px;
}

.pass-role {
	display: block;
	text-align: center;
	font-family: var(--mono);
	font-size: 13px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--amber-dim);
	margin-bottom: 20px;
	padding-bottom: 20px;
	border-bottom: 1px dashed rgba(23,19,14,0.2);
}

	.pass-role em {
		font-style: normal;
		color: var(--rust);
	}

.pass-bio {
	font-size: 18px;
	line-height: 1.75;
	color: #2a2419;
	text-align: center;
}

.lightbox-overlay {
	position: fixed;
	inset: 0;
	width: 100vw;
	height: 100vh;
	background: rgba(0,0,0,0.9);
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 100000;
	cursor: pointer;
}

.lightbox-image {
	max-width: 90vw;
	max-height: 90vh;
	box-shadow: 0 0 30px rgba(0,0,0,0.8);
}

/* ---------- tour ---------- */
.tour {
	background: var(--ink-2);
	border-top: 1px solid var(--line);
	border-bottom: 1px solid var(--line);
}

.stub-group-title {
	font-family: var(--cond);
	font-weight: 700;
	font-size: 15px;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--amber);
	margin: 0 0 18px;
	padding-bottom: 10px;
	border-bottom: 2px solid var(--amber);
}

	.stub-group-title:not(:first-child) {
		margin-top: 40px;
	}

.stub-list {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.stub {
	display: grid;
	grid-template-columns: 120px 1fr auto 140px;
	align-items: center;
	gap: 24px;
	background: rgba(237,227,206,0.03);
	border: 1px dashed var(--line);
	padding: 22px 26px;
	position: relative;
}

	.stub::before, .stub::after {
		content: "";
		position: absolute;
		top: 50%;
		transform: translateY(-50%);
		width: 18px;
		height: 18px;
		border-radius: 50%;
		background: var(--ink-2);
	}

	.stub::before {
		left: -9px;
	}

	.stub::after {
		right: -9px;
	}

	.stub .date {
		font-family: var(--mono);
		font-size: 15px;
		color: var(--amber);
	}

		.stub .date .day {
			display: block;
			font-family: var(--display);
			font-size: 30px;
			color: var(--paper);
			line-height: 1;
			margin-bottom: 4px;
		}

	.stub .venue {
		font-family: var(--cond);
		font-weight: 700;
		font-size: 20px;
		color: var(--paper);
	}

	.stub .city {
		font-size: 13px;
		color: var(--paper-dim);
		margin-top: 2px;
	}

	.stub .tag {
		font-family: var(--mono);
		font-size: 11px;
		letter-spacing: 0.12em;
		text-transform: uppercase;
		color: var(--teal);
		border: 1px solid var(--teal);
		padding: 5px 10px;
		justify-self: end;
		/* Neither group has a 4th "Tickets" button column anymore, so the tag
     spans into that leftover track — otherwise justify-self:end just
     aligns it within its own auto-sized column, which is already snug
     around the text and barely moves. */
		grid-column: 3 / -1;
	}

/* Past shows read as history rather than something actionable. */
.stub-past {
	opacity: 0.6;
}

/* ---------- setlist / chalkboard ---------- */
.setlist {
	background: var(--ink);
}

.chalkboard {
	background: #14201c;
	border: 10px solid #3a2a1c;
	padding: 44px 40px;
	box-shadow: inset 0 0 60px rgba(0,0,0,0.5);
}

.chalk-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 36px 56px;
}

.chalk-cat h4 {
	font-family: var(--cond);
	font-weight: 700;
	font-size: 15px;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--amber);
	margin-bottom: 14px;
	padding-bottom: 10px;
	border-bottom: 1px dashed rgba(237,227,206,0.25);
}

.chalk-cat ul {
	list-style: none;
	font-family: var(--mono);
	font-size: 15px;
	color: var(--paper-dim);
	line-height: 2.1;
}

	.chalk-cat ul li::before {
		content: "\2014  ";
		color: var(--rust);
	}

/* ---------- gallery ---------- */
.gallery {
	background: var(--ink-2);
	border-top: 1px solid var(--line);
}

.video-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 24px;
}

.video-card {
	background: #000;
	border: 1px solid var(--line);
}

	.video-card video {
		display: block;
		width: 100%;
		aspect-ratio: 16/9;
		background: #000;
	}

.video-title {
	display: block;
	padding: 14px 16px;
	font-family: var(--mono);
	font-size: 12px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--paper-dim);
	border-top: 1px solid var(--line);
}

/* ---------- booking / footer ---------- */
.booking {
	background: #100d09;
}

.booking-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 64px;
}

.field {
	margin-bottom: 24px;
}

	.field label {
		display: block;
		font-family: var(--mono);
		font-size: 12px;
		letter-spacing: 0.14em;
		text-transform: uppercase;
		color: var(--paper-dim);
		margin-bottom: 10px;
	}
	/* InputText/InputTextArea render their <input>/<textarea> from inside a
   child component, not this component's own markup, so Blazor's CSS
   isolation never stamps them with this file's scope attribute — a plain
   `.field input` selector silently matches nothing. `::deep` opts back
   into matching descendants regardless of which component rendered them. */
/*	.field ::deep input, .field ::deep textarea {
		width: 100%;
		background: rgba(237,227,206,0.04);
		border: 1.5px solid var(--sky);
		border-radius: 4px;
		color: var(--paper);
		font-family: var(--body);
		font-size: 18px;
		padding: 16px 18px;
		box-sizing: border-box;
	}

		.field ::deep input:focus, .field ::deep textarea:focus {
			outline: none;
			border-color: var(--amber);
		}

	.field ::deep textarea {
		resize: vertical;
		min-height: 240px;
	}
*/
.form-status {
	margin-top: 14px;
	font-family: var(--mono);
	font-size: 13px;
	letter-spacing: 0.04em;
	color: var(--teal);
}

.fieldWarning {
	font-family: var(--mono);
	font-size: 12px;
	letter-spacing: 0.04em;
	color: var(--rust);
	margin-top: 6px;
}

/* Visual highlight when a field is flagged as warning. Applied to the
   input/textarea element by adding the class name to the control. */
/* For InputText/InputTextArea rendered inside child components we must
   use ::deep so the selector matches the actual input/textarea element
   even though it isn't stamped with this component's scope attribute. */
/*.field ::deep input.fieldWarning,
.field ::deep textarea.fieldWarning {
	background: rgba(194,74,43,0.04);*/ /* subtle tinted background */
	/*border: 1.5px solid var(--rust);
	box-shadow: 0 0 0 4px rgba(194,74,43,0.06);
	color: var(--rust);
	transition: box-shadow .12s ease, border-color .12s ease, background .12s ease;
}

	.field ::deep input.fieldWarning::placeholder,
	.field ::deep textarea.fieldWarning::placeholder {
		color: rgba(194,74,43,0.6);
	}*/

.contact-block {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
}

.contact-info a {
	display: block;
	font-family: var(--cond);
	font-weight: 700;
	font-size: 26px;
	margin-bottom: 6px;
}

	.contact-info a:hover {
		color: var(--amber);
	}

.socials {
	display: flex;
	gap: 18px;
	margin-top: 26px;
}

	.socials a {
		font-family: var(--mono);
		font-size: 12px;
		letter-spacing: 0.1em;
		text-transform: uppercase;
		border: 1px solid var(--line);
		padding: 8px 14px;
	}

		.socials a:hover {
			border-color: var(--amber);
			color: var(--amber);
		}

.footer-bottom {
	margin-top: 60px;
	padding-top: 26px;
	border-top: 1px solid var(--line);
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	flex-wrap: wrap;
	gap: 12px;
	font-family: var(--mono);
	font-size: 11px;
	letter-spacing: 0.08em;
	color: var(--paper-dim);
	text-transform: uppercase;
}

.footer-left {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

	.footer-left .socials {
		margin-top: 0;
	}

.form-status {
	margin-top: 16px;
	padding: 12px;
	border-radius: 4px;
	font-weight: 500;
}

	.form-status.success {
		background-color: rgba(34,139,34,0.2);
		border: 1px solid rgba(34,139,34,0.4);
		color: #90EE90;
	}

	.form-status.error {
		background-color: rgba(220,20,60,0.2);
		border: 1px solid rgba(220,20,60,0.4);
		color: #FF6B6B;
	}

@media (max-width: 860px) {
	.about-grid, .booking-grid {
		grid-template-columns: 1fr;
		gap: 44px;
	}

	.about-photo {
		order: -1;
	}

	.chalk-grid {
		grid-template-columns: 1fr;
	}

	.stub {
		grid-template-columns: 1fr;
		gap: 8px;
		text-align: left;
	}
}

@media (max-width: 600px) {
	.video-grid {
		grid-template-columns: 1fr;
	}
}

@media (prefers-reduced-motion: reduce) {
	.hero-slide, .card-slide {
		animation: none !important;
		opacity: 0;
		pointer-events: none;
	}

		.hero-slide:first-child, .card-slide:first-child {
			opacity: 1;
			pointer-events: auto;
		}
}

/* Applied to a carousel container (.hero-carousel, .about-photo,
   .player-card-photo) when its rotation switch (see Home.razor @code) is
   off — freezes the group on its first image, same mechanism as the
   prefers-reduced-motion fallback above, just opt-in per section instead
   of driven by the user's OS setting. */
.no-cycle .hero-slide, .no-cycle .card-slide {
	animation: none !important;
	opacity: 0;
	pointer-events: none;
}

	.no-cycle .hero-slide:first-child, .no-cycle .card-slide:first-child {
		opacity: 1;
		pointer-events: auto;
	}

/* 08-03-2026 */
/* Add these styles to the component CSS file (adapt values as needed) */

/* Side menu & backdrop */
.side-menu-backdrop {
	position: fixed;
	inset: 0;
	background: rgba(0,0,0,0.35);
	opacity: 0;
	pointer-events: none;
	transition: opacity .25s ease;
	z-index: 9998;
}

	.side-menu-backdrop.visible {
		opacity: 1;
		pointer-events: auto;
	}

/* slide-out panel */
.side-menu {
	position: fixed;
	top: 0;
	left: 0;
	height: 100vh;
	width: 320px;
	max-width: 80%;
	background: linear-gradient(180deg, #fff, #f7f7f7);
	box-shadow: 2px 0 18px rgba(0,0,0,0.25);
	transform: translateX(-110%);
	transition: transform .28s cubic-bezier(.2,.9,.25,1);
	z-index: 9999;
	display: flex;
	flex-direction: column;
}

	.side-menu.open {
		transform: translateX(0);
	}

/* inner layout */
.side-menu-inner {
	/* push content down roughly '6 lines' (adjustable): add extra top padding
	   while preserving the original 20px padding on other sides */
	padding: calc(20px + 6rem) 20px 20px 20px;
	display: flex;
	flex-direction: column;
	gap: 12px;
	flex: 1 1 auto;
	overflow-y: auto;
}

.side-menu-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
}

	.side-menu-header h3 {
		margin: 0;
		font-size: 1.1rem;
	}

.close-btn {
	background: transparent;
	border: 0;
	font-size: 1.1rem;
	cursor: pointer;
}

.close-btn {
	padding: 4px 8px;
}

/* Horizontal rule separator inside the side-menu */
.side-menu-hr {
	border: 0;
	height: 1px;
	background: var(--line);
	margin: 8px 0 12px 0;
}

/* sign-in box */
.sign-in-box label {
	display: block;
	font-size: 0.9rem;
	margin-bottom: 8px;
	color: var(--ink-2);
}

/* Standardize input styling and use a clean sans-serif family */
.side-menu, .side-menu-inner, .sign-in-box, .side-menu .actions, .side-menu .account-menu a {
	font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

	.sign-in-box input[type="text"],
	.sign-in-box input[type="password"],
	.sign-in-box input[type="email"] {
		width: 100%;
		padding: 10px 12px;
		margin-top: 6px;
		border: 1px solid rgba(0,0,0,0.12);
		border-radius: 6px;
		font-size: 0.95rem;
		box-sizing: border-box;
		background: #fff;
		color: var(--ink-2);
		appearance: none;
	}

	.sign-in-box input::placeholder {
		color: rgba(0,0,0,0.45);
		font-weight: 500;
	}

	.sign-in-box .remember {
		display: flex;
		align-items: center;
		gap: 8px;
		margin-top: 6px;
		font-size: 0.9rem;
	}

	.sign-in-box .remember {
		font-family: inherit; /* ensure checkbox label uses the new sans-serif */
	}

	/* actions */
	.side-menu .actions {
		margin-top: 10px;
	}

	.side-menu .account-menu ul {
		list-style: none;
		padding: 0;
		margin: 0;
		display: flex;
		flex-direction: column;
		gap: 10px;
	}

	.side-menu .account-menu a {
		color: var(--ink);
		text-decoration: none;
		padding: 8px 6px;
		border-radius: 6px;
	}

/* Header center welcome */
.nav-center {
	flex: 0 1 auto;
	display: flex;
	justify-content: center;
	align-items: center;
	min-width: 0;
	max-width: 40%;
	text-align: center;
}

	.nav-center .welcome {
		font-family: var(--cond);
		color: var(--paper);
		background: transparent;
		font-weight: 600;
		font-size: 48px;
	}

/* Responsive: smaller screens make menu wider fractionally and allow header wrapping */
@media (max-width: 720px) {
	.side-menu {
		width: 80%;
	}

	.brand-mark {
		flex-basis: 100%;
		max-width: 100%;
	}

	.nav-center {
		order: 3;
		width: 100%;
		margin-top: 6px;
	}

	.nav-links {
		order: 2;
		width: 100%;
		justify-content: flex-start;
		padding-left: 32px;
		gap: 12px 14px;
	}

	/* When signed in we want brand + nav on the top row and the welcome
	   message to sit below, right-aligned. Override the default stacking
	   behavior for .site-nav.signed-in on small screens. */
	.site-nav.signed-in .brand-mark {
		flex-basis: auto;
		max-width: 60%;
	}

	.site-nav.signed-in .nav-links {
		order: 1;
		width: auto;
		justify-content: flex-end;
		padding-left: 0;
		padding-right: 16px;
		gap: 12px 10px;
		flex: 0 1 auto;
	}

	.site-nav.signed-in .nav-center {
		order: 2;
		width: 100%;
		margin-top: 6px;
		justify-content: flex-end;
		text-align: right;
		padding-right: 16px;
	}
}

/* ************************************************************ */
/* Data grids (same layout as Rankipedia)                       */
/* ************************************************************ */

.tightColumn { white-space: nowrap; width: 1px; }

.mud-table-row { vertical-align: top; }
.mud-table-foot td { font-weight: normal !important; }

.rank-grid-select { background-color: #007BFF; }
.rank-grid-edit { background-color: #CBA639; }
.rank-grid-delete { background-color: #DC3545; }
.rank-grid-add { background-color: #1A3A2A; color: #4FF2C9; }

/* GridControl (select/edit/delete buttons) is hidden except on:
   - the one active row: the last row clicked/tapped on the page (data-row-active, set in js/grid.js)
   - the row under the mouse, while it's there (doesn't change which row is active)
   - a row pending delete (its confirmation dialog is open) or holding keyboard focus
   It keeps its space so rows don't shift. GridEdit and GridNew aren't affected and always show. */
tr .grid-control {
	opacity: 0;
	pointer-events: none;			/* a tap on the hidden buttons reaches the row instead (and activates it) */
	transition: opacity 0.15s ease;
}

tr[data-row-active] .grid-control,
tr:hover .grid-control,
tr.rank-grid-delete .grid-control,
tr:focus-within .grid-control {
	opacity: 1;
	pointer-events: auto;
}
