/* ═════════════════════════════════════════════════════════════════════════
   status.starhold.fyi: the page's own layer on top of fleet-base.css.
   Tokens only (no colour literal, no custom property declared here). Status
   colours are semantic and never decorative: --ok for a passing check,
   --danger for a failing one, --text-muted for anything not known to be true.
   The site accent (violet) is chrome only: links, pills, motif, hero bloom.
   ═════════════════════════════════════════════════════════════════════════ */

/* ═══ hero: state line and meta row ═══════════════════════════════════════ */
.state-line {
	display: inline-flex;
	align-items: center;
	gap: var(--sp-3);
	margin: var(--sp-2) 0 var(--sp-4);
	padding: var(--sp-2) var(--sp-4) var(--sp-2) var(--sp-3);
	border: 1px solid var(--border-strong);
	border-radius: var(--radius-pill);
	background: var(--surface);
	font-size: var(--fs-3);
	font-weight: 600;
	line-height: 1.3;
	color: var(--text-muted);
}
/* The mark is the shape cue that rides with the words: filled disc = up,
   filled square = major outage, ring = unknown. Degraded carries its own
   ◐ glyph in the text, so the mark steps aside rather than doubling it. */
.state-mark {
	width: 12px;
	height: 12px;
	flex-shrink: 0;
	border-radius: 50%;
	border: 2px solid currentColor;
}
.state-line[data-overall='ok'] {
	color: var(--text);
	border-color: var(--border-strong);
}
.state-line[data-overall='ok'] .state-mark {
	background: var(--ok);
	border-color: var(--ok);
}
.state-line[data-overall='degraded'] {
	color: var(--text);
}
.state-line[data-overall='degraded'] .state-mark {
	display: none;
}
.state-line[data-overall='major'] {
	color: var(--text);
	border-color: var(--danger);
}
.state-line[data-overall='major'] .state-mark {
	border-radius: 2px;
	background: var(--danger);
	border-color: var(--danger);
}
.state-line[data-overall='nojs'] .state-mark {
	border-style: dashed;
}

.state-help {
	color: var(--text-muted);
	font-size: var(--fs-1);
	margin-top: calc(-1 * var(--sp-2));
}

.meta-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-2) var(--sp-4);
}
.meta-line {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-1) var(--sp-2);
	margin: 0;
	color: var(--text-muted);
	font-size: var(--fs-1);
}
.meta-line time {
	color: var(--text);
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
}
.meta-line .sep {
	color: var(--border-strong);
}
/* Phones: "data from Gatus" steps out (How this works says it), so the row is
   "Latest check · refreshes every 60 s [Refresh now]" on at most two lines and
   the hero stays the storefront's height. */
@media (max-width: 639px) {
	.meta-line .meta-src {
		display: none;
	}
}
.refresh {
	font-size: var(--fs-0);
	padding: var(--sp-1) var(--sp-3);
}
/* .btn sets display, which would beat the UA's [hidden] rule: without JS
   the button must not exist for the visitor at all. */
/* Without JS nothing refreshes, so the meta row (and the button in it) stays out. */
.refresh[hidden],
.meta-row[hidden] {
	display: none;
}
.refresh[aria-busy='true'] {
	color: var(--text-muted);
}

/* ═══ checks ══════════════════════════════════════════════════════════════ */
.section-head {
	margin-bottom: var(--sp-6);
}
.group + .group,
[data-extra-groups] > .group {
	margin-top: var(--sp-7);
}
.group-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sp-4);
	padding-bottom: var(--sp-3);
	margin-bottom: var(--sp-4);
	border-bottom: 1px solid var(--border);
}
.group-head h3 {
	margin: 0;
	font-size: var(--fs-4);
}
.group-sum {
	margin: 0;
	color: var(--text-muted);
	font-size: var(--fs-1);
	font-variant-numeric: tabular-nums;
}
.group-sum:empty {
	display: none;
}
.group[hidden] {
	display: none;
}
.rows {
	display: grid;
	gap: var(--sp-3);
}
.rows-note {
	margin: 0;
	color: var(--text-muted);
	font-size: var(--fs-1);
}

