/* SPG Events gig guide — deliberately theme-neutral. Themes restyle via the custom properties
   below or by overriding templates/*.php. Inherits font and colour from the page. */

/* ---------------------------------------------------------------------------
   The plugin's palette, defined ONCE.
   ---------------------------------------------------------------------------
   Every root element the plugin renders carries `spg-root`, so a theme overrides
   these in a single place. They used to be repeated per component, and adding
   the single-event page duplicated them — which is how a black button ended up
   on a red theme: the theme had overridden `.spg-guide` and `.spg-specials` but
   knew nothing about `.spg-single`.
   --------------------------------------------------------------------------- */
.spg-root {
	--spg-gap: 1rem;
	/* The page's own background. Needed so a sticky day bar is opaque as rows scroll under it —
	   the plugin cannot know the theme's ground, so the theme overrides this alongside the
	   accents. Transparent would let event rows show through the heading. */
	--spg-page-bg: #fff;
	--spg-accent: #111;
	--spg-accent-contrast: #fff;
	--spg-muted: color-mix(in srgb, currentColor 62%, transparent);
	--spg-border: color-mix(in srgb, currentColor 16%, transparent);
	--spg-radius: 4px;
}

.spg-guide {
	container-type: inline-size;
}

/* The LIST view is capped and centred. At the theme's wide width a row gives its description
   far more than a comfortable measure — the block is wide so the GRID can hold four columns,
   not so rows can stretch. The grid keeps the full width.

   64rem, which is 896px: the SAME pixel width this was tuned to when the root was 16px and the
   cap read 56rem. Dropping the root to 14px silently took 112px off the guide and squeezed the
   blurb to 43 characters a line. A cap expressed in rem moves when the root moves — that is
   usually what you want, but not for a measure that was set by counting characters. */
.spg-guide:not(.spg-guide--grid) {
	max-width: 64rem;
	margin-inline: auto;
}

/* Careful: this is a GROUPED selector. An earlier pass added a left indent here meaning to
   indent only the rows inside a day, and it silently indented the outer day list as well. */
.spg-guide__days,
.spg-guide__list,
.spg-day__events {
	list-style: none;
	margin: 0;
	padding: 0;
}

.spg-guide__empty {
	color: var(--spg-muted);
}

/* ---- day grouping ---- */

/* Type scale, largest to smallest: page title (~47px) > DAY (28px) > event title (20px) >
   body (15px). The day heading used to be 16px — SMALLER than the 20px event titles inside it
   — so days never read as sections containing things. A container must outrank its contents. */
/* Each day is a BLOCK. Its own panel does the segmenting — no rule under the date, no line
   between rows, nothing pinned to the top of the window. The gap between blocks is the
   separation, and everything inside one edge belongs to that night. */
.spg-day {
	padding: 1.4rem 1.5rem 1.5rem;
	border-radius: calc(var(--spg-radius) * 2);
	background: color-mix(in srgb, currentColor 5%, transparent);
}
.spg-day + .spg-day {
	margin-top: 1.5rem;
}

.spg-day__bar {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 0.35rem 1rem;
	margin: 0 0 0.5rem;
}
.spg-day__heading {
	display: flex;
	align-items: baseline;
	gap: 0.5rem;
	margin: 0;
	font-size: 1.75rem;
	line-height: 1.1;
	flex: 0 0 auto;
}
.spg-day__weekday {
	font-weight: 700;
	text-transform: uppercase;
	/* Tighter than at 16px: tracking that reads as deliberate at small sizes looks loose at 28. */
	letter-spacing: 0.01em;
}
.spg-day__date {
	color: var(--spg-muted);
	font-weight: 500;
	font-size: 0.6em;
}
.spg-day__today {
	flex: 0 0 auto;
	/* Holds the badge at the right edge on a day with no offer strip in the bar. */
	margin-left: auto;
	align-self: center;
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	background: var(--spg-accent);
	color: var(--spg-accent-contrast);
	padding: 0.2em 0.6em;
	border-radius: 999px;
}

/* ---- one event ---- */

.spg-event {
	display: grid;
	/* 6rem: "From 11am" measures 90px at the shared type size, so 5.5rem wrapped it by 2px.
	   Anything wider than this just steals room from the titles. */
	/* 11rem artwork: measured against the description it costs. At the 56rem cap a row gives the
	   blurb 60 chars at 7rem and 51 at 11rem — still a comfortable measure, for a 57% bigger
	   poster. 14rem would drop it to 45, the bottom of the range. */
	grid-template-columns: 6rem 11rem minmax(0, 1fr) auto;
	gap: var(--spg-gap);
	align-items: start;
	/* Space, not a rule. A day with three gigs drew five lines — heading, three rows and the
	   offer outline — and the page read as ruled paper. */
	padding: 1.15rem 0;
}

/* Cancelled dims the TEXT only. Artwork is never faded — a sold-out or cancelled show still
   deserves a legible poster, and its state is already carried by the badge. */
.spg-event.is-cancelled .spg-event__title,
.spg-event.is-cancelled .spg-event__time {
	text-decoration: line-through;
	opacity: 0.6;
}

.spg-event.has-no-art {
	grid-template-columns: 6rem minmax(0, 1fr) auto;
}
.spg-event.has-no-art .spg-event__art {
	display: none;
}

