/*
 * Global stylesheet — everything theme.json can't express: the CSS reset,
 * base typography, and the app-shell layout (top bar, primary nav, content
 * container). Ported from the static mockups' reset.css/base.css/layout.css
 * (see DESIGNAGENTS.md); component styles (cards, buttons, tables, etc.)
 * are ported incrementally as each block lands, not all at once.
 *
 * NOTE: Inter/JetBrains Mono are declared as theme.json font families but
 * have no self-hosted .woff2 files yet — the static project has the same
 * gap (see css/base.css). Browsers fall back to the rest of the stack
 * until real font files are added to both projects.
 */

/* Reset */

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

* {
	margin: 0;
}

html {
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
	font-size: 100%;
}

html,
body {
	height: 100%;
}

body {
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

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

input,
button,
textarea,
select {
	font: inherit;
	color: inherit;
}

p,
h1,
h2,
h3,
h4,
h5,
h6 {
	overflow-wrap: break-word;
}

ul,
ol {
	list-style: none;
	padding: 0;
}

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

button {
	background: none;
	border: none;
	padding: 0;
	cursor: pointer;
	text-align: inherit;
}

table {
	border-collapse: collapse;
	border-spacing: 0;
}

fieldset {
	border: none;
}

/* Color — the design system is dark (theme.json's custom colors are the
   dark values, docs/design-system.md). Light is an optional variant for
   anyone who flips the toggle (theme-toggle.js sets data-theme="light");
   every role keeps its name, only its value changes — "--paper" is the
   primary text color in both, even though it's dark ink here. Contrast
   of each pair is checked in design-system.md. */

html[data-theme="light"] {
	--wp--custom--color--ink: #F6F5F2;
	--wp--custom--color--surface: #FFFFFF;
	--wp--custom--color--surface-2: #EEEDE9;
	--wp--custom--color--line: rgba(14, 15, 17, 0.10);
	--wp--custom--color--line-strong: rgba(14, 15, 17, 0.18);
	--wp--custom--color--paper: #0E0F11;
	--wp--custom--color--muted: #5F6168;
	--wp--custom--color--crimson-text: #C8102E;
	--wp--custom--color--positive-text: #177A48;
	--wp--custom--color--grass: #4A7C59;
	--wp--custom--color--grass-alt: #558A65;
	--wp--custom--color--pitch-strip: #C9AE7E;
	color-scheme: light;
}

html {
	color-scheme: dark;
}

/* Base typography */

body {
	font-family: var(--wp--preset--font-family--sans);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 400;
	line-height: 1.6;
	color: var(--wp--custom--color--text-primary);
	background-color: var(--wp--custom--color--background);
}

/* Space Grotesk for headings and every number; Manrope for everything
   else (body, labels, captions, nav). */
h1, h2, h3, h4, h5, h6 {
	font-family: var(--wp--preset--font-family--display);
	font-weight: 700;
	line-height: 1.15;
	letter-spacing: -0.01em;
	color: var(--wp--custom--color--text-primary);
}

h1 { font-size: var(--wp--preset--font-size--2xl); }
h2 { font-size: var(--wp--preset--font-size--xl); }
h3 { font-size: var(--wp--preset--font-size--lg); font-weight: 600; }
h4 { font-size: var(--wp--preset--font-size--md); font-weight: 600; }
h5 { font-size: var(--wp--preset--font-size--base); font-weight: 600; }
h6 { font-size: var(--wp--preset--font-size--sm); font-weight: 600; }

p { font-size: var(--wp--preset--font-size--base); }

small {
	font-size: var(--wp--preset--font-size--sm);
	color: var(--wp--custom--color--text-secondary);
}

a {
	color: var(--wp--custom--color--crimson-text);
	text-decoration: none;
}

a:active {
	opacity: 0.7;
}

label {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 500;
}

/* Numeric content — scores, stats, points tables, leaderboards */

.num,
.font-mono,
.tabular-nums {
	font-family: var(--wp--preset--font-family--display);
	font-variant-numeric: tabular-nums;
}

/* Accessibility utility */

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

/*
 * App shell — slim top bar at every width, single-column content with a
 * bottom tab bar on mobile (base, <768px), a fixed left sidebar nav from
 * 768px up, and a centered content container. Mobile-first: base rules
 * apply everywhere, min-width queries layer changes on top. Direct port
 * of layout.css — see that file's own header comment for the breakpoint
 * rationale; theme.json's --wp--custom--container-laptop/desktop can't be
 * read inside @media conditions, so the literal px values are repeated
 * here too, same as the static project.
 */

.top-bar {
	position: sticky;
	top: 0;
	z-index: 30;
	display: flex;
	flex-direction: column;
	padding: var(--wp--preset--spacing--spacing-8) var(--wp--preset--spacing--spacing-16);
	padding-top: calc(var(--wp--preset--spacing--spacing-8) + env(safe-area-inset-top));
	background-color: var(--wp--custom--color--background);
	border-bottom: 1px solid var(--wp--custom--color--border);
}

@media (min-width: 768px) {
	.top-bar {
		padding-inline: var(--wp--preset--spacing--spacing-24);
	}
}

.top-bar__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--spacing-16);
	min-height: var(--wp--custom--topbar-height);
}