.noscript-note {
	color: var(--text-muted);
}
.raw-list {
	list-style: none;
	padding: 0;
	margin: 0;
	display: grid;
	gap: var(--sp-2);
	font-size: var(--fs-1);
}
.raw-list a {
	font-family: var(--font-mono);
	text-decoration: underline;
	text-underline-offset: 3px;
}
.raw-list span {
	color: var(--text-muted);
	margin-left: var(--sp-2);
}

/* One row per check. Phone: stacked. 900 px and up: identity | heartbeat |
   figures on one line, the chip under the name, Recent checks spanning. */
.check {
	display: grid;
	gap: var(--sp-4);
	grid-template-columns: 1fr auto;
	grid-template-areas:
		'id chip'
		'beat beat'
		'figs figs'
		'recent recent';
	padding: var(--sp-4) var(--sp-5);
}
.check-id {
	grid-area: id;
	min-width: 0;
}
.check-chip {
	grid-area: chip;
	align-self: start;
}
.check-figs {
	grid-area: figs;
}
.beat {
	grid-area: beat;
	min-width: 0;
}
.recent {
	grid-area: recent;
}
/* Phone: the chip takes its own line under the name. Side by side, a long chip
   ("Unknown (last check 00:00 UTC)") starved the name column to ~60 px and
   broke hostnames mid-word, in exactly the state a visitor needs to read. */
@media (max-width: 639px) {
	.check {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			'id'
			'chip'
			'beat'
			'figs'
			'recent';
		row-gap: var(--sp-3);
	}
	.check-chip {
		justify-self: start;
	}
	.beat {
		margin-top: var(--sp-2);
	}
}
@media (min-width: 900px) {
	.check {
		/* 15.5rem fits the longest key (entitlements-auth-enforced) on one line,
		   so every chip sits on the same baseline; the heartbeat gives up the room. */
		grid-template-columns: minmax(15.5rem, 1.1fr) minmax(0, 2fr) auto;
		grid-template-areas:
			'id beat figs'
			'chip beat figs'
			'recent recent recent';
		column-gap: var(--sp-6);
		row-gap: var(--sp-2);
	}
	.check-chip {
		align-self: end;
	}
	.beat {
		align-self: center;
	}
}

.fleet-card.check h4 {
	margin: 0;
	font-size: var(--fs-3);
	overflow-wrap: anywhere;
}
.check h4 a {
	color: var(--text);
}
.check h4 a:hover {
	color: var(--accent-hover);
}
.fleet-card.check .check-host,
.fleet-card.check .check-note {
	margin: var(--sp-1) 0 0;
	font-size: var(--fs-1);
	color: var(--text-muted);
	overflow-wrap: anywhere;
}
.fleet-card.check .check-host {
	font-family: var(--font-mono);
	font-size: var(--fs-0);
}

/* Down rows get a danger rail: a second cue next to the chip's word. */
.check[data-state='down'] {
	border-color: var(--danger);
	box-shadow: inset 3px 0 0 var(--danger);
}

.check-figs {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--sp-3);
	margin: 0;
}
@media (min-width: 900px) {
	.check-figs {
		grid-template-columns: repeat(4, minmax(64px, auto));
		gap: var(--sp-4);
		align-self: center;
	}
}
.check-figs div {
	text-align: right;
}
.check-figs dt {
	font-size: var(--fs-0);
	color: var(--text-muted);
	letter-spacing: 0.04em;
}
.check-figs dd {
	margin: 0;
	font-family: var(--font-mono);
	font-size: var(--fs-1);
	font-variant-numeric: tabular-nums;
	color: var(--text);
	white-space: nowrap;
}
.check-figs dd[data-asof] {
	color: var(--text-muted);
}
.check-figs .asof {
	display: block;
	font-size: var(--fs-0);
	color: var(--text-muted);
}

/* ═══ heartbeat bar ═══════════════════════════════════════════════════════
   Up to 50 results, oldest left. Height is the non-colour cue: a pass is a
   short tick with an --ok cap, a failure stands full height in --danger, and
   only the latest result also stands tall (in its own state colour). */
