/*
 * Trinity Rundown — front-end styles.
 *
 * Everything is scoped under .trun-* so it cannot leak into the theme, and
 * every color is a token declared on .trun-week so the theme's own palette is
 * never assumed. Team colors arrive per game as custom properties set inline
 * from the payload; --trun-away-ink and --trun-home-ink come with them and are
 * black or white, whichever the renderer computed is readable on that color.
 * Never hard-code text over a team color — use the ink.
 *
 * Layout switches on the *container*, not the viewport: the shortcode drops
 * into whatever column a theme gives it, and a 640px-wide sidebar needs the
 * phone layout even on a desktop.
 */

.trun-week {
	/* Neutral fallbacks. A game whose colors collided, or has none, lands here. */
	--trun-away: #4a5568;
	--trun-home: #2d3748;
	--trun-away-ink: #ffffff;
	--trun-home-ink: #ffffff;

	--trun-border: color-mix(in srgb, currentColor 15%, transparent);
	--trun-rule: color-mix(in srgb, currentColor 28%, transparent);
	--trun-muted: color-mix(in srgb, currentColor 65%, transparent);
	--trun-sunk: color-mix(in srgb, currentColor 4%, transparent);
	--trun-gap: 1rem;
	--trun-radius: 10px;

	container-type: inline-size;
	font-variant-numeric: tabular-nums;

	/*
	 * The shortcode is usually the first thing in the post, which puts the
	 * first panel directly under the site header with nothing between them --
	 * the page reads as one block and the header stops looking like a header.
	 * Themes vary in what they give a first child, so the gap is claimed here
	 * rather than assumed. Margin, not padding, so it collapses with any space
	 * a theme *has* already left instead of stacking on top of it.
	 */
	margin-block-start: 2rem;
}

/* ---------- The week's one control ---------- */

/*
 * Right-aligned and above the panels: a control over a list belongs at the
 * list's top, and the end of the row is where it stays out of the way of the
 * first matchup, which is what the reader came for.
 *
 * `hidden` until rundown.js unhides it -- see trun_render_toolbar(). The
 * attribute needs no rule of its own; nothing here overrides it.
 */
.trun-toolbar {
	display: flex;
	justify-content: flex-end;
	margin-block-end: 0.75rem;
}

/*
 * Every property a theme's button styles might otherwise supply is set, since
 * this sits in post content where a theme is free to style <button>. Colour is
 * the exception: it inherits, so the control is legible on a light theme and a
 * dark one without either being detected.
 */
.trun-toolbar__all {
	font: inherit;
	font-size: 0.8125rem;
	font-weight: 600;
	line-height: 1.2;
	color: inherit;
	background: none;
	border: 1px solid var(--trun-rule);
	border-radius: 999px;
	padding: 0.4rem 0.9rem;
	cursor: pointer;
	/* The label swaps between two words of different width; don't jump. */
	min-width: 7.5em;
	transition: background-color 150ms ease;
}

.trun-toolbar__all:hover {
	background: var(--trun-sunk);
}

.trun-toolbar__all:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.trun-toolbar__all {
		transition: none;
	}
}

/* ---------- Game panels ---------- */

.trun-game {
	border: 1px solid var(--trun-border);
	border-radius: var(--trun-radius);
	margin-block-end: var(--trun-gap);
	overflow: hidden;
}

.trun-game__summary {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.25rem 1rem;
	padding: 0.875rem 1rem;
	cursor: pointer;
	font-weight: 600;
	/* A 4px rule in the home team's color, so panels are scannable by team. */
	border-inline-start: 4px solid var(--trun-home);
	/* Room at the end for the chevron, which is positioned rather than flowed. */
	padding-inline-end: 2.25rem;
	position: relative;
	/*
	 * `display: flex` already drops the UA disclosure triangle -- summary stops
	 * being a list-item -- so the chevron below is the only affordance and this
	 * says so on purpose rather than by side effect.
	 */
	list-style: none;
}

.trun-game__summary::-webkit-details-marker {
	display: none;
}