.top-bar__title {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: var(--wp--preset--font-size--md);
	font-weight: 600;
	line-height: 1.15;
	margin: 0;
}

.top-bar__utilities {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--spacing-8);
}

.top-bar__icon-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--custom--color--text-primary);
}

.top-bar__icon-btn svg {
	width: 22px;
	height: 22px;
}

.top-bar__icon-btn:active {
	background-color: var(--wp--custom--color--surface);
}

/* Primary nav — bottom tab bar at base, fixed left sidebar from 768px.
   Same markup, same 5 items, same active-accent styling at every width;
   only the layout direction and position change. */

.app-nav {
	position: fixed;
	z-index: 20;
	left: 0;
	right: 0;
	bottom: 0;
	display: flex;
	flex-direction: row;
	align-items: stretch;
	gap: var(--wp--preset--spacing--spacing-8);
	padding: 0 var(--wp--preset--spacing--spacing-8);
	padding-bottom: env(safe-area-inset-bottom);
	background-color: var(--wp--custom--color--surface);
	border-top: 1px solid var(--wp--custom--color--border);
}

@media (min-width: 768px) {
	.app-nav {
		top: var(--wp--custom--topbar-height);
		right: auto;
		width: var(--wp--custom--sidebar-width);
		flex-direction: column;
		align-items: stretch;
		gap: var(--wp--preset--spacing--spacing-8);
		padding: var(--wp--preset--spacing--spacing-16) var(--wp--preset--spacing--spacing-8);
		border-top: none;
		border-right: 1px solid var(--wp--custom--color--border);
		overflow-y: auto;
	}
}

/* Staff who keep the WordPress toolbar (editors/admins — regular players
   never get it, see nplt20-fantasy's includes/frontend-access.php): the
   toolbar pushes the page down, but not this fixed sidebar, which then
   slid under the header and hid its first item (Home). Offset it by the
   toolbar's own height — 46px below WP's 783px breakpoint, 32px above. */
@media (min-width: 768px) {
	body.admin-bar .app-nav {
		top: calc(var(--wp--custom--topbar-height) + 46px);
	}
}

@media (min-width: 783px) {
	body.admin-bar .app-nav {
		top: calc(var(--wp--custom--topbar-height) + 32px);
	}
}

/* Same toolbar for the sticky top bar. Below 600px WP's toolbar scrolls
   away with the page (position: absolute), so no offset is needed there. */
@media (min-width: 600px) {
	body.admin-bar .top-bar {
		top: 46px;
	}
}

@media (min-width: 783px) {
	body.admin-bar .top-bar {
		top: 32px;
	}
}