.spg-event__when {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
}
.spg-event__time {
	font-size: 1.0625rem;
	font-weight: 700;
	line-height: 1.1;
	font-variant-numeric: tabular-nums;
}
.spg-event__room {
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--spg-muted);
	border: 1px solid var(--spg-border);
	border-radius: 3px;
	padding: 0.15em 0.4em;
	align-self: start;
}

.spg-event__art {
	min-width: 0;
}
.spg-event__art img {
	display: block;
	width: 100%;
	height: auto; /* beat the width/height attributes WP adds */
	aspect-ratio: 1;
	/* CONTAIN, not cover. 37 of the 44 posters are Moshtix squares and fill this exactly; the
	   venue's own 7 are 4:5 and would lose 10% off the TOP and 10% off the BOTTOM to a square
	   crop — which on a poster is the title and the price line. Contained, a 4:5 poster is
	   height-limited and sits in 80% of the width, so the cost is a 10% margin each side
	   instead of destroyed artwork. A poster is a designed object, not a photograph: it can be
	   framed but it cannot be cropped. */
	object-fit: contain;
	background: color-mix(in srgb, currentColor 8%, transparent);
	border-radius: var(--spg-radius);
}

.spg-event__body {
	min-width: 0;
}
.spg-event__title {
	margin: 0 0 0.25rem;
	font-size: 1.25rem;
	line-height: 1.2;
}
.spg-event__title a {
	color: inherit;
	text-decoration: none;
}
.spg-event__title a:hover {
	text-decoration: underline;
}
.spg-event__meta,
.spg-event__artists,
.spg-event__excerpt {
	margin: 0 0 0.25rem;
	font-size: 0.9375rem;
}
.spg-event__meta {
	color: var(--spg-muted);
}
.spg-event__artists {
	font-weight: 600;
}
.spg-event__more {
	display: inline-block;
	margin-top: 0.25rem;
	font-size: 0.875rem;
}

.spg-event__badges {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.375rem;
	margin: 0.25rem 0 0.5rem;
	padding: 0;
}
.spg-badge {
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	padding: 0.2em 0.6em;
	border: 1px solid currentColor;
	border-radius: 999px;
}
.spg-badge--sold-out,
.spg-badge--cancelled {
	background: var(--spg-accent);
	color: var(--spg-accent-contrast);
	border-color: var(--spg-accent);
}

.spg-event__ctas {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	min-width: 9rem;
}
.spg-cta {
	display: inline-block;
	text-align: center;
	padding: 0.55em 1em;
	border: 1px solid currentColor;
	border-radius: var(--spg-radius);
	font-size: 0.9375rem;
	font-weight: 600;
	line-height: 1.2;
	color: inherit;
	text-decoration: none;
}
a.spg-cta.is-primary {
	background: var(--spg-accent);
	color: var(--spg-accent-contrast);
	border-color: var(--spg-accent);
}
.spg-cta.is-static {
	border-style: dashed;
	font-weight: 500;
	color: var(--spg-muted);
}


/*
 * An "Embed" CTA. The markup comes from whoever registers the spg_events/cta_embed filter —
 * a ticketing widget, a form — so this only claims the box it sits in and makes any iframe
 * inside it responsive. Without these rules a returned widget renders at its intrinsic size
 * and breaks out of the row.
 *
 * With no filter registered the CTA falls back to a plain link, which .spg-cta already covers.
 */
.spg-cta-embed {
	display: block;
	width: 100%;
	min-width: 0;
	margin: 0.25rem 0;
}
.spg-cta-embed > iframe,
.spg-cta-embed > * {
	max-width: 100%;
}
.spg-cta-embed > iframe {
	width: 100%;
	border: 0;
}

.spg-guide--single .spg-guide__heading {
	margin-top: 2rem;
}

@container (max-width: 40rem) {
	.spg-day__heading {
		font-size: 1.375rem;
	}
	.spg-day + .spg-day {
		margin-top: 2.25rem;
	}
	.spg-event,
	.spg-event.has-no-art {
		grid-template-columns: 4.5rem minmax(0, 1fr);
	}
	.spg-event__art {
		grid-column: 2;
		max-width: 11rem;
	}
	.spg-event.has-no-art .spg-event__art {
		display: none;
	}
	.spg-event__body,
	.spg-event__ctas {
		grid-column: 2;
	}
	.spg-event__ctas {
		flex-direction: row;
		flex-wrap: wrap;
	}
}

/* ---- pub du jour: the offer row ----
   The SAME grid as .spg-event, so its time lands in the time column and its dish aligns with the
   gig titles. It was a full-width band, which on a day with a single gig read as part of THAT
   gig's offering rather than as its own row. The tint keeps it distinguishable; the grid keeps it
   a peer. */

/*
 * Identical to .spg-event, deliberately: same columns, same padding, no tint, no radius, no
 * inset. The special is one of the night's listings, not a promo box parked among them.
 *
 * What still marks it as a special is the "Pub du Jour" eyebrow on the title, which is enough
 * to identify it and costs nothing in visual weight. A background tint made it read as an
 * attachment to whichever row it sat under — see the treatments table in CLAUDE.md.
 */
.spg-offer {
	display: grid;
	grid-template-columns: 6rem 11rem minmax(0, 1fr) auto;
	gap: var(--spg-gap);
	align-items: start;
	padding: 1.15rem 0;
}