/*
 * The chevron. A week is sixteen closed rows, and without this nothing on the
 * page says they open: the cursor is the whole hint, and a reader who never
 * hovers never finds out. Drawn from two borders rather than set as text so it
 * inherits the theme's colour and needs no font or icon file.
 *
 * Positioned rather than left as a flex item. As an item it wrapped: a long
 * matchup on a phone pushed the spread and kickoff to their own line and the
 * chevron to a third, alone. Pinned to the end and centred on the whole
 * summary with `inset-block: 0` plus auto margins, it sits where the row's
 * only control should sit at any width, and the centring needs no assumption
 * about the theme's line-height.
 */
.trun-game__summary::after {
	content: "";
	position: absolute;
	inset-block: 0;
	inset-inline-end: 1rem;
	margin-block: auto;
	width: 0.45em;
	height: 0.45em;
	color: var(--trun-muted);
	border-inline-end: 2px solid currentColor;
	border-block-end: 2px solid currentColor;
	/* Pointing down: this panel is closed. */
	transform: rotate(45deg);
	transition: transform 150ms ease;
}

.trun-game[open] > .trun-game__summary::after {
	/* Pointing up: this panel is open. */
	transform: rotate(-135deg);
}

@media (prefers-reduced-motion: reduce) {
	.trun-game__summary::after {
		transition: none;
	}
}

.trun-game__summary:hover {
	background: var(--trun-sunk);
}

.trun-game__summary:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: -2px;
}

.trun-game__teams {
	flex: 1 1 auto;
}

.trun-game__line,
.trun-game__kick {
	font-weight: 400;
	color: var(--trun-muted);
	font-size: 0.875rem;
}

.trun-game__body {
	padding: 0 1rem 1rem;
	border-inline-start: 4px solid var(--trun-home);
}

/* ---------- Team bar ---------- */

/*
 * Who is playing, before any number about them. Each side is a small grid:
 * the logo spans both text rows, so the name and the record/moneyline line up
 * against it rather than floating.
 */
.trun-teambar {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
	gap: 0.75rem;
	margin-block: 1rem;
}

.trun-teambar__side {
	display: grid;
	grid-template-columns: auto 1fr;
	grid-template-areas:
		"logo role"
		"logo name"
		"logo meta";
	align-items: center;
	column-gap: 0.75rem;
	padding: 0.625rem 0.75rem;
	border-radius: 6px;
	background: var(--trun-sunk);
	/* The team's color, as a spine rather than a fill: a filled card in two
	   near-black navies is the collision all over again, and this reads at a
	   glance without betting the layout on the color being distinctive. */
	border-inline-start: 5px solid var(--trun-side, var(--trun-border));
}

.trun-teambar__side--away {
	--trun-side: var(--trun-away);
}

.trun-teambar__side--home {
	--trun-side: var(--trun-home);
}

.trun-teambar__logo {
	grid-area: logo;
	width: 44px;
	height: 44px;
	object-fit: contain;
}

.trun-teambar__role {
	grid-area: role;
	font-size: 0.6875rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--trun-muted);
}

.trun-teambar__name {
	grid-area: name;
	font-weight: 700;
	line-height: 1.25;
}

.trun-teambar__meta {
	grid-area: meta;
	font-size: 0.875rem;
	color: var(--trun-muted);
}

/* ---------- Odds bar and records strip ---------- */

/*
 * Column counts are fixed rather than auto-fit, because the cells have to fill
 * whole rows: six market cells over three columns, four records over four.
 * auto-fit put six cells in five columns and left the sixth alone on a row of
 * its own.
 *
 * Separators are borders on each cell's *start* edges, so a cell paints no
 * background of its own and keeps the theme's. That is not a stylistic
 * preference. These cells were `background: Canvas`, which is the user agent's
 * canvas colour and always white here -- against this dark theme it put
 * rgb(237,232,232) text on white at a contrast ratio of 1.21:1, which is to say
 * the spread, the total, both team totals and all four records were invisible
 * on the live page. Nothing in this stylesheet may assume the page is light.
 *
 * Only start edges are drawn, and the first row and column draw nothing, so
 * the cell borders never double up with the container's.
 */
