/**
 * Category Page presentation.
 *
 * Owns: the hero (breadcrumb/title/intro/main image), the contextual
 * upcoming-occurrence selector (Open/Close/Change disclosure; its Date/Day/
 * Time of day/Location/Event type filters, results list and compact/mobile
 * variant), and the sub-category/Class card grid. Markup lives in
 * inc/category-page.php; client-side filtering/disclosure behaviour lives in
 * assets/js/category-selector.js — neither is owned by this stylesheet.
 *
 * Figma: node 142:3916 (Category Page), node 80:2264 (hero), node 150:1456
 * (upcoming-events bar / selector shell), node 208:714 (compact filter
 * interface), node 212:6829 (Date Picker).
 *
 * Spec ownership: docs/product-spec.md §4/§4.2/§4.3.1-§4.3.8 (selector
 * behaviour and copy) and docs/technical-spec.md §3.2 (the `--ld-section-
 * color` custom property this file consumes rather than hardcoding colour)
 * and §4.5/§7.2 (Location filter values derive from the Venue's assigned
 * `ld_location` term, not the Venue itself).
 *
 * Shared primitives consumed rather than redefined here: `.ld-btn`,
 * `.ld-breadcrumb__list` and `.ld-toggle` (assets/css/components.css);
 * `--ld-color-*`, `--ld-font-inter`, `--ld-bp-desktop`, `--ld-display-2-*`
 * and `.ld-nav__chevron` (assets/css/header.css).
 */

/* `.ld-btn`/`.ld-breadcrumb` base rules live in assets/css/components.css
 * (enqueued sitewide, functions.php) since the Class/Event single page
 * (assets/css/class-page.css) also needs them — see components.css's own
 * header comment. This file keeps only the context-specific modifiers
 * below (e.g. `.ld-occurrence-row .ld-btn`, `.ld-category-card__body
 * .ld-btn`). */

/* Hero ------------------------------------------------------------------ */

.ld-category-hero {
	background: var( --ld-section-color, var( --ld-color-peach ) );
	padding-block: 20px 0;
}

.ld-category-hero__inner {
	max-width: 1400px;
	margin-inline: auto;
	padding-inline: 20px;
}

.ld-category-hero__row {
	display: flex;
	flex-direction: column;
	gap: 20px;
	padding-bottom: 20px;
}

.ld-category-hero__title {
	margin: 0;
	font-family: var( --ld-font-inter );
	font-weight: 700;
	font-size: 40px;
	line-height: 1;
	text-transform: uppercase;
	color: var( --ld-color-black );
}

.ld-category-hero__intro {
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.5;
	max-width: 288px;
}

.ld-category-hero__intro p {
	margin: 0;
}

.ld-category-hero__image img {
	display: block;
	width: 100%;
	height: 280px;
	object-fit: cover;
}

@media ( min-width: 900px ) {
	.ld-category-hero__row {
		flex-direction: row;
		align-items: flex-end;
		justify-content: space-between;
	}

	/* H1 token (Figma node 80:2264): 90px / Extra Bold / line-height 1.
	 * The theme self-hosts Inter at weight 600/700 only (no 800 face — see
	 * theme.json), so this renders at the nearest loaded weight (700) until
	 * an Extra Bold woff2 is added. */
	.ld-category-hero__title {
		font-size: 90px;
	}

	.ld-category-hero__image img {
		height: 500px;
	}
}

/* Contextual upcoming-occurrence selector -------------------------------- */

/* Figma node 150:1456: a full-width bar beneath the hero image, not a
 * card floating over it — square corners, no overlap treatment. */
.ld-category-selector-wrap {
	background: var( --ld-section-color, var( --ld-color-peach ) );
	padding: 20px;
}

/* Layout container only — no background/border of its own. Its expanded-
 * state children are two separate white-bordered boxes (summary bar,
 * results panel) with the filter toolbar sitting directly on the
 * section-coloured background between them, deliberately not boxed. */
.ld-occurrence-selector {
	max-width: 1400px;
	margin-inline: auto;
}

.ld-occurrence-selector--empty {
	max-width: 1400px;
	margin-inline: auto;
	background: var( --ld-color-white );
	border: 2px solid var( --ld-color-black );
	padding: 15px 20px;
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
}

.ld-occurrence-selector--empty p {
	margin: 0;
}

/* Part A (Figma structure requirement): the top white bordered prompt bar
 * — contextual prompt on the left, Open/Close/Change action on the right. */
