/*
 * Event Calendar month view — layout only (Phase 4C, Decision 026;
 * rewritten Increment 5A, v0.2.25 development cycle, approved
 * supersession of the original <table>-based DOM — see
 * templates/event-calendar.php's own docblock for the accessibility
 * reasoning). Deliberately isolated from frontend-event-card.css: a
 * month grid is a genuinely different presentation shape, not a
 * variant of the Event Card. Registered with frontend-event-card.css as
 * a dependency (Frontend\CalendarRenderer::register_assets()) purely so
 * this file can rely on its :root design tokens (fonts, colors, CTA and
 * status badge tokens) via var() with a hard fallback in every case —
 * no atomic Event Card class is reused or redefined here.
 *
 * CSS Grid replaces the previous <table>: a plain 7-column grid for the
 * weekday header, a second 7-column grid for the day cells — the exact
 * same technique templates/event-index.php's own week-grid already
 * uses. Each day cell keeps its own full border (all four sides, a
 * genuine visual-direction change from the immediately preceding
 * styling pass, superseded here per the newly approved
 * events-calendar_v2.html reference) with a real grid gap between
 * cells, rather than a border-collapse technique — the simpler,
 * more directly Elementor-control-friendly choice (a future "Line/
 * Border Color" control, Increment 5C, can target one obvious
 * `border-color` property on one selector).
 *
 * Single breakpoint, deliberately preserved from the original design
 * (700px): above it, a 7-column grid; below it, the grid collapses to a
 * single column — achieved with far less CSS than the old table-flip
 * technique required (only grid-template-columns changes; nothing needs
 * display:block added element-by-element). No horizontal-scroll mobile
 * workaround — deliberately not adopted from the reference HTML's own
 * prototype, which was explicitly rejected. No JavaScript. No
 * !important anywhere.
 *
 * Increment 5E (v0.2.25 development cycle): below 700px, empty and
 * outside-month day cells are hidden entirely (see the @media(max-width:
 * 700px) block's own comments below) rather than each rendering as its
 * own full-width stacked block — the previous mobile behavior was
 * functionally responsive but produced a long scroll of mostly-empty day
 * cards. What remains visible is a compact chronological agenda of only
 * the in-month days that actually have an event, over the exact same
 * DOM/data the desktop grid already renders — no second component, no
 * JS, no new query, no template change.
 *
 * No max-width on .jdx-events-calendar (unchanged design decision,
 * reaffirmed): the Elementor/page parent container owns the editorial
 * content width, this component does not recreate one.
 */

.jdx-events-calendar {
	width: 100%;
	box-sizing: border-box;
	font-family: var(--jdx-events-font-secondary, inherit);
	color: var(--jdx-events-color-text, inherit);
}

.jdx-events-calendar__sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.jdx-events-calendar__nav {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1em;
	margin-bottom: 1em;
}

/* Boxed-control language already established for the Event Index filter
 * row and this component's own Prev/Next (Increment 4A/4B and the prior
 * Calendar styling pass) — unchanged here, still correct under the new
 * grid below. */