.spg-offer__when {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
}
.spg-offer__time {
	font-size: 0.9375rem;
	font-weight: 600;
	line-height: 1.2;
}
.spg-offer__room {
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--spg-muted);
	border: 1px solid var(--spg-border);
	border-radius: 3px;
	padding: 0.15em 0.4em;
	align-self: start;
}

/* Carries the Pub du Jour mark, in the slot where a gig's poster goes — same box, same
   treatment, so the two kinds of row are structurally identical. Holding this column is also
   what keeps every dish name aligned with the gig titles above and below it. */
.spg-offer__art {
	min-width: 0;
}
.spg-offer__art img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	/* The Pub du Jour mark is square and fills this exactly. Contain anyway, so every artwork
	   slot on the site behaves identically if a differently-shaped mark is ever swapped in. */
	object-fit: contain;
	background: color-mix(in srgb, currentColor 8%, transparent);
	border-radius: var(--spg-radius);
}

.spg-offer__body {
	min-width: 0;
}
.spg-offer__label {
	margin: 0 0 0.1rem;
	font-size: 0.625rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--spg-muted);
}
/* The mark already says "Pub du Jour"; printing it again beside it is just saying it twice.
   The mark now renders at every width, so this is unconditional — no container query needed,
   and no risk of a width where neither the mark nor the words are showing. */
.spg-offer__label.has-mark {
	display: none;
}
.spg-offer__dish {
	margin: 0 0 0.15rem;
	font-size: 1.25rem;
	line-height: 1.2;
}
.spg-offer__dish a {
	color: inherit;
	text-decoration: none;
}
.spg-offer__dish a:hover {
	text-decoration: underline;
}
.spg-offer__copy {
	margin: 0 0 0.2rem;
	font-size: 0.9375rem;
	color: var(--spg-muted);
}
.spg-offer__price {
	margin: 0;
	font-size: 0.9375rem;
	font-weight: 600;
}
.spg-offer__ctas {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	min-width: 9rem;
}

/*
 * Narrow screens. This block MUST come after the .spg-offer base rules above: same specificity,
 * and a container query adds none, so source order alone decides it. Living in the earlier
 * @container block, these silently lost — the special kept its four-column desktop grid on a
 * phone. It went unnoticed while the mark was hidden, and showed up the moment it was not.
 */
@container (max-width: 40rem) {
	.spg-offer {
		grid-template-columns: 4.5rem minmax(0, 1fr);
	}
	/* Exactly what .spg-event__art does — a special keeps its mark on a phone for the same
	   reason a gig keeps its poster. */
	.spg-offer__art {
		grid-column: 2;
		max-width: 11rem;
	}
	.spg-offer__body,
	.spg-offer__ctas {
		grid-column: 2;
	}
	.spg-offer__ctas {
		flex-direction: row;
		flex-wrap: wrap;
	}
}

/* ---- pub du jour: the weekly board (page / block) ---- */
.spg-specials {
	container-type: inline-size;
}
.spg-specials__heading {
	margin: 0 0 0.75rem;
}
.spg-specials__list {
	list-style: none;
	margin: 0;
	padding: 0;
}
/* Every cell is placed explicitly. Auto-placement put the price on its own row whenever a
   description was present, because the description spans the full width.

   NO RULE between rows. It had a 1px border under every special, which is the ruled-paper look
   the guide deliberately dropped — and this board sits directly above the food menu, whose rows
   have no rules either. Spacing separates them. */
.spg-special {
	display: grid;
	/* Two columns, not three — the price column is gone (see templates/specials.php). */
	grid-template-columns: 6.5rem minmax(0, 1fr);
	gap: 0.1rem 1rem;
	align-items: baseline;
	padding: 0.55rem 0;
}
.spg-special__day {
	grid-column: 1;
	grid-row: 1 / span 2;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	/* 0.75rem, not 0.6875: at the 14px root the smaller value rendered at 9.6px, which is the
	   smallest type anywhere on the site and too small for a label doing real work. */
	font-size: 0.75rem;
	color: var(--spg-muted);
}
.spg-special__dish {
	grid-column: 2;
	grid-row: 1;
	font-size: 1.0625rem;
	font-weight: 700;
}
.spg-special__description {
	grid-column: 2 / -1;
	grid-row: 2;
	font-size: 0.9375rem;
	color: var(--spg-muted);
}
.spg-specials__empty {
	color: var(--spg-muted);
}

@container (max-width: 30rem) {
	.spg-special {
		grid-template-columns: minmax(0, 1fr);
	}
	.spg-special__day,
	.spg-special__dish,
	.spg-special__description {
		grid-column: 1;
	}
	.spg-special__day { grid-row: 1; }
	.spg-special__dish { grid-row: 2; }
	.spg-special__description { grid-row: 3; }
}

.spg-special__dish a {
	color: inherit;
	text-decoration: none;
}
.spg-special__dish a:hover {
	text-decoration: underline;
}

.spg-guide__recurrence {
	margin: 0 0 0.75rem;
	font-size: 1.0625rem;
	font-weight: 600;
}
.spg-guide__next-label {
	margin: 0 0 0.15rem;
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--spg-muted);
}