.ld-occurrence-selector__summary {
	list-style: none;
	cursor: pointer;
	padding: 15px 20px;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	background: var( --ld-color-white );
	border: 2px solid var( --ld-color-black );
}

.ld-occurrence-selector__summary::-webkit-details-marker {
	display: none;
}

.ld-occurrence-selector__summary::marker {
	content: "";
}

/* Initial/unselected state (docs/product-spec.md §4.3.1): the contextual
 * prompt. Selected state (§4.3.3): replaced by the compact Day/Date/Time/
 * Title summary — assets/js/category-selector.js toggles which of these two
 * is [hidden] on Select; both are plain text, never simultaneously shown. */
.ld-occurrence-selector__prompt,
.ld-occurrence-selector__summary-selected {
	font-family: var( --ld-font-inter );
	font-weight: 700;
	font-size: 16px;
}

/* All three Open/Close/Change labels render up front; only the
 * state-matching one is shown (Open/Close via [open] alone, Change via
 * .is-selected), so the accessible name always reflects one action. */
.ld-occurrence-selector__toggle {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px 12px;
	border-radius: 50px;
	background: var( --ld-color-black );
	color: var( --ld-color-white );
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.5;
	white-space: nowrap;
}

.ld-occurrence-selector__toggle-label {
	display: none;
}

.ld-occurrence-selector:not( [ open ] ):not( .is-selected ) .ld-occurrence-selector__toggle-label[ data-label="open" ] {
	display: inline;
}

.ld-occurrence-selector:not( [ open ] ).is-selected .ld-occurrence-selector__toggle-label[ data-label="change" ] {
	display: inline;
}

.ld-occurrence-selector[ open ] .ld-occurrence-selector__toggle-label[ data-label="close" ] {
	display: inline;
}

/* Downward chevron collapsed, upward chevron expanded (docs/product-
 * spec.md §4.3.1/§4.3.2); the exported chevron.svg points right at 0deg. */
.ld-occurrence-selector__toggle .ld-nav__chevron svg {
	transform: rotate( 90deg );
}

.ld-occurrence-selector[ open ] .ld-occurrence-selector__toggle .ld-nav__chevron svg {
	transform: rotate( -90deg );
}

/* Wraps Part B/C purely for the disclosure's aria-controls target — no
 * background/border of its own; native <details> already hides it when
 * collapsed. */
.ld-occurrence-selector__panel {
	padding-top: 15px;
}

/* "Include weekly classes" is deliberately excluded from the shared
 * six-column filter/result grid (see the @media(min-width:900px) rule
 * below) — it renders in its own row here so it cannot shift that
 * alignment. */
.ld-occurrence-selector__weekly {
	padding: 0 20px 12px;
}

/* Part B: sits directly on the section-coloured background, no white
 * panel of its own. Mobile-first wrapping flex row; the desktop
 * shared-grid rule below (900px) takes over per-column alignment. */
.ld-occurrence-selector__filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	/* Distributed across the full width, not clustered left; Reset's own
	 * margin-left: auto still pins it right even when the row wraps. */
	justify-content: space-between;
	gap: 12px 24px;
	padding: 0 20px;
}

/* Restores [hidden] over this rule's own unconditional display: flex,
 * which would otherwise outrank the UA default and defeat
 * category-selector.js's filtersPanel.hidden toggle (compact mode). */
.ld-occurrence-selector__filters[ hidden ] {
	display: none;
}

/* padding-bottom gives each filter's own box the trailing height its
 * popover's `top: 100%` anchors against — combined with every trigger
 * sharing `padding-block: 7px` (900px rule below), every popover opens at
 * the same height regardless of which filter is open. Manually verified
 * in browser; do not change without re-verifying popover position. */
.ld-occurrence-filter {
	display: flex;
	align-items: center;
	padding-bottom: 15px;
}

/* Date/Location's own inline pill label (Figma's lightweight inline filter
 * treatment): the pill's own visible text, not a caption stacked above a
 * boxed control — a normal-weight, normal-case single line. */
.ld-occurrence-filter__label {
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
}

/* Day / Time of day / Event type share Date's/Location's own trigger
 * treatment and popover primitive rather than a third parallel set of
 * rules — see .ld-occurrence-filter__popover-panel below.
 *
 * `position: relative`: this trigger is its own popover's positioned
 * ancestor, so `top: 100%`/`left: 0` on the popover panel resolve against
 * it — the same anchoring `.ld-occurrence-filter--date`/`--location`
 * below rely on. */
