/* ==========================================================================
   Events Upcoming Grid (neilkelly/events-upcoming)
   Figma: 19 — Events Hub / Zone/UpcomingEvents (2045:43)
   Token-driven, plain CSS. Muted band: heading + filter tabs (sticky on
   desktop) + a 3-up grid of event cards. No empty state — the section is SMART
   and hides itself when there are no upcoming events.
   Wrapper: .wp-block-neilkelly-events-upcoming.nk-events-upcoming
   ========================================================================== */
.wp-block-neilkelly-events-upcoming.nk-events-upcoming {
	background: var(--wp--preset--color--surface-section);
	font-family: var(--wp--preset--font-family--inter);
	padding-block: var(--wp--custom--components--events--upcoming-pad-block);
	box-sizing: border-box;
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__inner {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--8);
	width: 100%;
	max-width: var(--wp--custom--layout--max-width);
	margin-inline: auto;
	padding-inline: var(--wp--preset--spacing--gutter);
	box-sizing: border-box;
}

/* ── Header / filters ──────────────────────────────────────────────────── */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__header {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--4);
}

/* Optional intro between the heading and the filter rows — rendered only where the
   seam supplies copy (the Location Events hub). Same treatment as
   nk-event-presenters__body and nk-locservice-designers__body, so every intro on
   the template reads alike; the header's flex gap handles the spacing. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__body {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--4);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__body p {
	margin: 0;
	font-size: var(--wp--preset--font-size--md);
	font-weight: var(--wp--custom--font-weight--regular);
	line-height: var(--wp--custom--line-height--md);
	color: var(--wp--preset--color--ink-secondary);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__heading {
	/* Headline measure — three quarters of the content column, theme-wide (Shawn, 2026-08-18). */
	max-width: var(--wp--custom--layout--headline-measure);
	/* Size + case from the shared .nk-headline--content class (mapped in render.php). */
	margin: 0;
	font-weight: var(--wp--custom--font-weight--extrabold);
	line-height: var(--wp--custom--line-height--none);
	letter-spacing: var(--wp--custom--components--events--badge-tracking);
	color: var(--wp--preset--color--ink-primary);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__filters {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--3);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__filter-row {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--2-5);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__filter-label {
	flex: 0 0 var(--wp--custom--components--events--filter-label-width);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: var(--wp--custom--font-weight--semibold);
	line-height: var(--wp--custom--line-height--none);
	color: var(--wp--preset--color--ink-secondary);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__tabs {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--2-5);
}

/* Tabs are <button>s (filtering is client-side), so they need the UA button
   styling reset back to the pill the design calls for. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__tab {
	appearance: none;
	-webkit-appearance: none;
	margin: 0;
	display: inline-flex;
	align-items: center;
	padding: var(--wp--preset--spacing--2) var(--wp--preset--spacing--4);
	border: 1px solid var(--wp--preset--color--border-default);
	border-radius: var(--wp--custom--radius--lg);
	background: var(--wp--preset--color--surface-card);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--sm-md);
	font-weight: var(--wp--custom--font-weight--medium);
	line-height: var(--wp--custom--line-height--none);
	color: var(--wp--preset--color--ink-secondary);
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease;
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__tab:hover,
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__tab:focus-visible {
	border-color: var(--wp--preset--color--ink-secondary);
	color: var(--wp--preset--color--ink-primary);
}

/* Active state is a brand-red pill — a tab/filter accent, which is one of the
   non-CTA uses red is still reserved for. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__tab.is-active {
	background: var(--wp--preset--color--brand-red);
	border-color: var(--wp--preset--color--brand-red);
	color: var(--wp--preset--color--brand-white);
}

/* The active pill can't take the grey hover treatment above (it would go
   unreadable), so it deepens to the brand hover red instead. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__tab.is-active:hover,
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__tab.is-active:focus-visible {
	background: var(--wp--preset--color--brand-red-hover);
	border-color: var(--wp--preset--color--brand-red-hover);
	color: var(--wp--preset--color--brand-white);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__tab:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-red);
	outline-offset: 2px;
}

/* ── Result count / no-results ─────────────────────────────────────────── */
/* The count has no visual styling: it carries .screen-reader-text (see render.php)
   so it announces filter results without showing a count line. Being positioned
   out of flow, it also adds no gap to the flex column. */