.trun-oddsbar {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	border: 1px solid var(--trun-border);
	border-radius: 6px;
	overflow: hidden;
	margin-block: 1rem;
}

.trun-oddsbar--records {
	grid-template-columns: repeat(4, 1fr);
	margin-block-end: 1.75rem;
}

.trun-oddsbar__cell {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	padding: 0.75rem;
	border-inline-start: 1px solid var(--trun-border);
	border-block-start: 1px solid var(--trun-border);
}

.trun-oddsbar:not(.trun-oddsbar--records) .trun-oddsbar__cell:nth-child(3n + 1) {
	border-inline-start: 0;
}

.trun-oddsbar:not(.trun-oddsbar--records) .trun-oddsbar__cell:nth-child(-n + 3) {
	border-block-start: 0;
}

.trun-oddsbar--records .trun-oddsbar__cell:nth-child(4n + 1) {
	border-inline-start: 0;
}

/* Four records over four columns is a single row. */
.trun-oddsbar--records .trun-oddsbar__cell {
	border-block-start: 0;
}

.trun-oddsbar__label {
	font-size: 0.6875rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--trun-muted);
}

/* "(season)" qualifies the label without competing with it. */
.trun-oddsbar__qualifier {
	letter-spacing: 0;
	text-transform: none;
}

.trun-oddsbar__value {
	font-size: 1.125rem;
	font-weight: 600;
	line-height: 1.3;
}

/* The records strip carries four short values; it does not need the same size. */
.trun-oddsbar--records .trun-oddsbar__value {
	font-size: 1rem;
}

/* Line movement, under the line itself rather than trailing off the end of it. */
.trun-oddsbar__note {
	font-size: 0.75rem;
	color: var(--trun-muted);
}

/* ---------- Stat modules ---------- */

.trun-module {
	margin-block: 1.75rem;
}

/*
 * The weather line, repeated under the Kickers heading. It is the reason that
 * table exists -- roof, altitude and crosswind are what a venue split measures
 * -- and it is otherwise twenty rows up the page.
 */
.trun-module__note {
	margin-block: -0.25rem 0.75rem;
	font-size: 0.75rem;
	color: var(--trun-muted);
}

.trun-module__heading {
	font-size: 0.75rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--trun-muted);
	margin-block-end: 0.625rem;
	padding-block-end: 0.375rem;
	border-block-end: 1px solid var(--trun-rule);
}

/*
 * The border reset is not tidiness. Trinity Analytics' theme ships
 * `table, td, th { border: 1px solid }` and then `table { border-width: 1px 0
 * 0 1px }`, and a table here is content-box -- so `width: 100%` resolved to
 * the scroll box's width and the theme's left border pushed one pixel past
 * it. Every table on the page overflowed by exactly 1px, and the browser drew
 * a horizontal scrollbar under each one for it. The rules below own every
 * edge they draw, so a theme cannot add an edge we did not ask for.
 */
.trun-table {
	width: 100%;
	border: 0;
	border-collapse: collapse;
	font-size: 0.9375rem;
}

.trun-table th,
.trun-table td {
	padding: 0.5rem 0.625rem;
	text-align: left;
	border: 0;
	border-block-end: 1px solid var(--trun-border);
	vertical-align: baseline;
}

.trun-table thead th {
	font-size: 0.6875rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	font-weight: 600;
	color: var(--trun-muted);
	border-block-end-color: var(--trun-rule);
	white-space: nowrap;
}

.trun-table tbody th {
	font-weight: 600;
}

.trun-table tbody tr:last-child th,
.trun-table tbody tr:last-child td {
	border-block-end: 0;
}

.trun-table__team {
	font-weight: 600;
	font-size: 0.8125rem;
	color: var(--trun-muted);
}

/*
 * A two-sided table says whose it is in the caption, filled with that team's
 * color. The ink is computed per color rather than assumed white — several
 * secondaries (Pittsburgh's gold, the Rams' yellow) need black text.
 */