.ld-occurrence-filter--select {
	position: relative;
}

.ld-occurrence-filter--select .ld-nav__chevron svg {
	transform: rotate( 90deg );
}

.ld-occurrence-filter--select[ open ] .ld-nav__chevron svg {
	transform: rotate( -90deg );
}

/* One real, individually focusable/operable <button> per option
 * (docs/product-spec.md §5's accessible-implementation carve-out).
 * Shares .ld-occurrence-filter__popover-panel's positioning/border/
 * background; only the vertical option-list layout is its own. */
.ld-occurrence-filter__select-panel {
	min-width: 160px;
}

.ld-occurrence-filter__option {
	display: block;
	width: 100%;
	text-align: left;
	padding: 6px 4px;
	border: 0;
	background: transparent;
	color: var( --ld-color-black );
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.5;
	white-space: nowrap;
	cursor: pointer;
}

.ld-occurrence-filter__option:hover {
	opacity: 0.7;
}

.ld-occurrence-filter__option[ aria-pressed="true" ] {
	font-weight: 700;
	text-decoration: underline;
}

/* Date: a single <details>/<summary> disclosure opening a calendar
 * range-picker panel, rather than two visible native <input type="date">
 * From/To fields. category-selector.js builds the calendar grid into the
 * empty .ld-occurrence-filter__date-panel container; the two values that
 * actually hold the filter (data-ld-filter-date="start"/"end") are
 * `type="hidden"` and never rendered visually.
 *
 * `position: relative` anchors its popover panel — see
 * .ld-occurrence-filter--select above. */
.ld-occurrence-filter--date {
	position: relative;
}

/* Lightweight text + chevron trigger, shared by all five standard filters
 * (Date, Location and Day/Time of day/Event type's own custom single-select
 * summary) — no boxed/bordered pill, so every filter sits directly on the
 * toolbar's section-coloured surface. */
.ld-occurrence-filter__date-summary,
.ld-occurrence-filter--location > summary,
.ld-occurrence-filter--select > summary {
	list-style: none;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	padding: 0;
	border: 0;
	background: none;
	color: var( --ld-color-black );
}

.ld-occurrence-filter__date-summary::-webkit-details-marker,
.ld-occurrence-filter--location > summary::-webkit-details-marker,
.ld-occurrence-filter--select > summary::-webkit-details-marker {
	display: none;
}

.ld-occurrence-filter__date-summary::marker,
.ld-occurrence-filter--location > summary::marker,
.ld-occurrence-filter--select > summary::marker {
	content: "";
}

.ld-occurrence-filter--date > summary .ld-nav__chevron svg {
	transform: rotate( 90deg );
}

.ld-occurrence-filter--date[ open ] > summary .ld-nav__chevron svg {
	transform: rotate( -90deg );
}

/* Shared popover-panel primitive: Date's and Location's own filter panels
 * are both anchored popovers built from one identical structural/visual
 * treatment (positioning, z-index, flex layout, gap, padding, border,
 * background) rather than duplicating it per control. Positioned out of
 * flow against each trigger's own `position: relative`, so opening a
 * popover overlays the results panel rather than growing the toolbar's
 * height; category-selector.js (closeOtherFilterPopovers()/
 * closeFilterPopoversOutside()) coordinates outside-click/Escape/
 * single-open-popover behaviour via the shared `[data-ld-filter-group]`
 * attribute.
 *
 * `left: 0` is relative to each trigger's own box (its containing block,
 * via `position: relative` above). No top border — each panel reads as a
 * continuation of its trigger, not a separately boxed element. The
 * date/location-panel modifiers below carry only their genuine
 * difference: width. */
.ld-occurrence-filter__popover-panel {
	position: absolute;
	top: 100%;
	left: 0;
	z-index: 20;
	flex-direction: column;
	gap: 8px;
	padding: 15px;
	border: 2px solid var( --ld-color-black );
	border-top: none;
	border-radius: 0;
	background: var( --ld-section-color, var( --ld-color-peach ) );
}

/* `display` is deliberately scoped to `[open]` rather than living
 * unconditionally in .ld-occurrence-filter__popover-panel above — an
 * unconditional `display: flex` there would outrank the UA default that
 * hides a closed <details>'s non-summary content, rendering the popover
 * regardless of its own open state. */
[data-ld-filter-group][open] > .ld-occurrence-filter__popover-panel {
	display: flex;
}