/* How far down from the real viewport top a page's OWN sticky chrome
 * (.team-builder-header and the stacked headers below it — see
 * components.css's Tournament Squad section) should start. Despite
 * .top-bar's `position: sticky; top: 0`, it never actually stays
 * pinned once scrolled: its containing block (the header.wp-block-
 * template-part wrapping it) is only as tall as .top-bar itself, so
 * there's no extra height for it to stick through (confirmed
 * 2026-09-28 while fixing My Team's sticky "SEASON 3" bar bleeding
 * scrolled pitch content through a ~20px gap above it — that gap was
 * this same 56px topbar-height offset, minus whatever of the WP
 * toolbar's real height was covering part of it). The one thing that
 * DOES stay fixed at the real top is WordPress's own toolbar
 * (#wpadminbar, staff only — regular players never get it) — so the
 * true answer is 0 normally, or the toolbar's real height for staff,
 * the same breakpoints/heights .top-bar's own overrides above use.
 */
:root {
	--sticky-chrome-top: 0px;
}

@media (min-width: 600px) {
	body.admin-bar {
		--sticky-chrome-top: 46px;
	}
}

@media (min-width: 783px) {
	body.admin-bar {
		--sticky-chrome-top: 32px;
	}
}

.app-nav__item {
	flex: 1 1 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 2px;
	min-width: 44px;
	min-height: 44px;
	padding: var(--wp--preset--spacing--spacing-8) 4px;
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--custom--color--text-secondary);
}

@media (min-width: 768px) {
	.app-nav__item {
		flex: 0 0 auto;
		flex-direction: row;
		justify-content: flex-start;
		gap: var(--wp--preset--spacing--spacing-16);
		padding: var(--wp--preset--spacing--spacing-8) var(--wp--preset--spacing--spacing-16);
	}

	.app-nav__item:hover {
		color: var(--wp--custom--color--text-primary);
	}
}

.app-nav__item:active {
	transform: scale(0.97);
	opacity: 0.85;
}

.app-nav__item--active,
.app-nav__item[aria-current="page"] {
	color: var( --wp--custom--color--crimson-text, #C8102E );
}

.app-nav__icon {
	display: flex;
	width: 22px;
	height: 22px;
	flex-shrink: 0;
}

.app-nav__icon svg {
	width: 100%;
	height: 100%;
}

.app-nav__label {
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 500;
	line-height: 1;
}

@media (min-width: 768px) {
	.app-nav__label {
		font-size: var(--wp--preset--font-size--sm);
	}
}

/* Content area */

.app-content {
	padding: var(--wp--preset--spacing--spacing-16);
	padding-bottom: calc(var(--wp--custom--tabbar-height) + env(safe-area-inset-bottom) + var(--wp--preset--spacing--spacing-16));
}

@media (min-width: 768px) {
	.app-content {
		margin-left: var(--wp--custom--sidebar-width);
		padding: var(--wp--preset--spacing--spacing-24);
	}
}

.container {
	width: 100%;
	margin-inline: auto;
}

@media (min-width: 1024px) {
	.container {
		max-width: var(--wp--custom--container-laptop);
	}
}

@media (min-width: 1440px) {
	.container {
		max-width: var(--wp--custom--container-desktop);
	}
}

.grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--wp--preset--spacing--spacing-16);
}

@media (min-width: 768px) {
	.grid--2,
	.grid--3 {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 1024px) {
	.grid--3 {
		grid-template-columns: repeat(3, 1fr);
	}
}


/* Mobile: keep the top bar pinned while scrolling. .top-bar's own sticky
   can't travel (its template-part wrapper is only as tall as it is), so
   the wrapper is what sticks. Other sticky page chrome starts below it. */
@media (max-width: 767px) {
	header.wp-block-template-part {
		position: sticky;
		top: 0;
		z-index: 30;
	}

	:root {
		/* = the bar's real height: row + 2x8px padding + 1px border. */
		--sticky-chrome-top: calc(var(--wp--custom--topbar-height) + 17px + env(safe-area-inset-top));
	}
}

@media (min-width: 600px) and (max-width: 767px) {
	body.admin-bar header.wp-block-template-part {
		top: 46px;
	}
}