.trun-table__caption {
	caption-side: top;
	text-align: left;
	font-weight: 600;
	font-size: 0.8125rem;
	padding: 0.375rem 0.625rem;
	border-radius: 5px 5px 0 0;
	background: var(--trun-side, transparent);
	color: var(--trun-side-ink, inherit);
}

.trun-scroll[data-side="away"] {
	--trun-side: var(--trun-away);
	--trun-side-ink: var(--trun-away-ink);
}

.trun-scroll[data-side="home"] {
	--trun-side: var(--trun-home);
	--trun-side-ink: var(--trun-home-ink);
}

/*
 * The sample badge. Week 1 shows last season's numbers and weeks 2-4 show a
 * thin sample; the badge is how a reader knows which. It sits inline with the
 * module heading, so it must not inherit the heading's letter-spacing.
 */
.trun-badge {
	display: inline-block;
	margin-inline-start: 0.5rem;
	padding: 0.0625rem 0.375rem;
	border: 1px solid var(--trun-rule);
	border-radius: 0.75rem;
	font-size: 0.6875rem;
	letter-spacing: 0;
	text-transform: none;
	font-weight: 500;
	color: var(--trun-muted);
	vertical-align: middle;
}

/*
 * Wide tables scroll inside their own box rather than widening the page. Below
 * 640px they stop being tables at all — see the container query further down —
 * so this is the desktop safety net, not the phone answer.
 */