/* Figma node 212:6829: exact 248px content width producing an exact
 * rendered panel size — not the shared popover-panel's generic 8px gap
 * (below), which suits Location's/the select's single-block panels but
 * not this composition. Compact mode resets width to `auto` (900px
 * breakpoint below).
 *
 * Border is an inset box-shadow, not the shared `border` (reset to
 * `none`): a real border sits outside the content+padding box and would
 * push the rendered size past the Figma value; box-shadow paints within
 * it instead. */
.ld-occurrence-filter__date-panel {
	width: 248px;
	padding: 20px 30px 20px;
	gap: 20px;
	border: none;
	box-shadow:
		inset -2px 0 0 var( --ld-color-black ),
		inset 2px 0 0 var( --ld-color-black ),
		inset 0 -2px 0 var( --ld-color-black );
}

/* Month/year on the left, Previous/Next grouped on the right (Figma node
 * 212:6829) — .ld-calendar__nav-group below is that pair's own wrapper so
 * `justify-content: space-between` here only ever splits the row in two. */
.ld-calendar__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
}

/* Wraps the weekday row and date grid (Figma node 212:6829's own 10px gap
 * between them) separately from the 20px header gap above. */
.ld-calendar__body {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.ld-calendar__month-label {
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.5;
	color: var( --ld-color-black );
}

.ld-calendar__nav-group {
	display: flex;
	align-items: center;
	gap: 8px;
}

/* Reuses the shared `.ld-nav__chevron` primitive (assets/icons/chevron.svg,
 * assets/css/header.css) rather than a hand-drawn glyph or a second icon
 * asset. */
.ld-calendar__nav {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	padding: 0;
	border: 0;
	background: none;
	color: var( --ld-color-black );
	cursor: pointer;
}

/* `.ld-nav__chevron svg`'s own base rotation (header.css) points it down;
 * every consumer on this page re-specifies its own rotation rather than
 * relying on that default. */
.ld-calendar__nav--next .ld-nav__chevron svg {
	transform: rotate( 0deg );
}

.ld-calendar__nav--prev .ld-nav__chevron svg {
	transform: rotate( 180deg );
}

.ld-calendar__nav:hover {
	opacity: 0.6;
}

.ld-calendar__nav:focus-visible {
	outline: 1px solid var( --ld-color-black );
	outline-offset: 2px;
}

.ld-calendar__weekdays,
.ld-calendar__grid {
	display: grid;
	grid-template-columns: repeat( 7, 1fr );
	column-gap: 7px;
}

/* Figma node 212:6829's 5px vertical row gap; the weekday header is a
 * single row so it has no rows to space and does not need this. */
.ld-calendar__grid {
	row-gap: 5px;
}

.ld-calendar__weekday {
	text-align: center;
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.5;
	text-transform: uppercase;
}

/* Figma node 212:6829's 27px row height applies identically in wide and
 * compact mode — no `aspect-ratio` here, since a wide cell must not grow
 * taller just because its column is wide. */
.ld-calendar__day,
.ld-calendar__day-placeholder {
	height: 27px;
}

/* is-range-band's rectangular background (below) lives on this element;
 * the circular selected/endpoint treatment lives on the inner
 * .ld-calendar__day-number, so the two never conflict as a single
 * `background` on one element. */
.ld-calendar__day {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 0;
	background: transparent;
	color: var( --ld-color-black );
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.5;
	cursor: pointer;
}

.ld-calendar__day-number {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	border-radius: 50%;
}

.ld-calendar__day:hover:not( :disabled ) .ld-calendar__day-number {
	outline: 1px solid var( --ld-color-black );
}

.ld-calendar__day:focus-visible {
	outline: 1px solid var( --ld-color-black );
	outline-offset: 1px;
}

.ld-calendar__day:disabled {
	opacity: 0.3;
	cursor: not-allowed;
}

/* Continuous range band: every cell from start to end (inclusive) shares
 * one flat background (buildMonthCells()'s rangeBand field), rounded only
 * at the range's outer ends, so the selection reads as one connected band
 * rather than isolated circles. Never applied to a single selected date. */
.ld-calendar__day.is-range-band {
	background: var( --ld-color-black );
}

.ld-calendar__day.is-range-start.is-range-band {
	border-radius: 999px 0 0 999px;
}

.ld-calendar__day.is-range-end.is-range-band {
	border-radius: 0 999px 999px 0;
}

.ld-calendar__day.is-range-band .ld-calendar__day-number {
	color: var( --ld-color-white );
}

/* Bridges the grid's 7px column-gap to the next band cell so the range
 * still reads as one connected shape. Excluded at the true range end
 * (nothing to bridge into) and at each row's last column (`7n` — no cell
 * to its right; the bridge would overflow the grid). */
.ld-calendar__day.is-range-band:not( .is-range-end ):not( :nth-child( 7n ) )::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	right: -7px;
	width: 7px;
	background: var( --ld-color-black );
}