.jdx-events-calendar__prev,
.jdx-events-calendar__next {
	display: inline-flex;
	align-items: center;
	gap: 0.35em;
	min-height: 44px;
	padding: 0.5em 1em;
	color: inherit;
	text-decoration: none;
	background: transparent;
	border: 1px solid var(--jdx-events-card-border-color, #4a4a4a);
	border-radius: 0;
	font-size: 0.8em;
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

@media ( hover: hover ) {
	.jdx-events-calendar__prev:hover,
	.jdx-events-calendar__next:hover {
		background: var(--jdx-events-color-accent, currentColor);
		color: var(--jdx-events-cta-primary-fg, #ffffff);
		border-color: var(--jdx-events-color-accent, currentColor);
		text-decoration: none;
	}
}

.jdx-events-calendar__prev:focus-visible,
.jdx-events-calendar__next:focus-visible {
	position: relative;
	z-index: 1;
	box-shadow: 0 0 0 3px var(--jdx-events-focus-ring-shadow, #ffffff);
	outline: 2px solid var(--jdx-events-focus-ring-outline, #1a1a1a);
	outline-offset: 3px;
}

.jdx-events-calendar__heading {
	font-family: var(--jdx-events-font-primary, inherit);
	font-size: 1.3em;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	margin: 0;
	text-align: center;
	flex: 1 1 auto;
}

/* minmax(0, 1fr), not a bare 1fr (Correction 4, live stress-test
 * defect): CSS Grid's implicit track-sizing minimum is `auto` (roughly,
 * the widest unbreakable content inside that track), not 0 — a bare
 * `1fr` track can still be forced wider than its fair share by a long
 * unbroken string inside it ("grid blowout"). minmax(0, 1fr) caps the
 * minimum at 0, so the track can never grow past its own 1/7th share
 * regardless of content; the paired .jdx-events-calendar__day min-width:0
 * below and the overflow-wrap rules on title/description are the other
 * two pieces of this same defense — together they make the seven-column
 * grid geometry stable regardless of content, with no query/data change
 * and no truncation of stored data (Support\EventQuery and
 * Support\CalendarGrid are both untouched). Kept in sync with
 * .jdx-events-calendar__grid below (the header and body are two
 * separate grids that must stay column-aligned). */
.jdx-events-calendar__grid-head {
	display: grid;
	grid-template-columns: repeat( 7, minmax( 0, 1fr ) );
	margin-bottom: 0.5em;
	padding-bottom: 0.5em;
	border-bottom: 1px solid var(--jdx-events-card-border-color, #4a4a4a);
}

.jdx-events-calendar__weekday {
	font-size: 0.7em;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--jdx-events-color-text, inherit);
	padding: 0 0.5em;
}

.jdx-events-calendar__weekday abbr {
	text-decoration: none;
}

/* minmax(0, 1fr) — see .jdx-events-calendar__grid-head's own comment
 * above for the full grid-blowout rationale; this is the paired body
 * grid that must stay column-aligned with it. */
.jdx-events-calendar__grid {
	display: grid;
	grid-template-columns: repeat( 7, minmax( 0, 1fr ) );
	gap: 0.6em;
}

/* height, not min-height (validation.32 Correction — Defect 2): live
 * validation on validation.31's "let the row grow naturally" strategy
 * showed exactly the rejected outcome — a single tall Extra Event tile
 * pulled its ENTIRE Calendar week row substantially taller, since CSS
 * Grid's default row-sizing sizes a row to its tallest item and
 * min-height only ever set a FLOOR, never a ceiling. A fixed height
 * removes row size from content entirely: every day cell in every row
 * requests the exact same height, so every row settles to that one
 * value regardless of which days have 0, 1, or several events — this is
 * the "controlled, consistent" desktop model the correction calls for
 * (a deliberate, width-independent em constant, not aspect-ratio, which
 * validation.30 already showed goes uncomfortably small on some column
 * widths). overflow:hidden is the other half: it guarantees no content
 * can ever visibly spill past this fixed box (Requirement 7) without
 * resorting to the internal-scrollbar strategy validation.31 already
 * rejected — Extra Event's own internal reservations (rooms/description/
 * status, further trimmed below) are sized to fit comfortably inside
 * this height in normal use, so clipping is a safety net, not the normal
 * case. Empty days and Standard-only days get the exact same fixed
 * height (Requirement: "empty days retain the same controlled height"),
 * satisfying that requirement with zero extra CSS — there is only ever
 * one height rule now, not a conditional one.
 * Scoped to desktop only (min-width:701px, immediately above the
 * existing mobile agenda breakpoint) — the mobile agenda's own rules
 * below fully reset height/overflow back to content-driven, matching
 * the explicit instruction not to force fixed calendar squares onto the
 * mobile agenda. Background stays transparent by default (see this
 * file's own header comment). */
/* min-width:0 (Correction 4): a CSS Grid item's implicit min-width is
 * `auto` by default, which — independent of the minmax(0, 1fr) track
 * fix above — can itself still force this cell wider than its track
 * when it contains unbreakable content. Both fixes are needed together;
 * neither alone is sufficient in every browser/content combination. */
.jdx-events-calendar__day {
	position: relative;
	display: flex;
	flex-direction: column;
	min-width: 0;
	padding: 0;
	border: 1px solid var(--jdx-events-card-border-color, #4a4a4a);
	background: transparent;
}

@media ( min-width: 701px ) {
	.jdx-events-calendar__day {
		height: 16em;
		overflow: hidden;
	}
}

.jdx-events-calendar__day--outside {
	opacity: 0.4;
}

/* Deterministic, not a semi-transparent tint (same reasoning as the
 * prior styling pass): --jdx-events-color-accent can resolve to the
 * literal value `currentColor` when Elementor is inactive/unconfigured,
 * which cannot be safely decomposed into a partial-opacity overlay in
 * plain CSS — a solid inset ring plus an accent-colored date number
 * stay deterministic regardless of what the token resolves to. */
.jdx-events-calendar__day--today {
	box-shadow: inset 0 0 0 1px var(--jdx-events-color-accent, currentColor);
	border-color: var(--jdx-events-color-accent, currentColor);
}

.jdx-events-calendar__day--today .jdx-events-calendar__date {
	color: var(--jdx-events-color-accent, currentColor);
}

/* Screen-reader-only at every width now (previously display:none above
 * the mobile breakpoint) — dropping the <table> also drops the
 * <thead>/<td> header-association a sighted-only visual column gave for
 * free; every day cell now carries its own accessible weekday label
 * regardless of viewport. Restored to a plain visible inline label at
 * the existing mobile breakpoint below, matching the prior, already-
 * proven stacked-mobile treatment exactly. */
.jdx-events-calendar__day-label {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* position:absolute + z-index (validation.32 Correction — Defect 2, Day
 * Number Overlay requirement): the day number now OVERLAYS the event
 * surface instead of taking its own document-flow row above it — the
 * explicit new requirement is that Standard/Extra event backgrounds
 * fill the COMPLETE day-cell event area, with the number floating
 * legibly above whatever is beneath it (empty background, a Standard
 * event's flat color, or an Extra event's photo). .jdx-events-calendar__day's
 * own position:relative (above) is this element's positioning context.
 * z-index:2 only needs to beat the normal (auto/0) stacking of
 * .jdx-events-calendar__events below it — every .jdx-events-calendar__event
 * article has its own isolation:isolate, which contains any of ITS OWN
 * internal negative-z-index overlay tricks inside that one article, so
 * they can never compete with this z-index at the day-cell level.
 * pointer-events:none keeps the number purely decorative — it was
 * always a plain <time>, never interactive, and must not intercept
 * clicks meant for the event/CTAs now visually beneath it. Desktop-only
 * (min-width:701px, paired with .jdx-events-calendar__day's own
 * breakpoint above) — the mobile agenda rules further below fully
 * restore normal in-flow, non-overlaid placement. */
.jdx-events-calendar__date {
	display: block;
	font-family: var(--jdx-events-font-primary, inherit);
	font-size: 0.85em;
	font-weight: 600;
	margin: 0;
}

@media ( min-width: 701px ) {
	.jdx-events-calendar__date {
		position: absolute;
		top: 0.5em;
		left: 0.6em;
		z-index: 2;
		pointer-events: none;
	}
}

/* flex:1 1 auto (validation.31 Correction — Tasks 3/5, height:100% added
 * in validation.32): lets this area consume the day cell's available
 * height. Since the day number is now an absolute overlay (above) rather
 * than an in-flow sibling, this is the ONLY in-flow child of the day
 * cell at desktop width, so height:100% makes it (and, by the same
 * flex:1 1 auto on .jdx-events-calendar__event below) fill the entire
 * now-fixed-height cell — this, together with .jdx-events-calendar__day's
 * own fixed height above, is what makes a Standard event's own
 * background genuinely fill the available day-cell area instead of
 * collapsing to its content height. No overflow-y here (validation.30's
 * internal-scrollbar strategy stays removed) — the day cell's own
 * overflow:hidden (above) is the only overflow safeguard needed. */
.jdx-events-calendar__events {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	gap: 0.5em;
	min-width: 0;
}

@media ( min-width: 701px ) {
	.jdx-events-calendar__events {
		height: 100%;
	}
}

/* position:relative added for the Extra Event logo overlay below
 * (Extra Events / Cross-Promotion Mode) — inert on its own, no visual
 * change for a Standard Event, which never gets an absolutely-positioned
 * child to position against. */
/* width:100%/box-sizing:border-box (Correction 3, live stress-test
 * defect — a branded Extra Event tile rendered narrower than the
 * available cell width on wide desktop cells). min-width:0 (Correction
 * 4): flex items default to min-width:auto (content-based), which can
 * force this article wider than its flex container regardless of the
 * width:100% above — the same "blowout" mechanism as CSS Grid tracks,
 * just at the flex level; both min-width:0 here and on
 * .jdx-events-calendar__day above are needed, one per container type.
 * Neither property changes anything for a Standard Event's own tile —
 * it was already effectively full-width via the parent's default
 * align-items:stretch, so this is a no-op there. */
/* General per-event presentation (validation.30 Correction 3):
 * color/background-color/isolation used to live on .jdx-events-calendar__event--extra
 * only, which meant a Standard Event's own configured Background
 * Color/Text Color could never actually render — the confirmed root
 * cause of that defect. These are GENERAL fields (Final Sakura Event
 * Presentation Alignment) and now apply to every event tile regardless
 * of Extra/Standard; every custom property below has a fallback to
 * today's existing unbranded presentation, so an event with nothing
 * configured renders identically to before. isolation:isolate gives
 * every tile its own stacking context (needed by the overlay div's
 * z-index:-1 trick below whenever a background image is configured);
 * harmless when no image is set, since nothing here needs to stack
 * against page content outside the tile.
 *
 * flex:1 1 auto + width:100% (validation.31 Correction — Tasks 3/5,
 * replacing the removed negative-margin/padding-inline compensation
 * trick): the actual DOM relationship now does this work instead of an
 * arbitrary offset — .jdx-events-calendar__day carries no padding of
 * its own any more (see that rule above) and this article is a direct,
 * un-padded flex child of .jdx-events-calendar__events (also
 * flex:1 1 auto), so its own background/image/overlay paints the
 * complete available event area edge-to-edge by construction.
 * validation.32: the day cell's height is now a fixed constant (see
 * .jdx-events-calendar__day above), not content-driven — for a
 * single-event day this article fills that entire fixed height (both
 * flex:1 1 auto parent and child, plus .jdx-events-calendar__events'
 * own height:100%), which is what makes a short Standard event's
 * background fill the cell instead of collapsing to its content height,
 * WITHOUT that content also being able to pull the row taller (the
 * validation.31 defect this correction fixes — see .jdx-events-calendar__day's
 * own comment). For a multi-event day every article shares that same
 * flex:1 1 auto, so several short events still divide the available
 * height evenly rather than each shrinking to bare content size. padding
 * (own property now, not borrowed from the day cell) keeps text/CTA
 * content clear of this article's own edges — exactly the "content sits
 * inside with controlled padding" requirement. */
.jdx-events-calendar__event {
	position: relative;
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	gap: 0.25em;
	width: 100%;
	box-sizing: border-box;
	min-width: 0;
	max-width: 100%;
	padding: 0.6em 0.7em;
	color: var(--jdx-events-calendar-extra-text, inherit);
	background-color: var(--jdx-events-calendar-extra-bg-color, transparent);
	isolation: isolate;
	/* Event → Single Event navigation UX (validation.40 Part 2): the
	 * stretched title link's hover response (below) changes this same
	 * border-color, so it needs to transition here too. */
	transition: border-color 175ms;
}

/* Extra top clearance for the overlaid day number (validation.32, Day
 * Number Overlay requirement): only the FIRST stacked event in a day
 * sits directly beneath the number (.jdx-events-calendar__events is the
 * only in-flow child of the day cell now, and .jdx-events-calendar__date
 * is positioned on top of it — see those rules above); any 2nd/3rd
 * event in a multi-event day already starts further down, well clear of
 * it. 2em leaves a small buffer below the number (which sits at
 * top:0.5em, ~1.2em tall at its own font-size) before this article's own
 * title/date-line content begins. Desktop-only, paired with the
 * overlay's own breakpoint above — the mobile agenda (below) resets this
 * back to the normal 0.6em every event already uses, since the number is
 * never overlaid there. */
@media ( min-width: 701px ) {
	.jdx-events-calendar__event:first-child {
		padding-top: 2em;
	}
}

/* Extra Event promotional tile modifier (Extra Events / Cross-Promotion
 * Mode). No longer carries its own color/background-color/padding/
 * isolation rule (validation.30 Correction 3 moved those to the general
 * .jdx-events-calendar__event selector above, since they are general
 * fields, not Extra-only) — this class is now purely a marker: it still
 * gates the richer promotional tile composition (Logo, Rooms, head-row,
 * compact Description, statusrow; see templates/event-calendar-grid.php)
 * and remains available for CSS/debugging/future-rule targeting. */

/* Background image (Final Sakura Event Presentation Alignment) — the
 * article's own background, painted first/most-behind by definition (a
 * plain CSS background, not a positioned layer). Only applies with its
 * own separate modifier (added by the template only when an image is
 * actually configured) — an Extra Event with no image never receives
 * this rule. */
.jdx-events-calendar__event--extra-bg {
	background-image: var( --jdx-events-calendar-extra-bg-image, none );
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
}

/* Configurable overlay tint (Final Sakura Event Presentation Alignment)
 * — supersedes the previous hardcoded rgba(0,0,0,.55) scrim; matches
 * calendar-extra-event-tile.html's own .cet__overlay technique exactly:
 * a dedicated element with its own background-color and opacity,
 * rather than color-mix()-ing a color and an opacity into one gradient
 * stop — opacity is a plain 0-1 number here (Fields\EventFields::
 * sanitize_opacity()'s own stored format), which the CSS `opacity`
 * property accepts natively; color-mix()'s percentage argument would
 * have needed a second, redundant unit conversion for no benefit.
 * z-index:-1 relies on .jdx-events-calendar__event--extra's own
 * isolation:isolate (above) to scope stacking locally to this one
 * tile: a negative z-index child paints behind the stacking-context
 * root's own background (the image above) is wrong — negative z-index
 * children paint AFTER the root's own background/border but BEFORE
 * the root's in-flow non-positioned content (title, description, etc.)
 * per CSS2.1 §Appendix E — exactly the back-to-front order needed:
 * photo, then tint, then text. Fallback color/opacity (#0a0806 / .55)
 * reproduce the exact previous hardcoded scrim when neither is
 * configured. */
.jdx-events-calendar__event--extra-bg .jdx-events-calendar__event-overlay {
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background-color: var( --jdx-events-calendar-extra-overlay-color, #0a0806 );
	opacity: var( --jdx-events-calendar-extra-overlay-opacity, 0.55 );
}

/* head row: JDX: Title (left) + JDX: Event Logo (right), same row —
 * replaces the previous free-floating absolute top-right logo overlay. */
.jdx-events-calendar__event-head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 0.5em;
	min-width: 0;
}

/* Event-specific logo (Extra Events / Cross-Promotion Mode) — Extra
 * Events only; Standard Events never show a logo in Calendar and have no
 * reserved space for one either (templates/event-calendar-grid.php only
 * ever renders this element when $event['is_extra_event'] is true). An
 * in-flow flex child of .jdx-events-calendar__event-head, not an
 * absolute overlay — it sits beside the Title instead of floating over
 * it. Subtle, subordinate, never interactive — same non-clickable
 * pointer-events:none convention as every other JDX logo watermark. */
.jdx-events-calendar__event-logo {
	flex: 0 0 auto;
	max-width: 40%;
	max-height: 32px;
	width: auto;
	height: auto;
	display: block;
	pointer-events: none;
	opacity: 0.95;
}

.jdx-events-calendar__event-logo img {
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;
	object-position: right center;
	display: block;
}

/* JDX: Start Date — shared by Standard and Extra alike. Renders
 * $event['calendar_start_date'] (Frontend\EventCardPresenter — a plain
 * DD.MM.YYYY start date computed specifically for this Calendar view;
 * no weekday, no time, no end-date range). max-width:70% keeps a normal
 * date from ever being truncated while still leaving room for the day
 * number on the opposite side at narrow column widths.
 *
 * position:absolute (desktop only, below): shares the day cell's own
 * day-number top row by mirroring its offset on the opposite side
 * (.jdx-events-calendar__date sits at top:0.5em; left:0.6em — see that
 * rule) — .jdx-events-calendar__event's own position:relative is this
 * element's positioning context, which coincides with the day cell
 * itself for the first/only event in a day. Taking this out of normal
 * flow also frees the vertical space it would otherwise occupy, into
 * Description below. Desktop-only (min-width:701px, matching the
 * day-number overlay's own breakpoint) — the mobile agenda rules further
 * below restore normal in-flow placement, since the day number is never
 * overlaid there either. */
.jdx-events-calendar__event-date {
	margin: 0;
	text-align: right;
	font-size: 0.8em;
	letter-spacing: 0.02em;
	color: var(--jdx-events-color-accent, inherit);
	min-width: 0;
	max-width: 70%;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

@media ( min-width: 701px ) {
	.jdx-events-calendar__event-date {
		position: absolute;
		top: 0.5em;
		right: 0.7em;
		z-index: 1;
	}
}

/* JDX: Rooms — shared by Standard and Extra alike: Standard shows only
 * its first configured room, Extra shows all
 * (templates/event-calendar-grid.php's own $calendar_rooms handles that
 * count difference; this rule is identical either way). Single-line
 * lineup with ellipsis, not wrapping — matches the reference's own
 * nowrap/ellipsis treatment for this component specifically (unlike
 * Event Grid/Event Index, where Rooms may wrap). max-height:2 rows keeps
 * an event with many configured Rooms from pushing this tile's content
 * past the fixed cell height on its own — overflow:hidden clips any
 * 3rd+ room row rather than growing past it; a presentation-only clamp,
 * $event['rooms'] itself is untouched and still renders in full
 * everywhere else (Event Grid, Event Index, Single Event). */
.jdx-events-calendar__event-rooms {
	margin-top: 0.45em;
	display: flex;
	flex-direction: column;
	gap: 0.3em;
	min-width: 0;
	max-height: calc( 1em * 1.3 * 2 );
	overflow: hidden;
}

.jdx-events-calendar__event-room {
	display: flex;
	align-items: center;
	gap: 0.5em;
	min-width: 0;
}

/* Per-event > Elementor widget setting > JDX global setting > existing
 * fallback (Increment 4, v0.2.31) — same four-tier model as the CTA
 * colors above; see DECISIONS.md's Increment 4 entry. No Elementor
 * widget registers a Room Label Style control for Calendar, so the
 * widget tier here is always empty and a no-op fallthrough, exactly
 * the same relationship the CTA tokens already have to Calendar. */
.jdx-events-calendar__event-tag {
	flex: 0 0 auto;
	background: var(--jdx-events-calendar-extra-room-badge-bg, var(--jdx-events-room-badge-bg-widget, var(--jdx-events-room-badge-bg, #c9a227)));
	color: var(--jdx-events-calendar-extra-room-badge-fg, var(--jdx-events-room-badge-fg-widget, var(--jdx-events-room-badge-text, #1a1a1a)));
	font-size: 0.68em;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	padding: 0.35em 0.6em;
	white-space: nowrap;
}

.jdx-events-calendar__event-lineup {
	font-size: 0.75em;
	min-width: 0;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* JDX: Description — FIXED reserved zone, shared by Standard and Extra
 * alike (both render this exact class combination; see the bare
 * .jdx-events-calendar__event-description rule's own comment above for
 * why its layout declarations were removed rather than kept alongside
 * this one). Replaces the space Pricing previously occupied here
 * (Pricing is not rendered in this tile at all, see
 * templates/event-calendar-grid.php). --jdx-events-calendar-extra-desc-lines
 * (default 3) lets a theme tune the reserved line count without a
 * template change — raise it (here or via a future Elementor control) if
 * live validation shows more room is consistently available within the
 * fixed cell height (16em, see .jdx-events-calendar__day above). */
.jdx-events-calendar__event-description--extra {
	margin-top: 0.6em;
	font-size: 0.85em;
	line-height: 1.5;
	min-width: 0;
	overflow-wrap: anywhere;
	word-break: break-word;
	height: calc( 1em * 1.5 * var( --jdx-events-calendar-extra-desc-lines, 3 ) );
	display: -webkit-box;
	-webkit-line-clamp: var(--jdx-events-calendar-extra-desc-lines, 3);
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* validation.36: Extra Event's full content stack (head-row + Rooms +
 * 3-line Description + spacer + statusrow + CTA) totals more than the
 * available budget inside the fixed 16em cell, live-validated as the
 * CTA row sitting too low / partially outside the frame — Description's
 * 3-line reservation (shared with Standard above) is the single largest
 * reducible contributor. This overrides the custom property only when
 * nested inside an Extra-marked article (.jdx-events-calendar__event--extra),
 * without touching the shared rule's own default above — Standard's
 * article never carries that class, so its approved 3-line Description
 * is completely unaffected. */
.jdx-events-calendar__event--extra .jdx-events-calendar__event-description--extra {
	--jdx-events-calendar-extra-desc-lines: 2;
}

/* Pushes the Status row + CTA row to the bottom of the tile — same
 * flex-spacer technique Event Grid's own .jdx-events-card-pricing
 * margin-top:auto already uses, expressed here as an explicit spacer
 * element (matching the reference's own .cet__spacer) since Description
 * sits directly above it rather than a margin-top:auto candidate. Only
 * ever a floor; it still flex-grows to consume any real remaining space
 * above the Status/CTA rows. */
.jdx-events-calendar__event-spacer {
	flex: 1 1 auto;
	min-height: 0.5em;
}

/* JDX: Status — reserved-height row directly above the CTA row, shared
 * by Standard and Extra alike (both render this same .event-statusrow
 * wrapper unconditionally): present or not, this row is at least the
 * same height, so the CTA row's vertical position never shifts between
 * an event with a status and one without — same principle as Event
 * Grid/Event Index's own reserved Description/Pricing zones, applied
 * here to Status instead. Business logic is unchanged:
 * templates/event-calendar-grid.php still computes
 * $status_modifier/$sold_out exactly as before; multiple badges
 * (Cancelled/Postponed AND Sold Out) still group together unchanged
 * inside the same .jdx-events-calendar__event-status paragraph.
 *
 * height → min-height (Increment 2, v0.2.31, review correction): a hard
 * `height` clipped the row whenever the two filled badges (Cancelled +
 * Sold Out together) wrapped onto two lines in a narrow/mobile cell —
 * measured overflow of ~15px, clipping both above and below the fixed
 * box. min-height keeps every already-working case pixel-identical
 * (single badge or no status already fits inside 1.6em with room to
 * spare) and only grows the row in the rare combined-badges-wrapped
 * case, instead of silently clipping it. */
.jdx-events-calendar__event-statusrow {
	min-height: 1.6em;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	margin-bottom: 0.45em;
	min-width: 0;
}

/* overflow-wrap/word-break/max-width (Correction 4): a long unbroken
 * event title (or an admin-entered URL-like string with no natural
 * break point) can force this element — and therefore its ancestor
 * flex/grid containers — wider than the available column without this.
 * word-break:break-word is a secondary fallback alongside
 * overflow-wrap:anywhere (some older engines honor one but not the
 * other); together they only ever affect a genuinely unbreakable run of
 * characters, never ordinary wrapping text. Visual-only — the title
 * string itself is never truncated or altered server-side. */
/* font-size 0.85em → 1.05em (validation.34 — live validation: "title
 * reads like minor metadata... needs noticeably stronger hierarchy"):
 * a deliberate, modest increase within Calendar's own compact scale —
 * clearly larger than Date/Time/Status/Description, still nowhere near
 * Event Index's own 1.4em title (a different, larger component; not the
 * target here). */
.jdx-events-calendar__event-title {
	font-family: var(--jdx-events-font-primary, inherit);
	font-size: 1.05em;
	font-weight: 700;
	line-height: 1.2;
	margin: 0;
	max-width: 100%;
	overflow-wrap: anywhere;
	word-break: break-word;
	/* 2-line clamp (validation.32 Correction — Defect 2/Task 6): a
	 * safety ceiling for both Standard and Extra (this class is shared),
	 * so a genuinely long title can never by itself consume an
	 * unbounded share of the new fixed-height day cell. Previously
	 * unclamped and relying only on natural wrap — harmless for the
	 * common 1-line case, this only ever engages for unusually long
	 * titles. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* flex/min-width, scoped to the Extra tile's own .jdx-events-calendar__event-head
 * ROW context only (validation.34 Correction — confirmed root cause of
 * "Standard content pushed to the bottom"): these two properties used to
 * live on the bare .jdx-events-calendar__event-title rule above, with a
 * comment claiming they were "harmless no-ops" for a Standard entry's
 * plain in-flow <h3> — that was wrong. Standard's <h3> is a DIRECT flex
 * child of .jdx-events-calendar__event (a column-direction flex
 * container), so flex:1 1 auto there made the TITLE ELEMENT ITSELF grow
 * to fill all remaining vertical space in the fixed-height article,
 * silently pushing Description/CTA down to wherever that invisibly
 * inflated title box ended — exactly the live-reported "title near top,
 * huge gap, description/CTA near bottom" symptom, not a margin or
 * spacer issue. Scoping this to only the Extra tile's own horizontal
 * .event-head row (where flex:1 1 auto correctly lets the title claim
 * remaining ROW width beside the Logo, and min-width:0 lets it shrink
 * below its own text width when the Logo needs room) fixes Standard
 * without touching Extra's head-row layout at all. */
.jdx-events-calendar__event-head .jdx-events-calendar__event-title {
	min-width: 0;
	flex: 1 1 auto;
}

.jdx-events-calendar__event-title a {
	color: inherit;
	text-decoration: none;
	transition: color 175ms;
}

/* Event → Single Event navigation UX (validation.40 Part 2): same
 * technique as Event Grid/Event Index's own stretched title link — the
 * title is the event's real permalink anchor; Details
 * (.jdx-events-calendar__event-details, below) is that same permalink
 * relabeled as a CTA, not a second distinct destination. .jdx-events-calendar__event
 * (position:relative, above) is the nearest positioned ancestor, so
 * inset:0 covers the whole tile. z-index:1 stays below the CTA row,
 * which claims z-index:2 (see .jdx-events-calendar__event-cta below) so
 * Details/Buy Tickets remain independently clickable on top of it. */
.jdx-events-calendar__event-title a::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	cursor: pointer;
}

.jdx-events-calendar__event-title a:focus-visible {
	position: relative;
	z-index: 1;
	box-shadow: 0 0 0 3px var(--jdx-events-focus-ring-shadow, #ffffff);
	outline: 2px solid var(--jdx-events-focus-ring-outline, #1a1a1a);
	outline-offset: 3px;
}

/* Converted from compact colored text to filled badges (Increment 2,
 * v0.2.31 — supersedes Decision 021's original "applied here as compact
 * text rather than a filled chip, matching this design's own restrained/
 * no-SaaS-chip direction" choice; see DECISIONS.md for the full
 * supersession record). Reuses the exact same status color tokens and
 * fallback chains as the shared .jdx-events-card-badge component
 * (assets/css/frontend-event-card.css) — one color source for Event
 * Grid, Featured Event, Single Event, Event Index (both its list and
 * calendar view, which render this same partial), and the standalone
 * Event Calendar widget, never five independent copies. Confirmed this
 * stylesheet's own registration already declares
 * Frontend\EventCardRenderer::STYLE_HANDLE as its WordPress style
 * dependency (Frontend\CalendarRenderer::register_assets()), so the
 * :root token declarations/overrides that handle carries are always
 * present wherever this CSS loads, including a page with only the
 * standalone Calendar widget and no other JDX component — no new
 * enqueue/dependency wiring needed.
 *
 * .event-status (the wrapping <p>) switches from plain block flow to a
 * small flex row so two simultaneously-true statuses (Cancelled + Sold
 * Out — the only valid combination) sit side by side with a compact gap
 * and wrap safely if the cell is ever too narrow for both, rather than
 * running together as unseparated inline text. Typography (font-size/
 * letter-spacing/text-transform) stays on this wrapper and inherits
 * down to each span, unchanged from before; padding/border-radius/
 * background are necessarily per-span, since each status needs its own
 * independent chip, especially when both render together. Compact
 * sizing (0.7em font, 0.2em/0.5em padding) is deliberately smaller than
 * the standard .jdx-events-card-badge elsewhere, matching this
 * component's existing tight-cell scale — "compact, filled badges," not
 * a full-size badge transplanted in. Sold Out gets a real dedicated
 * rule for the first time here too, matching the equivalent new rule in
 * frontend-event-card.css — same fallback chain, so an unconfigured
 * site's Sold Out chip looks identical to what frontend-event-card.css
 * already renders elsewhere. */
.jdx-events-calendar__event-status {
	display: flex;
	flex-wrap: wrap;
	gap: 0.3em;
	font-size: 0.7em;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	margin: 0;
}

.jdx-events-calendar__event-status--cancelled {
	display: inline-block;
	padding: 0.2em 0.5em;
	border-radius: 4px;
	background: var(--jdx-events-badge-cancelled-bg, #b30000);
	color: var(--jdx-events-badge-cancelled-text, var(--jdx-events-badge-status-text, #ffffff));
	text-decoration: line-through;
}

.jdx-events-calendar__event-status--postponed {
	display: inline-block;
	padding: 0.2em 0.5em;
	border-radius: 4px;
	background: var(--jdx-events-badge-postponed-bg, #9a6400);
	color: var(--jdx-events-badge-postponed-text, var(--jdx-events-badge-status-text, #ffffff));
}

.jdx-events-calendar__event-status--sold-out {
	display: inline-block;
	padding: 0.2em 0.5em;
	border-radius: 4px;
	background: var(--jdx-events-badge-sold-out-bg, var(--e-global-color-accent, #1a1a1a));
	color: var(--jdx-events-badge-sold-out-text, var(--e-global-color-primary, #ffffff));
}

/* .jdx-events-calendar__event-description's own layout rule is
 * intentionally absent: every Description element now carries BOTH this
 * bare class AND .jdx-events-calendar__event-description--extra (see
 * templates/event-calendar-grid.php) — two same-specificity class
 * selectors on one element would otherwise fight over
 * font-size/line-height/line-clamp/height, so --extra below is the sole
 * layout source of truth. The bare class stays in the markup regardless
 * — Elementor\Widgets\EventCalendarWidget's own Text Color Style control
 * targets `{{WRAPPER}} .jdx-events-calendar__event-description` directly
 * (an independent, higher-specificity generated rule), so the class
 * itself must remain even with no layout rule of its own here. */
.jdx-events-calendar__event-description p {
	margin: 0;
}

/* .jdx-events-calendar__event-pricing rule removed (validation.30
 * Correction 4): Pricing is no longer rendered anywhere in the Calendar
 * (Standard or Extra) — templates/event-calendar-grid.php no longer
 * emits this class at all, so the rule was fully unreachable dead CSS.
 * Not referenced by any Elementor widget (confirmed via inspection).
 * $event['pricing_lines'] itself is untouched; every other component
 * that renders Pricing is unaffected. */

/* margin-top:auto REMOVED (validation.33 Correction — Defect 2): it
 * anchored the CTA row to the bottom of this article's own box, which —
 * once .jdx-events-calendar__event started filling the fixed-height day
 * cell (validation.32) — pulled the CTA (and, for Standard events, the
 * Description right above it, with nothing else between) all the way
 * down to the bottom of a now much-taller box, live-validated as a
 * large, unintended blank gap between Title and Description/CTA. The
 * Extra branch never actually needed this rule: its own
 * .jdx-events-calendar__event-spacer (flex:1 1 auto) already consumes
 * whatever extra height the fixed cell provides, BEFORE the
 * Status/CTA rows are reached — so Extra's own CTA still sits
 * correctly near the bottom of its content group with no margin trick
 * needed here at all. Standard events (which have no spacer element, by
 * design) now simply follow Description with a small fixed gap instead,
 * clustering Title/Description/CTA together near the top exactly as
 * required — the full-height BACKGROUND surface itself
 * (.jdx-events-calendar__event's own flex:1 1 auto) is completely
 * unaffected by this change; only the CONTENT distribution inside it
 * is. */
.jdx-events-calendar__event-cta {
	display: flex;
	gap: 0.4em;
	margin: 0.4em 0 0;
	/* Event → Single Event navigation UX (validation.40 Part 2): stacks
	 * above the stretched title link's ::after (z-index:1, see
	 * .jdx-events-calendar__event-title a::after above) so Details/Buy
	 * Tickets stay independently clickable. */
	position: relative;
	z-index: 2;
}

.jdx-events-calendar__event-details,
.jdx-events-calendar__event-tickets {
	flex: 1 1 0;
	text-align: center;
	font-size: 0.68em;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	padding: 0.45em 0.3em;
	border: 1px solid transparent;
	border-radius: 0;
	text-decoration: none;
}

/* Increment 5G (v0.2.25 development cycle); mobile exception removed in
 * Increment 5G.1 — this rule now applies at every viewport width. When
 * Tickets is suppressed or unavailable (templates/event-calendar-grid.php's
 * own conditional — unchanged), Details becomes the sole child of
 * .jdx-events-calendar__event-cta, and flex-grow:1 above would then let
 * it stretch to fill the entire row. :only-child targets exactly that
 * case — the row still has two CTAs' worth of layout math (gap:0.4em,
 * two buttons at flex-basis:0 growing equally = each renders at
 * 50% - 0.2em), so a lone CTA keeps that same effective width, sitting
 * in its normal flex-start position with the other half of the row left
 * empty, rather than stretching — desktop, tablet, and mobile alike.
 * Increment 5E's mobile agenda (empty/outside-month day hiding,
 * compact row treatment) is otherwise completely unaffected. */
.jdx-events-calendar__event-details:only-child,
.jdx-events-calendar__event-tickets:only-child {
	flex: 0 1 calc( 50% - 0.2em );
}

/* Details is the event's own permalink relabeled — a secondary/ghost
 * treatment, never suppressed by status (it is not a business CTA).
 * Tickets reuses the existing tickets_cta contract exactly as every
 * other JDX template already does, including its suppression rule
 * (Decision 021: Cancelled/Sold Out suppress, Postponed does not) —
 * see templates/event-calendar.php's own conditional. */
.jdx-events-calendar__event-details {
	background: transparent;
	color: inherit;
	border-color: var(--jdx-events-card-border-color, #4a4a4a);
}

.jdx-events-calendar__event-tickets {
	background: var(--jdx-events-color-accent, #1a1a1a);
	color: var(--jdx-events-cta-primary-fg, #ffffff);
	border-color: var(--jdx-events-color-accent, #1a1a1a);
}

/* Independent Primary (Buy Tickets) / Secondary (Details) CTA color
 * overrides (Correction 6, Extra Events / Cross-Promotion Mode;
 * generalized to every event in validation.30 Correction 1 — these are
 * general per-event fields, and live validation confirmed Standard
 * Calendar entries need the same override path as Extra tiles).
 * validation.30 root-cause fix: Elementor\Widgets\EventCalendarWidget
 * registers its own Normal/Hover Text/Background/Border Color controls
 * for these exact two classes (confirmed by inspection), generating a
 * {{WRAPPER}} .jdx-events-calendar__event-tickets-shaped rule at the
 * same 0,2,0 specificity as the previous version of this rule — with
 * equal specificity the winner is whichever stylesheet prints last,
 * and live validation showed Elementor's own generated CSS reliably
 * wins that race once a site editor has configured those controls
 * (an entirely plausible, likely state on a live production site).
 * Qualifying with the base .jdx-events-calendar__event class (rather
 * than the --extra modifier) plus the `a` type-selector keeps this at
 * 0,2,1 specificity, which always outranks a 0,2,0 rule regardless of
 * source order — no !important needed, and this in no way disables or
 * conflicts with Elementor's own controls, which continue to supply the
 * fallback tier's own effective default via the existing global CTA
 * tokens. Every property still falls back to that button's own existing
 * default value — never a new literal — so an event with neither
 * override configured renders identically to before. An Extra Event
 * carrying only the legacy single-pair value (validation.27 data,
 * before Primary/Secondary existed) renders identically to its own
 * previous appearance too, since Frontend\EventCardPresenter::
 * presentation() already resolved that legacy value into both pairs
 * before this template ever set these custom properties.
 *
 * validation.31 Correction (Task 9) root cause: `background: transparent`
 * below was hardcoded, not a var() — so an explicit Secondary Background
 * Color override could never actually fill this button; only the border
 * happened to pick up a color, producing exactly the reported
 * "border/ghost only" defect. Fixed by reading the same custom property
 * for the actual background fill. Border Color (Task 10) is now its own
 * dedicated field/custom property for both tiers, no longer derived from
 * Background Color (the previous "Secondary's border follows its
 * Background Color" behavior silently changed the border whenever a fill
 * was configured — surprising, and explicitly retired) — see
 * Frontend\EventCardPresenter::presentation() for the resolution.
 *
 * Elementor widget tier (Increment 3, v0.2.31, simplified in the
 * v0.2.31 stabilization Decision 045): inserted between the per-event
 * override and each property's own existing fallback.
 * Elementor\Widgets\EventCalendarWidget's 'tickets'/'details' CTA Style
 * controls write --jdx-events-cta-{primary,secondary}-{bg,fg,border}-widget
 * on {{WRAPPER}} instead of the resolved property directly, so this is
 * the ONLY rule left that ever sets background/color/border-color on
 * these selectors -- no specificity conflict possible, which is also
 * why the pre-existing `a.` specificity bump above remains safe to
 * leave in place unchanged (nothing left to out-rank). Decision 045
 * removed the JDX global setting tier entirely (Settings → JDX Events
 * → CTA Appearance no longer exists) -- the middle tier that used to
 * read the shared --jdx-events-cta-primary-bg/-fg base tokens here is
 * removed; Per-event override > Elementor widget setting > built-in
 * fallback is now the complete chain for this surface. */
.jdx-events-calendar__event a.jdx-events-calendar__event-details {
	background: var(--jdx-events-calendar-extra-cta-secondary-bg, var(--jdx-events-cta-secondary-bg-widget, transparent));
	color: var(--jdx-events-calendar-extra-cta-secondary-fg, var(--jdx-events-cta-secondary-fg-widget, var(--jdx-events-calendar-extra-text, inherit)));
	border-color: var(--jdx-events-calendar-extra-cta-secondary-border, var(--jdx-events-cta-secondary-border-widget, var(--jdx-events-card-border-color, #4a4a4a)));
}

/* Unset built-in default standardized to #D4AF37/#000000 (v0.2.31
 * stabilization, Decision 045 follow-up) — matches Featured Event's
 * own built-in default; previously chained through the generic,
 * widely-shared --jdx-events-color-accent token (used elsewhere for
 * unrelated structural UI — the "today" cell ring, Prev/Next hover —
 * so its own value is deliberately left untouched here, not
 * repurposed). Details/Secondary is NOT touched — it is a distinct
 * ghost-style permalink action, not CTA 2 (see DECISIONS.md). */
.jdx-events-calendar__event a.jdx-events-calendar__event-tickets {
	background: var(--jdx-events-calendar-extra-cta-primary-bg, var(--jdx-events-cta-primary-bg-widget, #D4AF37));
	color: var(--jdx-events-calendar-extra-cta-primary-fg, var(--jdx-events-cta-primary-fg-widget, #000000));
	border-color: var(--jdx-events-calendar-extra-cta-primary-border, var(--jdx-events-cta-primary-border-widget, #D4AF37));
}

@media ( hover: hover ) {
	/* Details (ghost/outline style, never filled -- deliberately
	 * different from Table/Secondary everywhere else, which IS always
	 * filled): background intentionally does NOT consume the shared
	 * --jdx-events-cta-secondary-bg-hover token here, since that token's
	 * own :root default (#e6e6e6) is a "filled" shade that would give
	 * Details an unwanted hover fill the instant this increment ships,
	 * even with zero settings touched anywhere. Per-event and Elementor
	 * widget overrides can still explicitly paint a hover fill if
	 * configured; only the JDX global default is skipped for this one
	 * property, on this one button -- text color has no such conflict and
	 * participates in the global tier normally. Elementor's own
	 * pre-existing Hover Border Color control for 'details' IS rewired
	 * (a genuine border-color declaration already existed here to
	 * extend); 'tickets' Hover Border Color is NOT (see below). */
	.jdx-events-calendar__event-details:hover {
		background: var(--jdx-events-calendar-extra-cta-secondary-bg-hover, var(--jdx-events-cta-secondary-bg-hover-widget, transparent));
		color: var(--jdx-events-calendar-extra-cta-secondary-fg-hover, var(--jdx-events-cta-secondary-fg-hover-widget, var(--jdx-events-calendar-extra-cta-secondary-fg, var(--jdx-events-calendar-extra-text, inherit))));
		border-color: var(--jdx-events-cta-secondary-border-hover-widget, var(--jdx-events-color-accent, currentColor));
	}

	/* Tickets Hover Border Color (Elementor widget control) is
	 * deliberately left UNREWIRED: this border-color has never had its
	 * own dedicated token -- it has always simply mirrored whatever
	 * bg-hover resolves to (a filled look), with no independent
	 * per-event/global tier to layer in. Per the Increment 3 correction,
	 * a control is only rewired into a token when the corresponding CSS
	 * actually consumes that token; since none does here, Elementor's own
	 * direct `{{WRAPPER}} .jdx-events-calendar__event-tickets:hover { border-color: ... }`
	 * rule (specificity 0,3,0) continues, unchanged, to take precedence
	 * over this rule's own border-color (specificity 0,2,0) whenever
	 * configured -- documented, pre-existing behavior, not altered here. */
	.jdx-events-calendar__event-tickets:hover {
		background: var(--jdx-events-calendar-extra-cta-primary-bg-hover, var(--jdx-events-cta-primary-bg-hover-widget, #0d0d0d));
		color: var(--jdx-events-calendar-extra-cta-primary-fg-hover, var(--jdx-events-cta-primary-fg-hover-widget, var(--jdx-events-calendar-extra-cta-primary-fg, #000000)));
		border-color: var(--jdx-events-calendar-extra-cta-primary-bg-hover, var(--jdx-events-cta-primary-bg-hover-widget, #0d0d0d));
	}

	/* Event → Single Event navigation UX (validation.40 Part 2): hovering
	 * anywhere on the tile — including the stretched title-link overlay,
	 * a descendant of .jdx-events-calendar__event — also matches :hover
	 * here, since :hover applies to every ancestor of the pointed-at
	 * element. Restrained response only: existing border/title tokens,
	 * no transform/scale/glow. Independent of the Details button's own
	 * existing :hover rule above. */
	.jdx-events-calendar__event:hover {
		border-color: var(--jdx-events-color-accent, currentColor);
	}

	.jdx-events-calendar__event:hover .jdx-events-calendar__event-title a {
		color: var(--jdx-events-color-accent, currentColor);
	}
}

.jdx-events-calendar__event-details:focus-visible,
.jdx-events-calendar__event-tickets:focus-visible {
	position: relative;
	z-index: 1;
	box-shadow: 0 0 0 3px var(--jdx-events-focus-ring-shadow, #ffffff);
	outline: 2px solid var(--jdx-events-focus-ring-outline, #1a1a1a);
	outline-offset: 3px;
}

/* validation.30's desktop square/equal cell matrix (strict aspect-ratio:1
 * day cells + overflow-y:auto internal scroll on
 * .jdx-events-calendar__events) is REMOVED here (validation.31 Task 3):
 * live validation confirmed it produced internal Calendar scrollbars on
 * genuinely tall Extra tiles and did not reliably let event backgrounds
 * fill the cell either. Row-height consistency is now handled the way
 * .jdx-events-calendar__day's own comment above describes — CSS Grid's
 * default row-sizing/stretch behavior, the same mechanism this Calendar
 * already relied on before that experiment — with no dedicated
 * breakpoint, no forced square, and no internal scroll of any kind. */

/* Increment 5E (v0.2.25 development cycle): mobile becomes a compact
 * chronological event agenda over the exact same Calendar DOM/data — not
 * a second component, not a JS-driven view, not a new query. The
 * standalone Calendar's 7-column grid and every desktop rule above this
 * breakpoint are completely unchanged. */
@media ( max-width: 700px ) {
	.jdx-events-calendar__grid-head {
		display: none;
	}

	.jdx-events-calendar__grid {
		/* minmax(0, 1fr), not a bare 1fr — same grid-blowout defense as
		 * the desktop rule (Correction 4), so unbreakable content can't
		 * force horizontal page scroll on the single-column mobile
		 * agenda either. */
		grid-template-columns: minmax( 0, 1fr );
		/* No extra row gap on mobile: each visible row now separates
		 * itself with its own border-bottom below, matching a compact
		 * agenda-list rhythm rather than the desktop boxed-cell grid's
		 * own gap. */
		gap: 0;
	}

	/* Outside-month cells are hidden outright on mobile, regardless of
	 * whether the cell happens to carry a neighboring month's event —
	 * avoids duplicate/confusing month content in a single-column
	 * agenda. Safe and always-available (no :has() dependency): every
	 * outside-month cell already unconditionally carries this exact
	 * class (templates/event-calendar-grid.php), so this rule works in
	 * every browser regardless of the :has() rule below. Kept as its
	 * own separate rule (not comma-joined with the :has() rule) so an
	 * unsupported :has() selector can never risk invalidating this
	 * simple, always-safe one in the same declaration. */
	.jdx-events-calendar__day--outside {
		display: none;
	}

	/* Empty in-month cells are hidden too, leaving only the days that
	 * actually have something to show — this is what turns 30+ stacked
	 * day blocks into a short, meaningful agenda. CSS-only against the
	 * existing, unmodified DOM: templates/event-calendar-grid.php only
	 * ever renders a .jdx-events-calendar__events child when that cell's
	 * own $cell['events'] array is non-empty, so
	 * :not(:has(.jdx-events-calendar__events)) is already a reliable
	 * structural "no events" signal — no new class, no template change.
	 * :has() has been Baseline-supported in every major browser since
	 * 2023; where it is unsupported, this one rule is simply dropped and
	 * mobile Calendar falls back to exactly validation.16's existing
	 * behavior (every day cell visible) — a safe progressive
	 * enhancement, never a functional regression. */
	.jdx-events-calendar__day:not( :has( .jdx-events-calendar__events ) ) {
		display: none;
	}

	/* Thin row separator instead of a box bordered on all four sides —
	 * a leaner agenda-row feel, reduced padding, no cell-box look.
	 * .jdx-events-calendar__day--today's own box-shadow ring (unchanged,
	 * above) still fully outlines a visible today row regardless of this
	 * border change, so the today cue remains just as clear. */
	.jdx-events-calendar__day {
		min-height: 0;
		padding: 0.75em 0;
		border: none;
		border-bottom: 1px solid var(--jdx-events-card-border-color, #4a4a4a);
	}

	.jdx-events-calendar__day-label {
		position: static;
		width: auto;
		height: auto;
		padding: 0;
		margin: 0 0.5em 0 0;
		overflow: visible;
		clip: auto;
		white-space: normal;
		border: 0;
		display: inline;
		font-size: 0.8em;
		text-transform: uppercase;
	}

	/* Small inner padding — mobile agenda content was sitting flush
	 * against the card edges. validation.36: 0.5em/0.6em (validation.35)
	 * read as slightly too padded for this compact agenda; reduced to
	 * 0.3em/0.4em — still deliberately smaller than the desktop rule's
	 * own 0.6em/0.7em, just enough that text/CTA never touch the card
	 * boundary without adding meaningful row height or pulling in any of
	 * desktop's fixed-height/overlay treatment. */
	.jdx-events-calendar__event {
		padding: 0.3em 0.4em;
	}

	/* margin:0, not just margin-bottom:0 (validation.31 — verified no
	 * desktop leak): the desktop rule above now sets a full
	 * margin:0.6em 0.7em 0.5em shorthand (replacing the day cell's own
	 * removed padding); this inline mobile date needs none of that
	 * inset (horizontal spacing between it and the day-label abbreviation
	 * already comes from that label's own margin-right:0.5em above), so
	 * every side must be reset here, not just bottom. */
	.jdx-events-calendar__date {
		display: inline;
		margin: 0;
	}
}

/* S2 (v0.2.31): multiple-event day — compact row list, one clickable row
 * per event, replacing the full promotional tile(s) that previously
 * stacked without limit and overflowed the desktop day cell's fixed
 * 16em height (the measured clipping defect this stabilization work
 * identified). Shared by both breakpoints: on mobile the day cell has no
 * fixed height/overflow:hidden to begin with, so this list just sits as
 * a short stacked agenda inside the existing mobile card styling below;
 * the desktop-only overlay escape for the overflow panel is further
 * down, scoped to the same min-width:701px breakpoint as the day cell's
 * own fixed height. */
.jdx-events-calendar__event-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.2em;
	min-width: 0;
}

/* S2 Final Spacing Refinement: the outer (visible-rows) list only, never
 * the nested --overflow list inside the open <details> panel — that
 * panel sits below the visible rows (top:100% on the day cell further
 * down), never under the absolutely-positioned day number, so it needs
 * no such reservation. .jdx-events-calendar__date is absolutely
 * positioned only at this same min-width:701px breakpoint (see its own
 * rule above); below that breakpoint it stays in normal flow and
 * already pushes this list down on its own, so this reservation is
 * desktop-only, matching the existing single-event tile's own
 * first-child padding-top:2em fix for the identical overlap. */
@media ( min-width: 701px ) {
	.jdx-events-calendar__event-list:not( .jdx-events-calendar__event-list--overflow ) {
		padding-top: 40px;
	}
}

.jdx-events-calendar__event-list-item {
	min-width: 0;
	border-bottom: 1px solid var(--jdx-events-card-border-color, #4a4a4a);
}

.jdx-events-calendar__event-list-item:last-child {
	border-bottom: none;
}

/* Whole row is the click target, not just the title text — a larger,
 * easier touch/pointer target than an inline link alone would give. */
/* S2 Final Spacing Refinement: left padding set explicitly to 12px
 * (not the shared 0.1em the other three sides keep) so a multi-event
 * row's clickable text doesn't start flush against the day cell's own
 * left edge. The whole padding box is still part of the <a>, so the
 * full row -- including this added left inset -- remains clickable;
 * time and title only shift right together (same gap between them),
 * so their relative alignment is unaffected. */
.jdx-events-calendar__event-list-link {
	display: flex;
	align-items: baseline;
	gap: 0.4em;
	min-width: 0;
	padding: 0.25em 0.1em 0.25em 12px;
	color: inherit;
	text-decoration: none;
}

.jdx-events-calendar__event-list-link:focus-visible {
	outline: 2px solid var(--jdx-events-color-accent, currentColor);
	outline-offset: 1px;
}

@media ( hover: hover ) {
	.jdx-events-calendar__event-list-link:hover .jdx-events-calendar__event-list-title {
		text-decoration: underline;
	}
}

.jdx-events-calendar__event-list-time {
	flex: 0 0 auto;
	font-size: 0.68em;
	opacity: 0.8;
}

/* flex:1 1 auto + min-width:0 + ellipsis — same long-title defense used
 * throughout this file's single-tile markup, so one very long title in
 * a compact row can't force the row (and the day cell) wider than the
 * grid column. */
.jdx-events-calendar__event-list-title {
	flex: 1 1 auto;
	min-width: 0;
	font-size: 0.78em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* "+N more" disclosure — native <details>/<summary>, no JS: keyboard-
 * operable and exposes its own open/closed state to assistive tech for
 * free. Collapsed, it's simply one more compact row. */
.jdx-events-calendar__event-list-more {
	border-bottom: none;
}

/* > details > summary, not > summary — S2 Final Spacing Refinement:
 * the actual markup is <li class="...-more"><details><summary>, so
 * <summary> is a grandchild of this <li>, never a direct child. The
 * earlier "> summary" selector never matched anything; these three
 * rules had silently never applied. */
.jdx-events-calendar__event-list-more > details > summary {
	cursor: pointer;
	list-style: none;
	padding: 0.25em 0.1em;
	font-size: 0.68em;
	opacity: 0.85;
}

.jdx-events-calendar__event-list-more > details > summary::-webkit-details-marker {
	display: none;
}

.jdx-events-calendar__event-list-more > details > summary:focus-visible {
	outline: 2px solid var(--jdx-events-color-accent, currentColor);
	outline-offset: 1px;
}

@media ( min-width: 701px ) {
	/* The expanded overflow list must never grow the day cell or push
	 * adjacent cells — it renders as a floating panel instead. Absolute
	 * positioning alone isn't enough: .jdx-events-calendar__day is the
	 * nearest positioned ancestor (position:relative, set above) but it
	 * also carries its own fixed height + overflow:hidden on this same
	 * breakpoint, which would clip the panel right back. The :has() rule
	 * below temporarily lifts that clipping on exactly the day cell whose
	 * own <details> is open, the same progressive-enhancement technique
	 * already used by this file's mobile "hide empty days" rule above:
	 * Baseline-supported since 2023, and where unsupported, the panel
	 * still opens but may be visually clipped by the cell's own boundary
	 * — a safe degradation (every event stays reachable in the DOM/tab
	 * order), never a functional one. */
	.jdx-events-calendar__day:has( details[open] ) {
		overflow: visible;
		z-index: 10;
	}

	.jdx-events-calendar__event-list--overflow {
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		margin-top: 0.1em;
		background: var(--jdx-events-card-bg, #1a1a1a);
		border: 1px solid var(--jdx-events-card-border-color, #4a4a4a);
		padding: 0.3em 0.4em;
		max-height: 50vh;
		overflow-y: auto;
		box-shadow: 0 4px 12px rgba( 0, 0, 0, 0.4 );
		z-index: 11;
	}
}

/* Past-event styling (v0.2.32, Decision 050) — opt-in only: the grid
 * carries --past-dimmed solely when the Event Calendar widget's "Past
 * Event Style" (or Event Index's "Past Events in Calendar") is set to
 * Dimmed, and only then does the template mark completed events. An
 * untouched calendar has none of these classes and renders exactly as
 * before.
 *
 * Reduced prominence without hurting readability: the tile is
 * desaturated (photography and accent colors fade to grey — white/black
 * text keeps its contrast) and, when it has a background image, a scrim
 * darkens that image further. The scrim is ::after with z-index:-1
 * inside the tile's own stacking context (isolation:isolate), so it
 * paints above the background image and overlay but below every piece
 * of text and every link. Text, links and focus rings are never made
 * transparent on tiles; links stay fully clickable and focusable.
 * Compact multi-event rows get a mild 0.75 opacity on their text spans
 * only (not the link, so its focus ring keeps full strength).
 * --jdx-events-calendar-past-scrim lets a theme tune the scrim color. */
.jdx-events-calendar__grid--past-dimmed .jdx-events-calendar__event--completed {
	filter: grayscale( 1 );
}

.jdx-events-calendar__grid--past-dimmed .jdx-events-calendar__event--completed.jdx-events-calendar__event--extra-bg::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background-color: var( --jdx-events-calendar-past-scrim, rgba( 0, 0, 0, 0.4 ) );
}

.jdx-events-calendar__grid--past-dimmed .jdx-events-calendar__event-list-item--completed .jdx-events-calendar__event-list-time,
.jdx-events-calendar__grid--past-dimmed .jdx-events-calendar__event-list-item--completed .jdx-events-calendar__event-list-title {
	opacity: 0.75;
	filter: grayscale( 1 );
}

/* ------------------------------------------------------------------
 * Deal dates (v0.2.33, Calendar Content "Events + Deals" / "Deals
 * only"). Compact rows in the same list as compact event rows; only
 * rendered when an editor opts in, so nothing here affects an
 * Events-only calendar. Each kind gets a visible text label and its own
 * marker shape (dashed = qualifying visit, solid = redemption, double =
 * direct offer), so the distinction never relies on color alone.
 * --jdx-events-calendar-deal-color (marker only) is set per kind by the
 * widgets' Style → Deal Dates controls.
 * ------------------------------------------------------------------ */

.jdx-events-calendar__deal {
	--jdx-events-calendar-deal-color: var(--jdx-events-color-accent, currentColor);
}

.jdx-events-calendar__deal .jdx-events-calendar__deal-link {
	flex-wrap: wrap;
	row-gap: 0;
	border-left: 3px solid var(--jdx-events-calendar-deal-color);
	padding-left: 9px;
}

.jdx-events-calendar__deal--qualify .jdx-events-calendar__deal-link {
	border-left-style: dashed;
}

.jdx-events-calendar__deal--available .jdx-events-calendar__deal-link {
	border-left-style: double;
	border-left-width: 4px;
}

.jdx-events-calendar__deal-kind {
	flex: 0 0 100%;
	font-size: 0.6em;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	opacity: 0.85;
}

/* Text keeps the inherited (contrast-checked) text color; only the
 * marker uses the per-kind color. */
.jdx-events-calendar__deal-highlight {
	font-weight: 700;
}