/* Smaller and quieter than the time itself, so the digits stay the thing the eye lands on. */
.spg-event__time-suffix {
	display: inline-block;
	margin-left: 0.3em;
	font-size: 0.65em;
	font-weight: 600;
	letter-spacing: 0.03em;
	color: var(--spg-muted);
}

.spg-event__label {
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	font-size: 0.8em;
}

/* ---------------------------------------------------------------------------
   Single event page
   ---------------------------------------------------------------------------
   Date, room, price and buttons sit ABOVE the description. The copy used to run
   first, which put the ticket link past the fold on any event with a real blurb.
   --------------------------------------------------------------------------- */

.spg-single {
	container-type: inline-size;
}

/* Breadcrumb. Replaced a "back" link, which competed with the browser's own back button and
   lost — native back restores scroll position, a link to the top of a listing does not. */
.spg-single__crumbs {
	margin: 0 0 1rem;
	font-size: 0.8125rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-weight: 700;
}
.spg-single__crumbs ol {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.4rem;
	list-style: none;
	margin: 0;
	padding: 0;
}
/* The separator is CSS, not markup — a screen reader should hear "Gigs, Chains of Rock", not a
   chevron between every item. */
.spg-single__crumbs li + li::before {
	content: "\203A";
	margin-right: 0.4rem;
	opacity: 0.55;
}
.spg-single__crumbs a {
	color: var(--spg-muted);
	text-decoration: none;
}
.spg-single__crumbs a:hover,
.spg-single__crumbs a:focus-visible {
	color: inherit;
	text-decoration: underline;
}
.spg-single__crumbs [aria-current] {
	color: var(--spg-muted);
	/* Promoter titles run to 90 characters and the h1 below already carries the full one, so the
	   trail keeps to a single line rather than wrapping to three. */
	display: inline-block;
	max-width: 24rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	vertical-align: bottom;
}

.spg-single__top {
	display: grid;
	grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
	gap: 2rem;
	align-items: start;
	margin-bottom: 2.5rem;
}
.spg-single.has-no-art .spg-single__top {
	grid-template-columns: minmax(0, 1fr);
}
.spg-single__img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1;
	object-fit: contain;
	background: color-mix(in srgb, currentColor 8%, transparent);
	border-radius: var(--spg-radius);
}

/* Grid items default to min-width:auto, so a long unbroken word in a title can blow the column
   wider than its track and push the artwork off. */
.spg-single__intro {
	min-width: 0;
}

.spg-single__date {
	margin: 0 0 0.35rem;
	font-size: 0.875rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}
.spg-single__title {
	margin: 0 0 0.5rem;
	font-size: clamp(1.75rem, 4cqi + 1rem, 2.75rem);
	line-height: 1.1;
}
.spg-single__meta {
	margin: 0 0 0.5rem;
	font-size: 1rem;
	color: var(--spg-muted);
}
.spg-single__artists {
	margin: 0 0 0.75rem;
	font-size: 1rem;
	font-weight: 600;
}
.spg-single__badges {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.375rem;
	margin: 0 0 0.75rem;
	padding: 0;
}
.spg-single__ctas {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	margin-top: 1.25rem;
}
.spg-single__ctas .spg-cta {
	min-width: 11rem;
	padding: 0.75em 1.4em;
	font-size: 1rem;
}

/* Wide is right for the artwork-beside-detail header, wrong for prose: at 1040px a paragraph
   runs ~150 characters a line, roughly double a comfortable measure. */
.spg-single__about,
.spg-single__dates {
	max-width: 42rem;
}

.spg-single__about-heading {
	margin: 0 0 0.6rem;
	font-size: 1.125rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

/* A fixed visible height regardless of how much the promoter wrote, so every event page has the
   same shape. Clamped by default (no flash of full text); <noscript> in the template lifts it so
   copy is never truncated with no way to read on. */
.spg-single__copy {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 6;
	overflow: hidden;
}
.spg-single__copy.is-expanded {
	display: block;
	-webkit-line-clamp: unset;
	overflow: visible;
}
.spg-single__copy > :first-child {
	margin-top: 0;
}

.spg-single__more {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	margin-top: 0.75rem;
	padding: 0.5em 0;
	font: inherit;
	font-size: 0.9375rem;
	font-weight: 700;
	color: inherit;
	background: none;
	border: 0;
	border-bottom: 2px solid currentColor;
	cursor: pointer;
}
.spg-single__more::after {
	content: "";
	width: 0.5em;
	height: 0.5em;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: translateY(-0.15em) rotate(45deg);
}
.spg-single__more[aria-expanded="true"]::after {
	transform: translateY(0.1em) rotate(225deg);
}

.spg-single__dates {
	margin-top: 2.5rem;
}
.spg-single__date-list {
	list-style: none;
	margin: 0;
	padding: 0;
}
.spg-single__date-list li {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.6rem 0;
	border-bottom: 1px solid var(--spg-border);
	font-size: 1rem;
}

/* 38rem, not 44: the two-column layout needs ~600px to be worth having, and the theme's
   constrained width is 40.3rem — a 44rem breakpoint collapsed it on every screen size. */
@container (max-width: 38rem) {
	.spg-single__top {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.25rem;
	}
	.spg-single__art {
		max-width: 16rem;
	}
	.spg-single__ctas .spg-cta {
		flex: 1 1 12rem;
	}
}

.spg-see-all {
	margin-top: 2rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	font-size: 0.875rem;
}

/* ---- previous / next between events ---- */

.spg-nav {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--spg-gap);
	margin-top: 3rem;
	padding-top: 1.5rem;
	border-top: 2px solid currentColor;
}
.spg-nav__link {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	padding: 0.9rem 1rem;
	border: 1px solid var(--spg-border);
	border-radius: var(--spg-radius);
	color: inherit;
	text-decoration: none;
	min-width: 0;
}
.spg-nav__link.is-empty {
	border: 0;
}
a.spg-nav__link:hover {
	border-color: currentColor;
}
a.spg-nav__link:focus-visible {
	outline: 3px solid currentColor;
	outline-offset: 2px;
}
.spg-nav__link--next {
	text-align: right;
}
.spg-nav__dir {
	font-size: 0.625rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--spg-muted);
}
.spg-nav__link--prev .spg-nav__dir::before {
	content: "← ";
}
.spg-nav__link--next .spg-nav__dir::after {
	content: " →";
}
.spg-nav__date {
	font-size: 0.8125rem;
	color: var(--spg-muted);
}
.spg-nav__title {
	font-weight: 700;
	line-height: 1.25;
	/* Two lines maximum: a 90-character promoter title must not make one card twice the height
	   of the other. */
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}