/* flex + gap so the trailing link sits on the same line as the message and wraps as a
   unit on narrow screens. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--1-5);
	margin: 0;
	font-size: var(--wp--preset--font-size--sm-md);
	font-weight: var(--wp--custom--font-weight--regular);
	color: var(--wp--preset--color--ink-secondary);
}

/* [hidden] has to win over the display:flex above, or view.js can't hide it. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results[hidden] {
	display: none;
}

/* Visually hidden but readable by assistive tech (defined per block, as in
   project-finder/style.css — there is no global utility). */
.wp-block-neilkelly-events-upcoming .screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ── Grid ──────────────────────────────────────────────────────────────── */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--6);
	margin: 0;
	padding: 0;
	list-style: none;
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__item {
	display: flex;
}

/* view.js filters by toggling the [hidden] attribute. That is only a UA-level
   display:none, so the author `display` rules above outrank it and the element
   stays visible — the attribute has to be restated here to actually bite. Same
   guard as nk-blog-hub__item[hidden]. Any new display rule on these two elements
   needs a matching [hidden] rule, or filtering silently stops working. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__item[hidden],
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__grid[hidden] {
	display: none;
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__card {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--2-5);
	width: 100%;
	min-height: var(--wp--custom--components--events--card-min-height);
	padding: var(--wp--preset--spacing--6);
	background: var(--wp--preset--color--surface-card);
	border: 1px solid var(--wp--preset--color--border-default);
	border-radius: var(--wp--custom--radius--card);
	box-sizing: border-box;
	transition: all 0.25s ease;
}
/* Whole card is one click target — the event CTA's ::after covers the card. */
a.nk-events-upcoming__cta::after { content: ""; position: absolute; inset: 0; }

/* Card raise on hover / keyboard focus (image-less card — the raise is the signal).
   Scoped to the CTA rather than any `a`: the host byline is also a link now, and
   focusing it must ring the byline, not the whole card. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__card:hover,
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__card:has(.nk-events-upcoming__cta:focus-visible) {
	transform: translateY(calc(-1 * var(--wp--custom--components--card--raise-lift)));
	box-shadow: var(--wp--custom--shadow--card-raise);
}

/* Keyboard focus on the card's own action: red ring around the whole card. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__card:has(.nk-events-upcoming__cta:focus-visible) {
	outline: 2px solid var(--wp--preset--color--brand-red);
	outline-offset: 2px;
}

/* ── Badges ────────────────────────────────────────────────────────────── */
/* Same pill treatment and tokens as nk-blog-hub__tag, nk-reviews-featured__market
   and the learning-hub-articles port — one pill across the site. Keep the four in
   step. The transparent border is this badge's own concern: the in-person variant
   below outlines instead of filling, and reserving the border here keeps both
   variants the same height. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__badge {
	align-self: flex-start;
	display: inline-flex;
	align-items: center;
	padding: var(--wp--preset--spacing--2);
	border: 1px solid transparent;
	border-radius: var(--wp--custom--radius--full);
	font-size: var(--wp--preset--font-size--xxs);
	font-weight: var(--wp--custom--font-weight--bold);
	line-height: var(--wp--custom--line-height--none);
	letter-spacing: var(--wp--custom--letter-spacing--wide);
	text-transform: uppercase;
	white-space: nowrap;
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__badge--online {
	background: var(--wp--preset--color--brand-red);
	border-color: var(--wp--preset--color--brand-red);
	color: var(--wp--preset--color--brand-white);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__badge--in-person {
	background: transparent;
	border-color: var(--wp--preset--color--brand-red);
	color: var(--wp--preset--color--brand-red);
}

/* ── Card text ─────────────────────────────────────────────────────────── */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--md);
	font-weight: var(--wp--custom--font-weight--semibold);
	line-height: var(--wp--custom--line-height--lg-tight);
	color: var(--wp--preset--color--ink-primary);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__date {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: var(--wp--custom--font-weight--medium);
	line-height: var(--wp--custom--line-height--none);
	color: var(--wp--preset--color--ink-secondary);
}

/* Plain text — the venue carries no marker icon. Back to a block <p>: the flex
   row and its gap only existed to seat the pin beside the name. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__venue {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: var(--wp--custom--font-weight--regular);
	line-height: var(--wp--custom--line-height--none);
	color: var(--wp--preset--color--ink-secondary);
}

/* Optional Venue Link. Inherits the line's colour rather than reading as a second
   CTA — underline on hover/focus is what marks it as a link. Same escape from the
   whole-card CTA overlay as a.nk-events-upcoming__host, or the card's own link
   would swallow every click on it. */