/* A single selected date (no completed range yet) keeps the circular
 * black-circle/white-text treatment on the inner day-number instead of the
 * full-width band above. */
.ld-calendar__day.is-range-start:not( .is-range-band ) .ld-calendar__day-number,
.ld-calendar__day.is-range-end:not( .is-range-band ) .ld-calendar__day-number {
	background: var( --ld-color-black );
	color: var( --ld-color-white );
}

/* Location: a multi-select checkbox menu, implemented as its own native
 * <details>/<summary> disclosure rather than a bespoke dropdown widget.
 *
 * `position: relative` anchors its popover panel — see
 * .ld-occurrence-filter--select above. */
.ld-occurrence-filter--location {
	position: relative;
}

.ld-occurrence-filter--location .ld-nav__chevron svg {
	transform: rotate( 90deg );
}

.ld-occurrence-filter--location[ open ] .ld-nav__chevron svg {
	transform: rotate( -90deg );
}

/* Location's own modifier: shares .ld-occurrence-filter__popover-panel
 * above (see that rule's own comment) and differs only in width. */
.ld-occurrence-filter__location-panel {
	min-width: 200px;
}

.ld-occurrence-filter__checkbox-option {
	display: flex;
	align-items: center;
	gap: 8px;
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	cursor: pointer;
	white-space: nowrap;
}

.ld-occurrence-filter__checkbox-empty {
	margin: 0;
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	opacity: 0.7;
	white-space: nowrap;
}

/* Figma-style custom checkbox treatment. ("Include weekly classes" uses
 * the reusable `.ld-toggle` primitive instead — a switch, not a
 * checkbox.) The native checkbox remains the real control; only its
 * default browser appearance is replaced. */
.ld-occurrence-filter__checkbox-option input[ type="checkbox" ] {
	appearance: none;
	-webkit-appearance: none;
	flex-shrink: 0;
	width: 18px;
	height: 18px;
	margin: 0;
	border: 2px solid var( --ld-color-black );
	border-radius: 2px;
	background: var( --ld-color-white );
	display: inline-flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
}

.ld-occurrence-filter__checkbox-option input[ type="checkbox" ]:checked {
	background: var( --ld-color-black );
}

.ld-occurrence-filter__checkbox-option input[ type="checkbox" ]:checked::after {
	content: "";
	width: 4px;
	height: 8px;
	border: solid var( --ld-color-white );
	border-width: 0 2px 2px 0;
	transform: rotate( 45deg ) translate( -1px, -1px );
}

/* The filter toolbar's action group (Reset, and — compact mode only, see
 * the @media block below — Apply): one wrapper owns the "pin to the far
 * right of the toolbar" position instead of Reset carrying its own
 * margin-left: auto, since Apply shares that slot with it. */
.ld-occurrence-selector__filter-actions {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-left: auto;
}

.ld-occurrence-selector__reset {
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	padding: 7px 16px;
	border: 1px solid var( --ld-color-black );
	border-radius: 50px;
	background: transparent;
	color: var( --ld-color-black );
	cursor: pointer;
}

.ld-occurrence-selector__reset:hover,
.ld-occurrence-selector__reset:focus-visible {
	background: var( --ld-color-black );
	color: var( --ld-color-white );
}

/* Apply (compact mode only, see the @media(max-width:899px) block below):
 * hidden above the compact breakpoint, since wide mode filters live-apply
 * on change. No dedicated Close button — dismissal in compact mode is via
 * re-toggling the Filters trigger or Escape (category-selector.js). */
.ld-occurrence-selector__apply {
	display: none;
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	padding: 7px 16px;
	border: 1px solid var( --ld-color-black );
	border-radius: 50px;
	cursor: pointer;
	background: var( --ld-color-black );
	color: var( --ld-color-white );
}

.ld-occurrence-selector__apply:hover,
.ld-occurrence-selector__apply:focus-visible {
	background: var( --ld-color-white );
	color: var( --ld-color-black );
}