.beat-bar {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	align-items: end;
	gap: 4px;
	height: 28px;
}
@media (max-width: 520px) {
	.beat-bar {
		gap: 2px;
	}
}
.pill {
	display: block;
	height: 6px;
	border-radius: 2px;
	background: var(--surface-2);
}
.pill[data-state='pass'] {
	background: var(--border-strong);
	border-top: 2px solid var(--ok);
}
.pill[data-state='fail'] {
	height: 28px;
	background: var(--danger);
}
.pill[data-state='pass'][data-newest] {
	height: 28px;
	background: var(--ok);
}
/* Each half is unbreakable; when both do not fit, the axis drops whole to its own line. */
.beat-cap {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: var(--sp-1) var(--sp-3);
	margin: var(--sp-2) 0 0;
	font-size: var(--fs-0);
	color: var(--text-muted);
	font-variant-numeric: tabular-nums;
}
.beat-axis,
[data-beat-sum] {
	white-space: nowrap;
}

/* A row whose data is not current keeps its history readable but shows no green:
   spec B9, "when data is missing or stale it never shows green". */
.check:is([data-state='unknown'], [data-state='stale']) .pill[data-state='pass'] {
	border-top-color: var(--text-muted);
}
.check:is([data-state='unknown'], [data-state='stale']) .recent td[data-r='pass'] {
	color: var(--text-muted);
}

/* ═══ recent checks ═══════════════════════════════════════════════════════ */
.recent {
	border-top: 1px solid var(--border);
	padding-top: var(--sp-3);
}
.recent > summary {
	cursor: pointer;
	width: max-content;
	font-size: var(--fs-1);
	font-weight: 600;
	color: var(--text-muted);
}
.recent > summary:hover,
.recent[open] > summary {
	color: var(--text);
}
.recent-wrap {
	overflow-x: auto;
	margin-top: var(--sp-3);
}
.recent table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--fs-1);
	font-variant-numeric: tabular-nums;
}
.recent th,
.recent td {
	text-align: left;
	padding: var(--sp-2) var(--sp-3) var(--sp-2) 0;
	border-bottom: 1px solid var(--border);
	white-space: nowrap;
}
.recent th {
	font-size: var(--fs-0);
	font-weight: 600;
	color: var(--text-muted);
}
.recent td {
	font-family: var(--font-mono);
	color: var(--text);
}
.recent td[data-r='fail'] {
	color: var(--danger);
}
.recent td[data-r='pass'] {
	color: var(--ok);
}

/* ═══ how this works ══════════════════════════════════════════════════════ */
.works-grid {
	display: grid;
	gap: var(--sp-6);
	align-items: center;
}
@media (min-width: 900px) {
	.works-grid {
		grid-template-columns: 1fr 1fr;
		gap: var(--sp-7);
	}
}
.works-note {
	color: var(--text-muted);
	font-size: var(--fs-1);
	max-width: var(--measure);
}
.term .ln .v {
	text-align: right;
}

/* ═══ closing band ════════════════════════════════════════════════════════ */
.raw-band .lede {
	margin-bottom: var(--sp-5);
}
.raw-tiles {
	display: grid;
	gap: var(--sp-4);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
}
.raw-tiles .tile h3 {
	font-size: var(--fs-3);
}

/* ═══ mast array: lights blink in more than two phases ════════════════════
   Delays only, inside no-preference; durations and counts come from
   fleet-base, so every light still rests by 30 s. */
@media (prefers-reduced-motion: no-preference) {
	.mast-art .lights circle:nth-child(3n) {
		animation-delay: -0.9s;
	}
	.mast-art .lights circle:nth-child(3n + 1) {
		animation-delay: -2.7s;
	}
	.mast-art .lights circle:nth-child(7) {
		animation-delay: 0s;
	}
}

/* Phones and tablets: the tower lattice is tall and solid, so at the shared
   0.22 it fought the pill and the CTAs. Fainter, smaller and lifted to sit
   behind the wordmark and h1, not the controls. */
@media (max-width: 899px) {
	.fleet-hero-art {
		opacity: 0.12;
		bottom: auto;
		top: var(--sp-7);
		width: 80%;
		right: -20%;
	}
}