@container (max-width: 38rem) {
	.spg-nav {
		grid-template-columns: 1fr;
	}
	.spg-nav__link.is-empty {
		display: none;
	}
	.spg-nav__link--next {
		text-align: left;
	}
}

/* ---------------------------------------------------------------------------
   Food menu — dot leaders
   ---------------------------------------------------------------------------
   Real "." characters at the text's own font size, running from the last
   character of the dish to the price — and from the last character of the LAST
   LINE when the dish wraps.

   It was a flexing element with a 2px dotted border. That could never follow a
   wrapped dish: as a SIBLING of the text it only ever sat beside the first line,
   and its dots had their own size and rhythm rather than the type's.

   How it works. The leader is inline, glued to the end of the text with no
   whitespace, so it starts exactly where the dish ends on whatever line that is.
   It is an inline-block of ZERO width holding a nowrap run of dots, so it adds
   nothing to the line and can never itself cause a wrap or be pushed onto a line
   of its own. Its dots overflow to the right and .spg-menu__text clips them.
   The price is taken out of flow and pinned bottom-right, which is what puts it
   on the last line of a wrapped dish.
   --------------------------------------------------------------------------- */

.spg-menu {
	container-type: inline-size;
}
.spg-menu__heading {
	margin: 0 0 1.25rem;
	/* Matches .spg-day__heading in the guide — the section title outranks its contents by the
	   same amount everywhere. */
	font-size: 1.75rem;
	line-height: 1.1;
}
/*
 * One line under the menu heading, saying what this menu IS.
 *
 * Deliberately sets NO font-size and NO colour, so it renders exactly like an ordinary paragraph
 * on whatever page it appears. On the Pub du Jour page that means it matches the intro line under
 * the page title by construction, rather than by someone matching two numbers by hand and them
 * drifting apart the next time the type scale moves.
 */
.spg-menu__intro {
	margin: 0.35rem 0 1.75rem;
	max-width: 42rem;
}

.spg-menu__section + .spg-menu__section {
	margin-top: 2.25rem;
}
.spg-menu__section-heading {
	margin: 0 0 0.15rem;
	font-size: 0.875rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}
.spg-menu__section-note {
	margin: 0 0 0.5rem;
	font-size: 0.875rem;
	color: var(--spg-muted);
}
.spg-menu__items {
	list-style: none;
	margin: 0.75rem 0 0;
	padding: 0;
}
.spg-menu__item {
	position: relative;
	padding: 0.3rem 0;
	line-height: 1.45;
	/*
	 * 0.9375rem, matching .spg-special__description and the guide's body copy.
	 *
	 * This block had NO font-size at all, so it inherited the theme's body size — 19.25px, half
	 * again bigger than every other component on the page. The specials board sits directly above
	 * it at 13–15px and the two read as different systems. Everything else on the site is sized
	 * explicitly; the menu was simply never given a value.
	 */
	font-size: 0.9375rem;
}
/* The gutter the price sits in. The leader is clipped at its edge, so the dots stop short of
   the price instead of running under it — no opaque background needed, which matters because
   what sits behind this is a tint, not a flat colour. */
.spg-menu__item.has-price {
	/* 3.75rem: holds "$120" at this size with a little air. Wider than that and short prices
	   like "$4" float in a pool of dead space, because the dots stop at a fixed x while the
	   price is right-aligned. */
	padding-right: 3.75rem;
}
.spg-menu__text {
	display: block;
	overflow: hidden;
}
.spg-menu__name::after {
	content: ",";
}
/* No description means no comma to separate it from. :only-child stopped working once the
   leader became a sibling inside the text, so the leader is matched directly. */