/* The Filters toggle (compact mode only — see the @media block below):
 * hidden above the compact breakpoint, since wide mode's toolbar has no
 * separate open/closed state for the filter row itself. */
.ld-occurrence-selector__filters-toggle {
	display: none;
	align-items: center;
	gap: 6px;
	padding: 7px 16px;
	border: 1px solid var( --ld-color-black );
	border-radius: 50px;
	background: transparent;
	color: var( --ld-color-black );
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	cursor: pointer;
	margin: 0 20px 15px;
}

.ld-occurrence-selector__filters-toggle .ld-nav__chevron svg {
	transform: rotate( 90deg );
}

.ld-occurrence-selector__filters-toggle[ aria-expanded="true" ] .ld-nav__chevron svg {
	transform: rotate( -90deg );
}

/* Part C (Figma structure requirement): a results panel visually separate
 * from both the prompt bar (Part A) and the filter toolbar (Part B), with
 * its own white background/border. */
.ld-occurrence-selector__results {
	max-width: 1400px;
	margin-inline: auto;
	background: var( --ld-color-white );
	border: 2px solid var( --ld-color-black );
}

.ld-occurrence-selector__list {
	list-style: none;
	margin: 0;
	padding: 0 20px 15px;
	max-height: 60vh;
	overflow-y: auto;
}

/* Shown by category-selector.js when the active filters hide every
 * result row. No [hidden] override needed here (unlike .ld-occurrence-row
 * below) — this rule declares no competing `display`, so the UA default
 * is never overridden. */
.ld-occurrence-selector__no-matches {
	margin: 0;
	padding: 15px 20px;
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
}

/* One occurrence result: title on its own first line, then Date, Day,
 * Time, Location, Event type/section-identity, Select. Each row is the
 * <li> itself, not a wrapping item plus a nested row element, so Select
 * remains its only interactive control. The `[hidden]` rule below is
 * required — this rule's own `display: grid` would otherwise outrank the
 * UA [hidden] default and defeat category-selector.js's row filtering. */
.ld-occurrence-row {
	/* Mobile-first (matching this file's own convention elsewhere): a
	 * single stacked column, so the title's own line is simply the grid's
	 * only column at this width. */
	display: grid;
	grid-template-columns: 1fr;
	gap: 6px;
	padding: 16px 0;
	/* Bottom edge, not top: a top-edge separator would double up with
	 * .ld-occurrence-selector__results' own top border immediately above
	 * the list, producing a visible double line at that boundary. */
	border-bottom: 2px solid var( --ld-color-black );
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.5;
}

.ld-occurrence-row:last-child {
	border-bottom: 0;
}

/* `:last-child` alone only catches the DOM-structural last row. Once an
 * earlier row is hidden (filtering, or a weekly-class row hidden by
 * default) while a later row stays visible, `:last-child` no longer
 * matches the true last *visible* row, leaving a stray separator.
 * `:has()` expresses "no later visible sibling" declaratively, with no
 * JS bookkeeping needed. Declared after :last-child so it wins when the
 * two disagree. */
.ld-occurrence-row:not( [ hidden ] ):not( :has( ~ .ld-occurrence-row:not( [ hidden ] ) ) ) {
	border-bottom: 0;
}

.ld-occurrence-row[ hidden ] {
	display: none;
}

/* category-selector.js's updateMonthHeadings() inserts one of these <li>
 * elements before the first visible row of each month, recomputed on
 * every filter change. A plain non-interactive divider — not a
 * `.ld-occurrence-row`, so it never participates in the grid/separator
 * rules above.
 *
 * Consumes the shared theme-owned Display 2 primitive (header.css's
 * `--ld-display-2-*`, also used by .ld-category-content below) rather
 * than a bespoke typography treatment. */
.ld-occurrence-selector__month-heading {
	padding: 10px 0 4px;
	font-family: var( --ld-font-inter );
	font-weight: var( --ld-display-2-weight );
	font-size: var( --ld-display-2-size );
	line-height: var( --ld-display-2-line-height );
}

.ld-occurrence-row__title {
	font-weight: 700;
	font-size: 16px;
}

.ld-occurrence-row .ld-btn {
	justify-self: start;
}