.wp-block-neilkelly-events-upcoming a.nk-events-upcoming__venue-link {
	position: relative;
	z-index: 1;
	color: inherit;
	text-decoration: none;
}

.wp-block-neilkelly-events-upcoming a.nk-events-upcoming__venue-link:hover,
.wp-block-neilkelly-events-upcoming a.nk-events-upcoming__venue-link:focus-visible {
	text-decoration: underline;
}

.wp-block-neilkelly-events-upcoming a.nk-events-upcoming__venue-link:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-red);
	outline-offset: 2px;
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__excerpt {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm-md);
	font-weight: var(--wp--custom--font-weight--regular);
	line-height: var(--wp--custom--components--events--card-desc-line-height);
	color: var(--wp--preset--color--ink-primary);
}

/* ── Host (closes the copy, under the excerpt and above the CTA) ───────── */
/* Matches nk-learning-hub-workshops__host — the byline the Resources hub uses
   for the same Event CPT data: a 40px bordered round avatar beside a bold
   ink-primary "Hosted by {name}" over a secondary role, both at --sm. The same
   treatment nk-project-related__designer carries, so the three agree.
   Classes stay events-namespaced rather than shared, which is the deliberate
   duplication the project cards already use (a partial extraction was tried
   there and reverted). KEEP IN STEP WITH learning-hub-workshops/style.css. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__host {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--3);
	margin-top: var(--wp--preset--spacing--1);
	text-decoration: none;
	color: inherit;
}

/* The card's CTA paints an ::after over the whole card, so the byline has to be
   lifted out of it to stay clickable — without this the host link is covered and
   every click goes to the event instead. Same escape as
   a.nk-project-related__designer. Anchors only: the <div> fallback (host with no
   profile) stays inert and needs no stacking context. */
a.nk-events-upcoming__host {
	position: relative;
	z-index: 1;
}

a.nk-events-upcoming__host:hover .nk-events-upcoming__host-name {
	text-decoration: underline;
}

a.nk-events-upcoming__host:focus-visible {
	outline: 2px solid var(--wp--preset--color--ink-primary);
	outline-offset: 2px;
	border-radius: var(--wp--custom--radius--default);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__avatar {
	display: block;
	flex: 0 0 auto;
	width: var(--wp--custom--components--events--avatar-size);
	height: var(--wp--custom--components--events--avatar-size);
	border-radius: var(--wp--custom--radius--full);
	border: 1px solid var(--wp--preset--color--border-default);
	overflow: hidden;
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__avatar-img,
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__avatar-placeholder {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center top; /* keep the head in frame, not center-cropped */
}

/* Hosts with no headshot still render the row, so the empty circle needs a fill
   — same surface-section the workshops placeholder uses. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__avatar-placeholder {
	background: var(--wp--preset--color--surface-section);
}

/* Neil Kelly box-logo fallback (no active host): the logo sits on the brand-red-logo disc
   (#d71921, the logo's own red), contained rather than cover-cropped like a headshot.
   Matches the project designer fallback avatar. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__avatar--logo .nk-events-upcoming__avatar-img {
	object-fit: contain;
	background: var(--wp--preset--color--brand-red-logo);
	padding: var(--wp--preset--spacing--0-5);
	box-sizing: border-box;
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__host-text {
	display: flex;
	flex-direction: column;
	min-width: 0;
	text-align: left;
}

/* "Hosted by {name}" is a single line now, so it carries the size itself. The
   __host-line flex wrapper and the grey __host-by span it used to need are gone
   — nk-learning-hub-workshops sets the whole prefixed string bold. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__host-name {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: var(--wp--custom--font-weight--bold);
	color: var(--wp--preset--color--ink-primary);
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__host-role {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: var(--wp--custom--font-weight--regular);
	color: var(--wp--preset--color--ink-secondary);
}

/* ── CTA (always the last thing in the card) ───────────────────────────── */
/* margin-top:auto eats the leftover column space so the CTA sits on the card's
   bottom edge however short the copy is — cards in a row keep their CTAs on one
   line. The padding is on top of the card's own flex gap. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__cta {
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--4-5);
	font-size: var(--wp--preset--font-size--sm-md);
	font-weight: var(--wp--custom--font-weight--semibold);
	line-height: var(--wp--custom--line-height--none);
	color: var(--wp--preset--color--brand-red);
	text-decoration: none;
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__cta:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-red);
	outline-offset: 2px;
}

/* Single clean focus ring: the whole-card :has() ring is the affordance, so
   suppress the inner link's own outline where :has() is supported. Legacy
   browsers without :has() keep the inner ring as the fallback. */
@supports selector(:has(*)) {
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__cta:focus-visible { outline: none; }
}

.wp-block-neilkelly-events-upcoming .nk-events-upcoming__arrow {
	white-space: nowrap;
	display: inline-block;
	transition: transform 200ms ease;
}
/* Arrow nudges right when the (whole) card is hovered/focused. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__cta:hover .nk-events-upcoming__arrow,
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__cta:focus-visible .nk-events-upcoming__arrow {
	transform: translateX(var(--wp--preset--spacing--1-5));
}
@media (prefers-reduced-motion: reduce) {
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__arrow { transition: none; }
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__card:hover,
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__card:has(.nk-events-upcoming__cta:focus-visible) { transform: none; }
}

/* ── Filtered-to-nothing link ───────────────────────────────────────────
   The published-nothing empty state that used to share these rules is gone: the
   section hides itself when there are no upcoming events, so only the
   filtered-to-nothing message remains (its own layout rule is further up). Red is a
   non-CTA accent here, which CLAUDE.md allows. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results-link {
	/* inline-flex so the trailing arrow is a flex item with its own gap, rather than
	   riding on the literal space in the markup — which is what makes the nudge below
	   read as the arrow moving away from the label. */
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--1);
	font-weight: var(--wp--custom--font-weight--semibold);
	color: var(--wp--preset--color--brand-red);
	text-decoration: none;
}