.spg-menu__name:last-child::after,
.spg-menu__name:nth-last-child(2):has(+ .spg-menu__leader)::after {
	content: "";
}
.spg-menu__desc {
	color: var(--spg-muted);
}
.spg-menu__leader {
	/* Zero width: it contributes nothing to the line, so however little room is left after the
	   dish it can never be pushed onto a line of its own. Its content simply overflows. */
	display: inline-block;
	width: 0;
	white-space: nowrap;
	vertical-align: baseline;
	color: var(--spg-muted);
}
.spg-menu__leader::before {
	/* Leading NBSP, for two reasons. It has to live INSIDE the content rather than be padding
	   on the element: padding gave the leader real width, and on a dish whose last line ended
	   near the right edge there was no room for it, so the whole leader was pushed down and
	   drew a line of nothing but dots. And it has to be a NON-BREAKING space, because the
	   inline-block starts its own line box and an ordinary leading space is trimmed there —
	   which is exactly what happened: the dots ran straight into the last letter.

	   160 characters, long enough to cross the widest row this menu can produce, and all of
	   equal width because the face is monospaced. */
	content: "\00a0..............................................................................................................................................................";
}
.spg-menu__price {
	position: absolute;
	right: 0;
	/* Matches .spg-menu__item's padding, so the price sits on the LAST line's box rather than
	   the first. That is the whole reason it is out of flow. */
	bottom: 0.3rem;
	line-height: 1.45;
	font-variant-numeric: tabular-nums;
}
.spg-menu__price::before {
	content: "$";
}
.spg-menu__footnote {
	margin: 2rem 0 0;
	font-size: 0.875rem;
	color: var(--spg-muted);
}
.spg-menu__empty {
	color: var(--spg-muted);
}

@container (max-width: 30rem) {
	.spg-menu__item.has-price {
		padding-right: 3.5rem;
	}
}

/* ---------------------------------------------------------------------------
   Gig guide — poster grid
   ---------------------------------------------------------------------------
   Answers "what's coming up that I want to see", so it leads with the artwork
   and carries the date on each card rather than in a day heading.
   --------------------------------------------------------------------------- */

.spg-guide--grid {
	container-type: inline-size;
}
.spg-grid {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	/* auto-fill, not auto-fit: a single remaining gig keeps a card's width instead of stretching
	   its poster across the whole row. */
	grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
	gap: 2rem 1.5rem;
}
.spg-card {
	display: flex;
	flex-direction: column;
	min-width: 0;
}
.spg-card__art {
	display: block;
	border-radius: var(--spg-radius);
	overflow: hidden;
	/* Holds the row's rhythm even when a gig has no poster, so cards below stay aligned. */
	aspect-ratio: 1;
	background: color-mix(in srgb, currentColor 8%, transparent);
}
.spg-card__art img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}
.spg-card.is-cancelled .spg-card__title,
.spg-card.is-cancelled .spg-card__when {
	text-decoration: line-through;
	opacity: 0.6;
}

.spg-card__body {
	flex: 1 1 auto;
	padding-top: 0.7rem;
	min-width: 0;
}
.spg-card__when {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 0.15rem 0.5rem;
	margin: 0 0 0.2rem;
	font-size: 0.75rem;
}
.spg-card__date {
	font-weight: 700;
	letter-spacing: 0.08em;
}
.spg-card__time {
	color: var(--spg-muted);
	margin-left: 0.35rem;
}
.spg-card__room {
	font-size: 0.625rem;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--spg-muted);
	border: 1px solid var(--spg-border);
	border-radius: 3px;
	padding: 0.1em 0.35em;
}
.spg-card__title {
	margin: 0 0 0.35rem;
	font-size: 1.0625rem;
	line-height: 1.25;
	/* Three lines maximum: promoter titles run long and a ragged grid reads as broken. */
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	overflow: hidden;
}
.spg-card__title a {
	color: inherit;
	text-decoration: none;
}
.spg-card__title a:hover {
	text-decoration: underline;
}
.spg-card__badges {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.3rem;
	margin: 0 0 0.4rem;
	padding: 0;
}
.spg-card__more {
	display: inline-block;
	font-size: 0.8125rem;
}
.spg-card__ctas {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	margin-top: 0.6rem;
}
.spg-card__ctas .spg-cta {
	font-size: 0.875rem;
	padding: 0.5em 0.9em;
}

@container (max-width: 30rem) {
	.spg-grid {
		grid-template-columns: 1fr 1fr;
		gap: 1.5rem 1rem;
	}
	.spg-card__ctas .spg-cta {
		font-size: 0.8125rem;
	}
}


/* ---------------------------------------------------------------------------
   "See more" — the folded guide on the homepage
   --------------------------------------------------------------------------- */
/* 0,2,0, so it beats the plain .spg-day rules above. The fold is server-rendered; a <noscript>
   block in the template restores `display: list-item` and hides the button. */
.spg-guide__days .spg-day.is-folded {
	display: none;
}
.spg-guide__days .spg-day.is-folded + .spg-day {
	/* The day after a folded one must not keep the 1.5rem gap meant to separate it from a
	   sibling that is no longer there — otherwise revealing days visibly re-spaces the list. */
	margin-top: 0;
}
.spg-guide__more {
	display: block;
	margin: 1.5rem auto 0;
	padding: 0.7em 1.6em;
	font: inherit;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: inherit;
	background: none;
	border: 1px solid var(--spg-border);
	border-radius: var(--spg-radius);
	cursor: pointer;
}
.spg-guide__more:hover {
	border-color: currentColor;
	background: color-mix(in srgb, currentColor 8%, transparent);
}
.spg-guide__more:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}
/* The revealed day is focused so a keyboard lands on new content; it is a scroll target, not a
   control, so it must not draw a focus ring of its own. */