.trun-scroll {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

.trun-scroll + .trun-scroll {
	margin-block-start: 1.25rem;
}

/*
 * The two-sided modules render one table per team, one under the other, and
 * automatic layout sized each side's columns from that side's own content --
 * so the two disagreed about where every column after the name began, which
 * reads as a rendering fault rather than as two tables. Fixed layout makes
 * them honour the widths render.php writes on the header row instead, and
 * identical widths in two boxes of identical width line up.
 *
 * Efficiency and injuries are single tables with nothing to line up against,
 * and stay automatic.
 */
.trun-table--passing,
.trun-table--rushing,
.trun-table--fantasy,
.trun-table--kicking {
	table-layout: fixed;
}

/* Numbers right-align so magnitudes line up; the name column stays left. */
.trun-table--efficiency td,
.trun-table--passing td,
.trun-table--rushing td,
.trun-table--fantasy td,
.trun-table--kicking td {
	text-align: right;
}

/*
 * The passing table's role and the fantasy table's position are attributes of
 * the name beside them rather than stats, so they read as part of the row
 * header. The kicker table's first cell is the venue, which is the row's
 * subject and left-aligns for the same reason.
 */
.trun-table--passing td:first-of-type,
.trun-table--fantasy td:first-of-type {
	text-align: left;
	color: var(--trun-muted);
	font-size: 0.8125rem;
}

.trun-table--efficiency thead th,
.trun-table--passing thead th,
.trun-table--rushing thead th,
.trun-table--fantasy thead th,
.trun-table--kicking thead th {
	text-align: right;
}

.trun-table--efficiency thead th:first-child,
.trun-table--passing thead th:first-child,
.trun-table--passing thead th:nth-child(2),
.trun-table--rushing thead th:first-child,
.trun-table--fantasy thead th:first-child,
.trun-table--fantasy thead th:nth-child(2),
.trun-table--kicking thead th:first-child {
	text-align: left;
}

/*
 * Every column heading explains itself on hover. The TGT RATE one is the case
 * that matters most — it is not TPRR, and this is what keeps that distinction
 * on the page rather than only in docs/metrics.md — so the heading has to look
 * like an explanation rather than an underline artifact.
 *
 * Known limit: title text does not open on touch. It is still in the markup
 * and still reaches screen readers; a tap-to-open treatment is a later job.
 */
.trun-table thead th abbr {
	text-decoration: underline dotted;
	text-underline-offset: 0.2em;
	cursor: help;
}

.trun-oddsbar__label abbr {
	text-decoration: underline dotted;
	text-underline-offset: 0.2em;
	cursor: help;
}

/*
 * Status carries weight, not just hue: the word itself is always the signal,
 * so this reads correctly in greyscale and to anyone who cannot separate the
 * colors.
 *
 * Each hue is mixed toward currentColor so it tracks the page rather than the
 * operating system. These were flat hex values with lighter variants behind
 * `prefers-color-scheme: dark`, which never fired on the live site: this theme
 * is dark unconditionally, not by OS preference, so the dark reds sat on near
 * black at 3.2:1 and the olive at 3.0:1. Mixing puts them at roughly 5.7:1 and
 * 6.2:1 on this theme and above 11:1 on a light one, without moving the hue
 * far enough to stop reading as a warning.
 */
.trun-status {
	font-weight: 600;
}

.trun-status--out,
.trun-status--injured-reserve {
	color: color-mix(in srgb, #b3261e 65%, currentColor);
}

.trun-status--doubtful {
	color: color-mix(in srgb, #a15c00 65%, currentColor);
}

.trun-status--questionable {
	color: color-mix(in srgb, #6b5900 65%, currentColor);
}

/* ---------- Editorial ---------- */

.trun-notes {
	margin-block: 1.5rem;
}

.trun-notes__heading {
	font-size: 0.75rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--trun-muted);
	margin-block-end: 0.5rem;
}

.trun-notes p:last-child {
	margin-block-end: 0;
}

.trun-footer {
	font-size: 0.8125rem;
	color: var(--trun-muted);
	margin-block-start: 2rem;
	padding-block-start: 0.75rem;
	border-block-start: 1px solid var(--trun-border);
}

.trun-empty {
	padding: 1rem;
	border: 1px dashed var(--trun-rule);
	border-radius: 6px;
	color: var(--trun-muted);
}

/* ---------- Narrow containers: tables become stacked cards ---------- */

@container (max-width: 640px) {
	/*
	 * The injury table reflows into one card per player.
	 *
	 * The areas are named rather than left to auto-flow. Each row is its own
	 * grid, so `auto 1fr auto` sized its columns from that row's own content
	 * and every player's name landed somewhere different down the list --
	 * which reads as a rendering fault rather than as a table.
	 */
	.trun-table--injuries thead {
		display: none;
	}

	.trun-table--injuries tr {
		display: grid;
		grid-template-columns: auto 1fr auto;
		grid-template-areas:
			"team player pos"
			"status status status"
			"note note note";
		gap: 0.125rem 0.5rem;
		padding-block: 0.625rem;
		border-block-end: 1px solid var(--trun-border);
	}

	.trun-table--injuries th,
	.trun-table--injuries td {
		border: 0;
		padding: 0;
	}

	.trun-table--injuries td:nth-child(1) {
		grid-area: team;
	}

	.trun-table--injuries th {
		grid-area: player;
	}

	.trun-table--injuries td:nth-child(3) {
		grid-area: pos;
		color: var(--trun-muted);
		font-size: 0.8125rem;
	}

	.trun-table--injuries td:nth-child(4) {
		grid-area: status;
	}

	/* An absent note collapses to nothing rather than leaving a blank line. */
	.trun-table--injuries td:nth-child(5) {
		grid-area: note;
		color: var(--trun-muted);
		font-size: 0.875rem;
	}

	.trun-table--injuries td:nth-child(5):empty {
		display: none;
	}

	/*
	 * The stat tables stack. Seven columns cannot be read on a phone
	 * sideways-scrolled either, and a reader who scrolls a table right loses
	 * the row header that said whose number it is. Each cell instead prints
	 * its own heading, out of the data-label the renderer emits.
	 *
	 * These five lists are enumerated rather than generic, so a new
	 * trun-table-- class has to be added to every one of them. Miss one and
	 * the desktop table still looks right while the phone silently becomes an
	 * unlabelled column of bare numbers.
	 */
	.trun-table--efficiency thead,
	.trun-table--passing thead,
	.trun-table--rushing thead,
	.trun-table--fantasy thead,
	.trun-table--kicking thead {
		display: none;
	}

	.trun-table--efficiency tr,
	.trun-table--passing tr,
	.trun-table--rushing tr,
	.trun-table--fantasy tr,
	.trun-table--kicking tr {
		display: block;
		padding-block: 0.625rem;
		border-block-end: 1px solid var(--trun-border);
	}

	.trun-table--efficiency tbody th,
	.trun-table--passing tbody th,
	.trun-table--rushing tbody th,
	.trun-table--fantasy tbody th,
	.trun-table--kicking tbody th {
		display: block;
		padding: 0 0 0.25rem;
		border: 0;
		font-size: 1rem;
	}

	.trun-table--efficiency td,
	.trun-table--passing td,
	.trun-table--rushing td,
	.trun-table--fantasy td,
	.trun-table--kicking td {
		display: flex;
		justify-content: space-between;
		align-items: baseline;
		gap: 1rem;
		padding: 0.125rem 0;
		border: 0;
	}

	.trun-table--efficiency td::before,
	.trun-table--passing td::before,
	.trun-table--rushing td::before,
	.trun-table--fantasy td::before,
	.trun-table--kicking td::before {
		content: attr(data-label);
		font-size: 0.6875rem;
		letter-spacing: 0.06em;
		text-transform: uppercase;
		color: var(--trun-muted);
	}

	/* Role and position are attributes of the name, not stats. */
	.trun-table--passing td:first-of-type,
	.trun-table--fantasy td:first-of-type {
		font-size: 0.875rem;
	}

	/*
	 * Stacked rows are no longer table rows, so the column widths on the
	 * header -- hidden just above -- have nothing left to size. Say so
	 * rather than leaving a fixed layout to divide up a table that has no
	 * columns any more.
	 */
	.trun-table--passing,
	.trun-table--rushing,
	.trun-table--fantasy,
	.trun-table--kicking {
		table-layout: auto;
	}

	/* Nothing overflows once stacked, so the scroll box would only clip. */
	.trun-scroll {
		overflow-x: visible;
	}

	/* Three columns of market data do not fit; two do, and 6 and 4 both halve. */
	.trun-oddsbar,
	.trun-oddsbar--records {
		grid-template-columns: repeat(2, 1fr);
	}

	/* Two columns means a different first column and first row. */
	.trun-oddsbar .trun-oddsbar__cell {
		border-inline-start: 1px solid var(--trun-border);
		border-block-start: 1px solid var(--trun-border);
	}

	.trun-oddsbar .trun-oddsbar__cell:nth-child(2n + 1) {
		border-inline-start: 0;
	}

	.trun-oddsbar .trun-oddsbar__cell:nth-child(-n + 2) {
		border-block-start: 0;
	}
}

/* ---------- Theme ----------
 *
 * There is deliberately no `prefers-color-scheme` block. Every colour here is
 * either relative to currentColor or a team colour paired with the ink the
 * renderer computed for it, so the page follows whatever theme surrounds it —
 * including a theme that is dark regardless of the visitor's OS setting, which
 * is what Trinity Analytics runs and what an OS-keyed block silently missed.
 */

/* ---------- Print ---------- */

@media print {
	.trun-game {
		break-inside: avoid;
		border-color: #999;
	}

	.trun-game[open] .trun-game__summary,
	.trun-game__summary {
		list-style: none;
	}

	/*
	 * Expand everything — a printed page cannot be clicked open, and every
	 * panel ships closed, so without this a printed week is sixteen headers.
	 */
	.trun-game:not([open]) .trun-game__body {
		display: block;
	}

	/* Every panel prints expanded, so the chevron is a control pointing at
	   nothing. Same reason the tab strip never printed. */
	.trun-game__summary::after {
		display: none;
	}

	/* Logos cost ink and say nothing the name beside them does not. */
	.trun-teambar__logo {
		display: none;
	}

	.trun-teambar__side {
		background: none;
	}

	/*
	 * Filled captions print as solid blocks. Keep the team's color as a rule
	 * and put the text back to black, which also survives a greyscale printer.
	 */
	.trun-table__caption {
		background: none;
		color: inherit;
		border-inline-start: 4px solid var(--trun-side, #999);
		border-radius: 0;
	}

	.trun-scroll {
		overflow-x: visible;
	}
}