/* No underline on hover: the arrow nudge is the affordance, matching
   nk-events-more__view-all. That nudge is switched off under prefers-reduced-motion,
   which would leave hover with no feedback at all, so the link also deepens to the
   red-hover token. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results-link:hover,
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results-link:focus-visible {
	color: var(--wp--preset--color--brand-red-hover);
}

/* The underline used to be the only focus indicator this link had; with it gone it
   needs a real ring. Black rather than red, so it reads against the red text. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results-link:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-black);
	outline-offset: 2px;
}

/* The arrow nudge further up is scoped to the card CTA, so this link needs its own —
   same distance and easing. The transition itself is on __arrow. */
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results-link:hover .nk-events-upcoming__arrow,
.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results-link:focus-visible .nk-events-upcoming__arrow {
	transform: translateX(var(--wp--preset--spacing--1-5));
}

@media (prefers-reduced-motion: reduce) {
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results-link:hover .nk-events-upcoming__arrow,
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__no-results-link:focus-visible .nk-events-upcoming__arrow {
		transform: none;
	}
}

/* ── Sticky filter header on desktop (per Figma annotation) ────────────── */
@media (min-width: 1024px) {
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__header {
		position: sticky;
		/* Clears the site header once it goes sticky. Generation referenced
		   --wp--custom--layout--header-height, which does not exist (the token is
		   layout.header.height → --wp--custom--layout--header--height); the
		   declaration was dropped and the header never actually stuck. Uses the
		   same 130px clearance as the other sticky rails in the theme. */
		top: var(--wp--custom--components--events--upcoming-sticky-top);
		z-index: 2;
		background: var(--wp--preset--color--surface-section);
		padding-block: var(--wp--preset--spacing--4);
	}
}

/* ── Responsive grid ───────────────────────────────────────────────────── */
@media (max-width: 1023px) {
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 767px) {
	.wp-block-neilkelly-events-upcoming.nk-events-upcoming {
		padding-block: var(--wp--preset--spacing--16);
	}
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__inner {
		padding-inline: var(--wp--preset--spacing--6);
	}
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__grid {
		grid-template-columns: minmax(0, 1fr);
	}
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__heading {
		font-size: var(--wp--preset--font-size--xxl-sm);
	}
	/* Steps down with the other intros on the template at the same breakpoint. */
	.wp-block-neilkelly-events-upcoming .nk-events-upcoming__body p {
		font-size: var(--wp--preset--font-size--base);
	}
}

/* No block-gap seam between full-bleed sections. */
.wp-block-neilkelly-events-upcoming { margin-block: 0; }