@media ( min-width: 900px ) {
	/* Shared filter/result column grid: the toolbar and every result row
	 * use the same grid-template-columns — one definition, not two
	 * independently spaced layouts — so each filter lines up as the header
	 * of its result column. The title still spans the full row width,
	 * forcing every other field onto its own row via normal grid
	 * auto-placement. Five equal `1fr` columns; the last sizes to its own
	 * content (Reset / each row's Select action). */
	.ld-occurrence-selector__filters,
	.ld-occurrence-row {
		display: grid;
		grid-template-columns: 1fr 1fr 1fr 1fr 1fr fit-content( 100% );
		align-items: baseline;
		gap: 6px 20px;
	}

	/* Shares this vertical padding with Reset/Apply's own box, so combined
	 * with .ld-occurrence-filter's `padding-bottom: 15px` above, every
	 * popover's `top: 100%` anchor is consistent regardless of which
	 * filter is open. */
	.ld-occurrence-filter__date-summary,
	.ld-occurrence-filter--location > summary,
	.ld-occurrence-filter--select > summary {
		padding-block: 7px;
	}

	.ld-occurrence-row__title {
		grid-column: 1 / -1;
	}

	.ld-occurrence-row .ld-btn {
		justify-self: end;
	}
}

/* Compact filter interface (Figma node 208:714): below the shared
 * --ld-bp-desktop breakpoint (900px). Full-width stacked filter rows with
 * 2px separators, each popover expanding inline in normal flow instead of
 * an anchored overlay, plus a Filters/Apply control set visible only
 * here. The interface's draft-state is read/written purely through
 * attributes ([data-ld-draft-open], [hidden]) by category-selector.js —
 * nothing here needs to know about that state directly.
 *
 * Desktop-only values (per-panel width/min-width modifiers, the
 * toolbar's wide-mode `justify-content: space-between`) each get an
 * explicit reset below rather than relying on source order alone. */
@media ( max-width: 899px ) {
	.ld-occurrence-selector__filters-toggle {
		display: inline-flex;
	}

	.ld-occurrence-selector__filters {
		display: flex;
		flex-direction: column;
		align-items: stretch;
		/* Resets the wide-mode toolbar's own `justify-content:
		 * space-between` (declared unconditionally above): with
		 * `flex-direction: column` here, that value would distribute rows
		 * across any leftover vertical space rather than stacking them
		 * immediately beneath one another. */
		justify-content: flex-start;
		gap: 0;
	}

	.ld-occurrence-filter {
		width: 100%;
		justify-content: space-between;
		padding: 14px 0;
		border-bottom: 2px solid var( --ld-color-black );
	}

	/* The shared `.ld-occurrence-filter` base's row-direction flex (above)
	 * is correct for the wide-mode single-line trigger, but here it would
	 * lay popover content beside the trigger rather than stacked beneath
	 * it. Column direction lets the popover's `width: auto`/`min-width: 0`
	 * reset below stretch to the full row width. Scoped to the three
	 * disclosure-based filters only — not `--toggle` (the weekly-classes
	 * checkbox row has no disclosure content and keeps the shared layout). */
	.ld-occurrence-filter--date,
	.ld-occurrence-filter--location,
	.ld-occurrence-filter--select {
		flex-direction: column;
		align-items: stretch;
		justify-content: flex-start;
	}

	.ld-occurrence-filter--date > summary,
	.ld-occurrence-filter--location > summary,
	.ld-occurrence-filter--select > summary {
		width: 100%;
		justify-content: space-between;
	}

	/* Overrides the shared .ld-occurrence-filter__popover-panel's absolute
	 * positioning so filters expand inline beneath their own trigger row
	 * instead of floating over the results panel. Border/background/
	 * padding are reset to none — compact-mode structure comes from the
	 * existing divider lines between filter rows instead. */
	.ld-occurrence-filter__popover-panel {
		position: static;
		width: auto;
		min-width: 0;
		margin-top: 8px;
		border: 0;
		background: none;
		padding: 0;
	}

	/* Each panel's own desktop-only width/min-width modifier, explicitly
	 * reset rather than left to the shared rule above winning by source
	 * order alone. */
	.ld-occurrence-filter__date-panel,
	.ld-occurrence-filter__location-panel,
	.ld-occurrence-filter__select-panel {
		width: auto;
		min-width: 0;
		box-shadow: none;
	}

	.ld-occurrence-selector__filter-actions {
		width: 100%;
		justify-content: flex-end;
		margin-left: 0;
		padding-top: 15px;
	}

	.ld-occurrence-selector__apply {
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}
}

/* The Event type / section-identity area (docs/product-spec.md §4.3.2):
 * the section-identity marker sits here, beside Event type — never as a
 * leading bullet before the title. */