.spg-day[tabindex="-1"]:focus {
	outline: none;
}


/* ---------------------------------------------------------------------------
   Homepage hero carousel (Featured)

   Two layers per slide. A COVER copy of the artwork, blurred and dimmed, fills the slide edge to
   edge; the real poster sits on top CONTAINED, at its true shape. Cropping a 4:5 poster to a
   banner leaves a thin strip of its middle — on the Trivia poster, a band of hair and no words —
   but a contained picture on a flat ground reads as a mistake and gives text nowhere legible to
   sit. The blur solves both: full-bleed slide, whole poster, dark ground for the copy.

   🔴 Every rule is scoped `.spg-root.spg-hero` (0,3,0) on purpose. These are ordinary h2, p and
   ol elements inside .wp-block-post-content, and the theme's section-spacing rule is
   `.wp-block-post-content h2:not(.spg-menu__heading)` — :not() carries its ARGUMENT's
   specificity, so that is 0,2,1 and a two-class override loses on the element. Same trap that put
   a 3.5rem gap above every featured title.
   --------------------------------------------------------------------------- */
.spg-root.spg-hero {
	position: relative;
	/* 🔴 WITHOUT THIS THE MOBILE LAYOUT NEVER RUNS. Every narrow-screen rule for the hero lives in
	   `@container (max-width: 34rem)`, and a container query with no container to query simply
	   never matches — so the carousel kept its desktop two-column grid on a phone and said
	   nothing about it. Unlike .spg-guide / .spg-specials / .spg-single / .spg-menu, this section
	   does not carry .spg-guide, so it inherited no container from anywhere.
	   A missing container fails SILENTLY and looks exactly like a breakpoint that is simply wrong. */
	container-type: inline-size;
	/* 64rem = 896px, the SAME cap the guide list and the footer use. This section does not carry
	   `.spg-guide`, so it inherits nothing — left uncapped it ran to the full alignwide 1180px and
	   started 190px left of the listings beneath it, which reads as a broken page rather than a
	   wide hero. `auto`, not 0, or the cap applies and the box sits flush left. */
	max-width: 64rem;
	margin: 0 auto 3rem;
}
.spg-root.spg-hero .spg-hero__track {
	display: flex;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	list-style: none;
	margin: 0;
	padding: 0;
	/* The dots ARE the position indicator; a scrollbar under a hero is chrome, not information. */
	scrollbar-width: none;
}
.spg-root.spg-hero .spg-hero__track::-webkit-scrollbar {
	display: none;
}
.spg-root.spg-hero .spg-hero__slide {
	position: relative;
	flex: 0 0 100%;
	min-width: 0;
	overflow: hidden;
	scroll-snap-align: start;
	border-radius: calc(var(--spg-radius) * 2);
	/* Opaque, so the blur has something to sit on and the text has a known ground. */
	background: var(--spg-page-bg);
}
.spg-root.spg-hero .spg-hero__bg {
	position: absolute;
	inset: 0;
	z-index: 0;
	background-size: cover;
	background-position: center;
	/* scale() hides the soft, semi-transparent edge a blur leaves at the box boundary. */
	filter: blur(40px) saturate(1.25);
	transform: scale(1.25);
	opacity: 0.34;
}
/* 🔴 THE SCRIM, and it is not decoration.
   Measured before it existed: a LIGHT poster blurred at 34% lifted the near-black ground to
   rgb(83,64,63), and the brand red — already only 4.46:1 on flat black — fell to **2.21:1** for
   the title and eyebrow. A dark poster measured 3.92:1. That is the fundamental problem with text
   over imagery: the contrast is a property of whatever picture someone uploads next.
   The scrim makes the ground predictable, heaviest on the right where the copy sits. */
.spg-root.spg-hero .spg-hero__slide::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background: linear-gradient(to right,
		color-mix(in srgb, var(--spg-page-bg) 30%, transparent) 0%,
		color-mix(in srgb, var(--spg-page-bg) 72%, transparent) 45%,
		color-mix(in srgb, var(--spg-page-bg) 82%, transparent) 100%);
}

.spg-root.spg-hero .spg-hero__inner {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
	gap: 2rem;
	align-items: center;
	padding: 2rem;
	min-height: 17rem;
}
.spg-root.spg-hero .spg-hero__slide.has-no-art .spg-hero__inner {
	grid-template-columns: minmax(0, 1fr);
}
.spg-root.spg-hero .spg-hero__art {
	/* It is an <a> now, so it needs this to keep behaving like the block it replaced. */
	display: block;
}
.spg-root.spg-hero .spg-hero__art img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1;
	object-fit: contain;
	border-radius: var(--spg-radius);
}
.spg-root.spg-hero .spg-hero__text {
	min-width: 0;
}
/* 🔴 The hero copy is WHITE, not the brand red that everything else on the site uses.
   Both palettes here are dark (red-on-near-black, and white-on-black in high contrast), so white
   is safe in either — and it is the only colour that survives an arbitrary photograph behind it.
   The red is not lost: it is still the CTA's fill, which is where it does the selling.
   Do not "restore" this to var(--spg-accent) for consistency. It was measured, and it failed. */
.spg-root.spg-hero .spg-hero__eyebrow,
.spg-root.spg-hero .spg-hero__title,
.spg-root.spg-hero .spg-hero__title a {
	color: #fff;
}
.spg-root.spg-hero .spg-hero__eyebrow {
	margin: 0 0 0.4rem;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}
.spg-root.spg-hero .spg-hero__title {
	margin: 0 0 0.5rem;
	/* 🔴 A flat size stepped in the @container block below, NOT clamp(…, 3.5vw, …).
	   `vw` measures the VIEWPORT; everything else about this hero measures its CONTAINER, and the
	   two disagree — the hero is capped at 896px, so on a 1727px monitor the title sized off the
	   monitor regardless of how wide the hero actually was. Measured: a 358px-wide hero still
	   rendering a 31.5px title. Mixing viewport units into a container-queried component is a
	   guaranteed future mismatch. */
	font-size: 2rem;
	line-height: 1.1;
}
.spg-root.spg-hero .spg-hero__title a {
	color: inherit;
	text-decoration: none;
}
.spg-root.spg-hero .spg-hero__title a:hover,
.spg-root.spg-hero .spg-hero__title a:focus-visible {
	text-decoration: underline;
}
.spg-root.spg-hero .spg-hero__blurb {
	margin: 0 0 1.1rem;
	font-size: 0.9375rem;
	/* A real light grey, not var(--spg-muted): muted is derived from currentColor, and over a
	   picture it lands wherever the picture puts it. */
	color: #DDD;
	/* THREE lines. The clamp is a guard against a 1600-character promoter blurb making one slide
	   twice the height of the next — not a target. Two was too tight: a 122-character line of the
	   venue's own copy needed four lines on a 360px phone and lost its tail, which is where the
	   price sits. Measured at 326 / 358 / 398px and desktop. */
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.spg-root.spg-hero .spg-hero__cta {
	display: inline-block;
	padding: 0.7em 1.6em;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--spg-accent-contrast);
	background: var(--spg-accent);
	border-radius: var(--spg-radius);
}
.spg-root.spg-hero .spg-hero__cta:hover {
	opacity: 0.88;
}
.spg-root.spg-hero .spg-hero__cta:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

.spg-root.spg-hero .spg-hero__nav {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	margin-top: 1rem;
}
.spg-root.spg-hero .spg-hero__arrow {
	/* 🔴 PIXELS, not rem, and the comment that used to sit here was WRONG. It said "2.75rem =
	   44px", which is true at a 16px root — but this site sets the root to 87.5% (14px), so it
	   rendered 38.5px and shipped a tap target under the 44px floor. Measured: 39x39.
	   A tap target is a PHYSICAL measure, like the guide's character-counted caps: it must not
	   move when the type scale does. The project has now been bitten by the 14px root three
	   times; anything whose rem value encodes a measured pixel size needs re-deriving. */
	width: 44px;
	height: 44px;
	font: inherit;
	font-size: 1.5rem;
	line-height: 1;
	color: inherit;
	background: none;
	border: 1px solid var(--spg-border);
	border-radius: 50%;
	cursor: pointer;
}
.spg-root.spg-hero .spg-hero__arrow:hover {
	border-color: currentColor;
	background: color-mix(in srgb, currentColor 8%, transparent);
}
.spg-root.spg-hero .spg-hero__arrow:focus-visible,
.spg-root.spg-hero .spg-hero__dot:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}
.spg-root.spg-hero .spg-hero__dots {
	display: flex;
	align-items: center;
	/* No gap: the 44px buttons already hold the dots apart, and spacing them further pushes the
	   row past a 360px screen once there are four or five slides. */
	gap: 0;
	list-style: none;
	margin: 0;
	padding: 0;
}
.spg-root.spg-hero .spg-hero__dot {
	display: block;
	/* The visible dot is 7px; the BUTTON is 44px. The radial-gradient draws the dot in the middle
	   of a transparent 44px box, so the thumb gets a full target and the eye gets a small dot.
	   Was 1.5rem, which at the 14px root measured 21x21 — a third of the area a thumb needs. */
	width: 44px;
	height: 44px;
	padding: 0;
	background: radial-gradient(circle, currentColor 0 3.5px, transparent 3.5px);
	border: 0;
	border-radius: 50%;
	opacity: 0.45;
	cursor: pointer;
}
.spg-root.spg-hero .spg-hero__dot[aria-current="true"] {
	opacity: 1;
}

@container (max-width: 34rem) {
	.spg-root.spg-hero .spg-hero__inner {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.25rem;
		padding: 1.25rem;
		text-align: center;
	}
	.spg-root.spg-hero .spg-hero__art {
		max-width: 11rem;
		margin-inline: auto;
	}
	/* This step was MISSING, so the hero title stayed at its desktop size on a phone. */
	.spg-root.spg-hero .spg-hero__title {
		font-size: 1.5rem;
	}
	.spg-root.spg-hero .spg-hero__blurb {
		-webkit-line-clamp: 4;
	}
}

/* Mirrors .spg-menu__intro exactly — including setting NO font-size, so the two halves of the
   Food page match by construction rather than by two numbers being kept in step by hand. */
.spg-specials__intro {
	margin: 0.35rem 0 1.75rem;
	max-width: 42rem;
}