.ld-occurrence-row__event-type-area {
	display: inline-flex;
	align-items: center;
	gap: 8px;
}

/* The section-identity marker (docs/technical-spec.md §3.2): consumes the
 * shared --ld-section-color custom property inherited from <body>, the same
 * mechanism the card marker (.ld-category-card__marker above) uses — never
 * a colour hardcoded per page/section. */
.ld-occurrence-row__marker {
	display: inline-block;
	flex-shrink: 0;
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: var( --ld-section-color, var( --ld-color-peach ) );
}

/* `:focus` clears the browser default outline; `:focus-visible` restores
 * one only for keyboard/assistive-technology focus, not a mouse click —
 * covering every interactive element in this component. The calendar
 * day/nav cells and card CTA already carry their own more specific
 * :focus-visible treatment and are unaffected by this lower-specificity
 * rule. */
.ld-occurrence-selector a:focus,
.ld-occurrence-selector button:focus,
.ld-occurrence-selector summary:focus,
.ld-occurrence-selector input:focus {
	outline: none;
}

.ld-occurrence-selector a:focus-visible,
.ld-occurrence-selector button:focus-visible,
.ld-occurrence-selector summary:focus-visible,
.ld-occurrence-selector input:focus-visible {
	outline: 2px solid var( --ld-color-black );
	outline-offset: 2px;
}

/* Admin-entered supporting page content (docs/product-spec.md §4) -------- */

/* Typography only, for whatever admin-entered content the_content()
 * outputs. The "Today" highlighted-event panel Figma node 142:4974 shows
 * beside this copy is a distinct, out-of-scope feature not built here. */
.ld-category-content {
	max-width: 1400px;
	margin-inline: auto;
	padding: 40px 20px 0;
	background: var( --ld-color-white );
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.6;
}

/* 760px is an interim reading-column estimate, not a value confirmed
 * against current Figma design context — pending Figma verification. */
.ld-category-content > * {
	max-width: 760px;
}

.ld-category-content :is( h1, h2, h3 ) {
	margin: 0 0 20px;
	font-weight: var( --ld-display-2-weight );
	font-size: var( --ld-display-2-size );
	line-height: var( --ld-display-2-line-height );
}

/* Sub-category / Class cards ---------------------------------------------- */

.ld-category-cards {
	max-width: 1400px;
	margin-inline: auto;
	padding: 20px 20px 10px;
	background: var( --ld-color-white );
	display: grid;
	grid-template-columns: 1fr;
	gap: 30px;
}

@media ( min-width: 900px ) {
	.ld-category-cards {
		grid-template-columns: repeat( 3, 1fr );
		gap: 10px;
	}
}

.ld-category-card {
	display: flex;
	flex-direction: column;
	/* Containing block for .ld-category-card__cta's stretched ::after below
	 * (docs/product-spec.md §4.2 whole-card interaction) — this is the only
	 * reason this rule is positioned; it does not otherwise affect layout. */
	position: relative;
}

.ld-category-card__image {
	display: block;
}

.ld-category-card__image img {
	display: block;
	width: 100%;
	aspect-ratio: 460 / 354;
	object-fit: cover;
}

.ld-category-card__body {
	padding: 20px 20px 20px 0;
	display: flex;
	flex-direction: column;
	flex: 1;
}

.ld-category-card__title {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 12px;
	font-family: var( --ld-font-inter );
	font-weight: 700;
	font-size: 24px;
	line-height: 1.4;
	text-transform: uppercase;
	color: var( --ld-color-black );
}

.ld-category-card__marker {
	display: inline-block;
	flex-shrink: 0;
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: var( --ld-section-color, var( --ld-color-peach ) );
}

.ld-category-card__description {
	margin: 0 0 16px;
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.6;
	flex-grow: 1;
}

.ld-category-card__next {
	margin: 0 0 16px;
	font-family: var( --ld-font-inter );
	font-weight: 600;
	font-size: 14px;
	line-height: 1.5;
}

.ld-category-card__next-label {
	font-weight: 700;
	margin-right: 6px;
}

.ld-category-card__body .ld-btn {
	align-self: flex-start;
}

/* The visible `explore` CTA is the card's only interactive element; its
 * hit area is stretched to cover the full card ("stretched link"
 * technique, against .ld-category-card's `position: relative` above)
 * rather than wrapping the card in a second interactive element, which
 * would nest interactive controls. */
.ld-category-card__cta::after {
	content: "";
	position: absolute;
	inset: 0;
}
