/**
 * Kalendli calendar — front-end presentation.
 *
 * Typography-led, classical-grid design system (Agent/project/07_design_system.md).
 * Layer order (specificity deliberately increases downward):
 *
 *   1. Foundation     — tokens, base type, atmosphere
 *   2. Shared         — the stable semantic list structure all views share
 *   3. Design presets — design_preset treatments (swiss is the foundation default)
 *   4. Layouts        — view structures (index, editorial, compact, card; agenda
 *                       and timetable are reserved and inherit the index structure)
 *   5. Image modes    — static figures (card/inline) and the hover preview element
 *   6. Interactions   — single-event accordion and lightbox dialog surfaces
 *   7. Empty state
 *   8. Responsive     — recomposition, not squeezed grids
 *   9. Accessibility  — focus, forced colors, reduced motion
 *
 * Doctrine: time is the primary visual coordinate; rules (not boxes or
 * shadows) express chronology with four deliberate weights (structural rule,
 * group hairline, status outline, focus outline); identity comes from
 * repetition plus at most one status-driven anomaly, never color alone.
 * Fonts and color inherit from the active theme; uppercase is applied
 * visually only, never to source content. theme.json presets are preferred
 * when present.
 */

/* == 1. Foundation: tokens, base type, atmosphere ========================= */

.kalendli-calendar,
.kalendli-event {
	/* Minimal token set from the design system spec; theme.json presets are
	   used when present, fallbacks keep non-block-theme sites correct. Both
	   the calendar list and the single-event detail share one type register. */
	--kalendli-font-body: var(--wp--preset--font-family--body, inherit);
	--kalendli-font-display: var(--wp--preset--font-family--heading, inherit);
	--kalendli-color: inherit;
	--kalendli-muted: currentColor;
	--kalendli-muted: color-mix(in srgb, currentColor 62%, transparent);
	--kalendli-rule: currentColor;
	--kalendli-rule: color-mix(in srgb, currentColor 18%, transparent);
	--kalendli-rule-strong: currentColor;
	--kalendli-rule-strong: color-mix(in srgb, currentColor 80%, transparent);
	--kalendli-accent: currentColor;
	--kalendli-gap-xs: var(--wp--preset--spacing--20, 0.25rem);
	--kalendli-gap-sm: var(--wp--preset--spacing--30, 0.5rem);
	--kalendli-gap-md: var(--wp--preset--spacing--40, 1rem);
	--kalendli-gap-lg: var(--wp--preset--spacing--50, 1.5rem);
	--kalendli-gap-xl: var(--wp--preset--spacing--60, 2rem);
	--kalendli-date-scale: 3.2;
	--kalendli-title-scale: 1.3;
	--kalendli-card-radius: 0;
	/* Swiss type register: one size and one caps tracking for every small
	   label (weekday, month, status, tags, venue, action, empty state);
	   numerals and display headings take the tight tracking and leading. */
	/* Structural vs. hairline rule weights (status and focus outlines live
	   with their components below). */
	--kalendli-rule-structural: 2px;
	--kalendli-rule-hairline: 1px;
	--kalendli-text-micro: 0.6875rem;
	--kalendli-text-meta: 0.8125rem;
	--kalendli-track-caps: 0.14em;
	--kalendli-track-tight: -0.03em;
	--kalendli-leading-display: 1.05;

	font-family: var(--kalendli-font-body);
	color: var(--kalendli-color);
	/* No background atmosphere: the calendar sits flush on the theme's own
	   surface; hierarchy comes from type and rules alone. */
	line-height: 1.4;
}

/* == 2. Shared list structure =============================================
   A poster timetable: heavy structural rules open and close the run of rows,
   hairlines separate them, oversized numerals lead, flush-left titles and a
   disciplined right-hand place column complete the row. */

.kalendli-calendar__items {
	list-style: none;
	margin: 0;
	padding: 0;
	border-top: var(--kalendli-rule-structural) solid var(--kalendli-rule-strong);
	border-bottom: var(--kalendli-rule-structural) solid var(--kalendli-rule-strong);
}

.kalendli-calendar__item {
	display: grid;
	grid-template-columns: minmax(5rem, auto) minmax(0, 1fr) minmax(0, auto);
	column-gap: var(--kalendli-gap-lg);
	align-items: baseline;
	padding: var(--kalendli-gap-lg) 0;
	border-bottom: var(--kalendli-rule-hairline) solid var(--kalendli-rule);
}

.kalendli-calendar__item:last-child {
	border-bottom: 0;
}

/* Whole-row link: the title's anchor is stretched across the entire item —
   card or list row — while sibling links (ticket actions, venue) stay
   interactive above it. One real link per item keeps keyboard order and
   screen-reader output clean. */

.kalendli-calendar__item--linked {
	position: relative;
	cursor: pointer;
	transition: background-color 140ms ease, box-shadow 140ms ease;
}

.kalendli-calendar__item--linked .kalendli-calendar__title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.kalendli-calendar__item--linked:hover,
.kalendli-calendar__item--linked:focus-within {
	background: transparent;
	background: color-mix(in srgb, currentColor 5%, transparent);
}

.kalendli-calendar__item--linked:focus-within {
	outline: 2px solid currentColor;
	outline-offset: 4px;
}

.kalendli-calendar--card .kalendli-calendar__item--linked:hover,
.kalendli-calendar--card .kalendli-calendar__item--linked:focus-within {
	box-shadow: 0 0 0 2px currentColor;
	box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 32%, transparent);
}

.kalendli-calendar__item--linked .kalendli-calendar__action,
.kalendli-calendar__item--linked .kalendli-calendar__venue {
	position: relative;
	z-index: 2;
}

.kalendli-calendar__item--linked .kalendli-calendar__title a:hover,
.kalendli-calendar__item--linked .kalendli-calendar__title a:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

/* Tags render as quiet pill chips; the ticket/action link is a pill
   button in every view so the primary action reads as a button. */

.kalendli-calendar__tags {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
	list-style: none;
	margin: 0.25rem 0 0;
	padding: 0;
}

.kalendli-calendar__tag {
	border: 1px solid var(--kalendli-rule);
	border-radius: 999px;
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	letter-spacing: var(--kalendli-track-caps);
	padding: 0.15rem 0.6rem;
	text-transform: uppercase;
	color: var(--kalendli-muted);
}

.kalendli-calendar__action a {
	border: 2px solid currentColor;
	border-radius: 999px;
	display: inline-block;
	padding: 0.3rem 0.9rem;
	text-decoration: none;
}

.kalendli-calendar__action a:hover,
.kalendli-calendar__action a:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

/* Date column: weekday micro-label, oversized day numeral, quiet month.
   Baseline-aligned with the title: date and title share one reading line. */

.kalendli-calendar__date {
	display: inline-flex;
	flex-direction: column;
	align-items: flex-start;
	text-decoration: none;
	font-variant-numeric: tabular-nums;
	min-width: 5rem;
}

.kalendli-calendar__weekday,
.kalendli-calendar__month {
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
	color: var(--kalendli-muted);
}

.kalendli-calendar__weekday {
	order: -1;
	margin-bottom: var(--kalendli-gap-xs);
}

.kalendli-calendar__day {
	font-family: var(--kalendli-font-display);
	/* Defensive scaling: never below a legible numeral, never above the
	   preset's intended poster scale. */
	font-size: clamp(2.4rem, calc(0.55em + 3.2vw), calc(1em * var(--kalendli-date-scale)));
	font-weight: 700;
	line-height: 0.95;
	letter-spacing: var(--kalendli-track-tight);
	font-variant-numeric: tabular-nums lining-nums;
}

.kalendli-calendar__month {
	margin-top: var(--kalendli-gap-xs);
	/* The month is the row's word, not a caption: it carries the date on its
	   own when the numeral is read at a glance, so it sits a step above the
	   micro register the weekday keeps. */
	font-size: var(--kalendli-text-meta);
	letter-spacing: var(--kalendli-track-caps);
}

.kalendli-calendar__time {
	margin-top: var(--kalendli-gap-sm);
	font-size: var(--kalendli-text-meta);
	font-weight: 600;
	font-variant-numeric: tabular-nums lining-nums;
	color: var(--kalendli-muted);
}

/* Summary column: display-family title at poster scale, quiet metadata.
   Real content can be long: no fixed heights, no truncation — wrap, and
   break unbreakable tokens as a last resort. */

.kalendli-calendar__summary {
	min-width: 0;
	overflow-wrap: break-word;
}

.kalendli-calendar__programme,
.kalendli-calendar__participants {
	margin: var(--kalendli-gap-xs) 0 0;
	font-size: var(--kalendli-text-meta);
	line-height: 1.35;
	color: var(--kalendli-muted);
}

.kalendli-calendar__participants {
	margin-top: var(--kalendli-gap-sm);
}

.kalendli-calendar__title {
	margin: 0;
	font-family: var(--kalendli-font-display);
	font-size: clamp(1rem, calc(0.95em + 0.4vw), calc(1em * var(--kalendli-title-scale)));
	font-weight: 700;
	line-height: var(--kalendli-leading-display);
	letter-spacing: -0.015em;
	text-wrap: balance;
	overflow-wrap: anywhere;
}

.kalendli-calendar__title a {
	color: inherit;
	text-decoration: none;
}

.kalendli-calendar__title a:hover,
.kalendli-calendar__title a:focus-visible {
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 0.15em;
}

/* Status chip: outlined uppercase label, like a printed programme tag.
   Outline (a rule weight), never a fill — unknown themes must stay safe,
   and status is never communicated by color alone. */

.kalendli-calendar__meta {
	margin: var(--kalendli-gap-sm) 0 0;
}

.kalendli-calendar__status {
	display: inline-block;
	padding: 0.2em 0.6em;
	border: var(--kalendli-rule-hairline) solid var(--kalendli-rule-strong);
	font-size: var(--kalendli-text-micro);
	font-weight: 700;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
	color: inherit;
}

/* Availability banner: the one status-driven anomaly. A manual Event-level
   statement ("no tickets left") reads as a heavier outlined tag than the
   schedule status chip, so the two never blur together, and the words — not
   color — carry the meaning. */

.kalendli-calendar__availability {
	margin: var(--kalendli-gap-sm) 0 0;
}

.kalendli-calendar__sold-out {
	display: inline-block;
	padding: 0.25em 0.7em;
	border: var(--kalendli-rule-structural) solid currentColor;
	font-size: var(--kalendli-text-micro);
	font-weight: 700;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
	overflow-wrap: anywhere;
}

.kalendli-calendar__action {
	margin: var(--kalendli-gap-sm) 0 0;
	min-width: 0;
	max-width: 100%;
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
	overflow-wrap: anywhere;
}

.kalendli-calendar__action a {
	display: inline-block;
	max-width: 100%;
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 0.2em;
	text-decoration-thickness: 1px;
}

.kalendli-calendar__action a::after {
	content: " \2197"; /* external/tickets affordance */
}

/* Venue column: uppercase micro-label pinned right, like a poster colophon. */

.kalendli-calendar__venue {
	margin: 0;
	min-width: 0;
	max-width: 100%;
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	line-height: 1.5;
	text-align: right;
	text-transform: uppercase;
	letter-spacing: var(--kalendli-track-caps);
	color: var(--kalendli-muted);
	overflow-wrap: anywhere;
}

/* == 3. Design presets ====================================================
   Presets are typography/rule treatments, orthogonal to layout and images.
   `swiss` is the foundation default above (poster numerals, heavy structural
   rules, uppercase micro-labels). Preset rules come before layouts so
   density-critical layouts (compact) keep priority. */

/* Classical grid: a quiet, printed-programme register. Hairline rules only,
   inline dates, sentence-case place column, restrained scale. */

.kalendli-calendar--preset-classic {
	--kalendli-date-scale: 1.6;
	--kalendli-title-scale: 1.08;
	--kalendli-rule-structural: 1px;
	--kalendli-rule-strong: currentColor;
	--kalendli-rule-strong: color-mix(in srgb, currentColor 38%, transparent);
}

.kalendli-calendar--preset-classic .kalendli-calendar__item {
	padding: var(--kalendli-gap-md) 0;
}

.kalendli-calendar--preset-classic .kalendli-calendar__date {
	flex-direction: row;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 0.4rem;
}

.kalendli-calendar--preset-classic .kalendli-calendar__weekday,
.kalendli-calendar--preset-classic .kalendli-calendar__month {
	font-size: 0.68em;
	letter-spacing: 0.1em;
}

.kalendli-calendar--preset-classic .kalendli-calendar__weekday {
	margin-bottom: 0;
}

.kalendli-calendar--preset-classic .kalendli-calendar__month {
	margin-top: 0;
}

.kalendli-calendar--preset-classic .kalendli-calendar__day {
	letter-spacing: -0.01em;
}

.kalendli-calendar--preset-classic .kalendli-calendar__title {
	letter-spacing: 0;
}

.kalendli-calendar--preset-classic .kalendli-calendar__venue {
	text-transform: none;
	letter-spacing: 0.02em;
	font-size: 0.8em;
}

/* Expressive poster: maximum type energy for hero placements — larger
   numerals and titles, tighter tracking, more generous pacing. */

.kalendli-calendar--preset-expressive {
	--kalendli-date-scale: 4.2;
	--kalendli-title-scale: 1.6;
}

.kalendli-calendar--preset-expressive .kalendli-calendar__item {
	padding: var(--kalendli-gap-xl) 0;
}

.kalendli-calendar--preset-expressive .kalendli-calendar__day {
	letter-spacing: -0.045em;
}

.kalendli-calendar--preset-expressive .kalendli-calendar__weekday,
.kalendli-calendar--preset-expressive .kalendli-calendar__month {
	font-size: 0.66em;
	letter-spacing: 0.18em;
}

.kalendli-calendar--preset-expressive .kalendli-calendar__title {
	letter-spacing: -0.025em;
}

/* == 4. Layouts ===========================================================
   The index view is the shared structure itself. Editorial, compact, and
   card re-compose the same semantic markup. Agenda and timetable are
   reserved view names: they inherit the index structure until their model
   support is verified. */

/* Editorial / big date: the date becomes a horizontal typographic event at
   the head of each row. */

.kalendli-calendar--editorial {
	--kalendli-date-scale: 3.8;
	--kalendli-title-scale: 1.45;
}

.kalendli-calendar--editorial .kalendli-calendar__date {
	flex-direction: row;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 0.6rem;
	min-width: 8rem;
}

.kalendli-calendar--editorial .kalendli-calendar__weekday {
	margin-bottom: 0;
}

.kalendli-calendar--editorial .kalendli-calendar__month {
	margin-top: 0;
}

.kalendli-calendar--editorial .kalendli-calendar__time {
	margin-top: 0;
}

.kalendli-calendar--editorial .kalendli-calendar__title {
	margin-top: var(--kalendli-gap-xs);
}

/* Compact archive: tighter rows, inline date, near-body scale. Density is
   acceptable because the hierarchy stays sharp; layout wins over presets
   where they conflict. */

.kalendli-calendar--compact {
	--kalendli-date-scale: 1.15;
	--kalendli-title-scale: 1;
}

.kalendli-calendar--compact .kalendli-calendar__items {
	border-top-width: 1px;
	border-bottom-width: 1px;
}

.kalendli-calendar--compact .kalendli-calendar__item {
	padding: var(--kalendli-gap-sm) 0;
	column-gap: var(--kalendli-gap-md);
	grid-template-columns: minmax(5.5rem, auto) minmax(0, 1fr) minmax(0, auto);
}

.kalendli-calendar--compact .kalendli-calendar__date {
	flex-direction: row;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 0.4rem;
	min-width: 5.5rem;
}

.kalendli-calendar--compact .kalendli-calendar__weekday {
	margin-bottom: 0;
}

.kalendli-calendar--compact .kalendli-calendar__month {
	margin-top: 0;
}

/* Compact rows must stay small: bypass the foundation's legibility clamp,
   which would otherwise raise the numeral above the intended density. */
.kalendli-calendar--compact .kalendli-calendar__day {
	font-size: calc(1em * var(--kalendli-date-scale));
	font-weight: 700;
	line-height: 1;
}

.kalendli-calendar--compact .kalendli-calendar__time {
	margin-top: 0;
}

.kalendli-calendar--compact .kalendli-calendar__title {
	font-weight: 600;
	line-height: 1.3;
	letter-spacing: 0;
}

.kalendli-calendar--compact .kalendli-calendar__venue {
	text-align: right;
}

/* Card: poster tiles — square corners, hairline frame, oversized numeral,
   venue pinned to the tile floor under a hairline. Two card concepts live
   on this one structure: the interface card (quiet) and the poster card
   (preset-expressive); the markup never differs. */

.kalendli-calendar--card .kalendli-calendar__items {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
	gap: var(--kalendli-gap-md);
	border-top: 0;
	border-bottom: 0;
}

.kalendli-calendar--card .kalendli-calendar__item {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--kalendli-gap-xs);
	padding: var(--kalendli-gap-lg) var(--kalendli-gap-md);
	border: 1px solid var(--kalendli-rule);
	border-radius: var(--kalendli-card-radius);
}

.kalendli-calendar--card .kalendli-calendar__day {
	font-size: calc(1em * 3.4);
}

.kalendli-calendar--card .kalendli-calendar__title {
	margin-top: var(--kalendli-gap-sm);
}

.kalendli-calendar--card .kalendli-calendar__summary {
	width: 100%;
}

.kalendli-calendar--card .kalendli-calendar__venue {
	margin-top: auto;
	padding-top: var(--kalendli-gap-md);
	border-top: 1px solid var(--kalendli-rule);
	text-align: left;
	align-self: stretch;
}

.kalendli-calendar--card .kalendli-calendar__action {
	margin-top: 0;
}

/* Full-bleed poster face (card_full_bleed): the tile cover spans the whole
   card — edge to edge, full width and height, no padding — while the text
   floor overlays the poster on a theme-aware scrim (a Canvas mix keeps light
   and dark themes safe). The face grows with long content: the poster ratio
   is a preferred size, never a clipping height. */

.kalendli-calendar--card .kalendli-calendar__item--bleed {
	position: relative;
	gap: 0;
	padding: 0;
	aspect-ratio: 3 / 4;
	justify-content: flex-end;
}

.kalendli-calendar--card .kalendli-calendar__item--bleed .kalendli-calendar__image--tile {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	aspect-ratio: auto;
	z-index: 0;
}

.kalendli-calendar--card .kalendli-calendar__item--bleed > .kalendli-calendar__date,
.kalendli-calendar--card .kalendli-calendar__item--bleed > .kalendli-calendar__summary,
.kalendli-calendar--card .kalendli-calendar__item--bleed > .kalendli-calendar__tags,
.kalendli-calendar--card .kalendli-calendar__item--bleed > .kalendli-calendar__venue,
.kalendli-calendar--card .kalendli-calendar__item--bleed > .kalendli-calendar__action {
	position: relative;
	align-self: stretch;
	margin: 0;
	padding: var(--kalendli-gap-sm) var(--kalendli-gap-md);
	background: Canvas;
	background: color-mix(in srgb, Canvas 82%, transparent);
}

.kalendli-calendar--card .kalendli-calendar__item--bleed .kalendli-calendar__venue {
	border-top: var(--kalendli-rule-hairline) solid var(--kalendli-rule);
	text-align: left;
}

/* == 5. Image modes =======================================================
   Images are punctuation, never structure. Curated crops only: defined
   aspect ratios and object-fit cover keep mixed portrait/landscape sources
   on one disciplined grid. No image, no figure — ever. */

.kalendli-calendar__image {
	margin: 0;
	overflow: hidden;
	background: transparent;
	background: color-mix(in srgb, currentColor 6%, transparent);
}

.kalendli-calendar__image img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Card-tile covers: the poster face of a tile. */
.kalendli-calendar--card .kalendli-calendar__image--tile {
	width: 100%;
	aspect-ratio: 3 / 4;
	margin: 0 0 var(--kalendli-gap-sm);
	align-self: stretch;
}

/* Static lead images in list rows (image_mode "card"): a leading poster
   block at the row's left edge; the row gains a stable image edge. */

.kalendli-calendar__item--with-image {
	grid-template-columns: auto minmax(4.5rem, auto) minmax(0, 1fr) minmax(0, auto);
}

.kalendli-calendar__item--with-image .kalendli-calendar__date {
	min-width: 4.5rem;
}

.kalendli-calendar--image-card .kalendli-calendar__image--card {
	width: clamp(4.5rem, 16vw, 7rem);
	aspect-ratio: 3 / 4;
	align-self: center;
}

/* Inline thumbnails (image_mode "inline"): small square, quiet presence. */

.kalendli-calendar--image-inline .kalendli-calendar__image--inline {
	width: 4rem;
	aspect-ratio: 1 / 1;
	align-self: center;
}

/* Card view overrides the list grid: tiles keep their flex structure, and
   any image mode falls back to tile covers (a cursor-following preview
   makes no sense on a tile). */

.kalendli-calendar--card .kalendli-calendar__item--with-image {
	display: flex;
	grid-template-columns: none;
}

/* Hover previews (image_mode "hover"): rows carry no static image; the
   optional frontend script reveals a poster beside the cursor or the
   focused row. This element is appended to the document body, so it cannot
   rely on the .kalendli-calendar token scope — literal values only. */

.kalendli-calendar__preview {
	position: fixed;
	z-index: 9990;
	width: clamp(9rem, 24vw, 14rem);
	max-width: 60vw;
	margin: 0;
	border: 1px solid currentcolor;
	background: transparent;
	background: color-mix(in srgb, currentcolor 5%, transparent);
	overflow: hidden;
	pointer-events: none;
	opacity: 0;
	visibility: hidden;
}

.kalendli-calendar__preview.is-visible {
	opacity: 1;
	visibility: visible;
}

.kalendli-calendar__preview img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* == 6. Single event interactions ==========================================
   Accordion (single_event_mode "accordion"): rows embed the full event
   detail inside a native <details>/<summary> — opening and closing works
   with no JavaScript at all. Lightbox (single_event_mode "lightbox"): rows
   stretch-link to the canonical event page; JavaScript upgrades that link
   into a modal <dialog> fed from server-rendered templates. Without JS the
   lightbox is simply a normal page link. */

.kalendli-calendar__item--accordion .kalendli-calendar__accordion {
	grid-column: 1 / -1;
	margin-top: var(--kalendli-gap-md);
	border-top: var(--kalendli-rule-hairline) solid var(--kalendli-rule);
}

.kalendli-calendar__accordion-summary {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.35rem 0.75rem;
	padding: var(--kalendli-gap-sm) 0 0;
	cursor: pointer;
	list-style: none; /* remove the default disclosure marker */
}

.kalendli-calendar__accordion-summary::-webkit-details-marker {
	display: none;
}

.kalendli-calendar__accordion-label {
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
	color: var(--kalendli-muted);
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

.kalendli-calendar__accordion-marker::after {
	content: "+";
	font-variant-numeric: tabular-nums;
}

.kalendli-calendar__accordion[open] .kalendli-calendar__accordion-marker::after {
	content: "\2212"; /* minus */
}

.kalendli-calendar__accordion-summary:focus-visible {
	outline: 2px solid var(--kalendli-accent);
	outline-offset: 3px;
}

.kalendli-calendar__accordion-panel {
	padding: var(--kalendli-gap-md) 0 var(--kalendli-gap-sm);
}

.kalendli-calendar__accordion-panel .kalendli-event {
	gap: var(--kalendli-gap-lg);
}

.kalendli-calendar__accordion-page {
	margin: var(--kalendli-gap-md) 0 0;
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
}

.kalendli-calendar__accordion-page a {
	color: inherit;
	text-underline-offset: 0.2em;
	text-decoration-thickness: 1px;
}

/* Card tiles: the accordion spans the full card width below the tile floor. */
.kalendli-calendar--card .kalendli-calendar__item--accordion .kalendli-calendar__accordion {
	width: 100%;
	margin-top: var(--kalendli-gap-sm);
}

/* Lightbox dialog region. Templates render nothing; the dialog is hidden
   until shown. The dialog lives outside the .kalendli-calendar token scope,
   so colors are explicit Canvas/CanvasText (theme-aware in every mode). */

.kalendli-calendar__dialogs {
	display: contents;
}

.kalendli-calendar__dialog {
	position: fixed;
	inset: 0;
	margin: auto;
	z-index: 9999;
	width: min(92vw, 44rem);
	max-width: calc(100vw - 2rem);
	max-height: min(86vh, 60rem);
	padding: 0;
	border: var(--kalendli-rule-structural) solid var(--kalendli-rule-strong);
	background: Canvas;
	color: CanvasText;
	overflow: hidden;
}

.kalendli-calendar__dialog[open] {
	display: grid;
	grid-template-rows: auto minmax(0, 1fr);
}

.kalendli-calendar__dialog::backdrop {
	background: transparent;
	background: color-mix(in srgb, CanvasText 55%, transparent);
}

.kalendli-calendar__dialog-bar {
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: var(--kalendli-gap-md);
	padding: var(--kalendli-gap-md) var(--kalendli-gap-lg);
	border-bottom: var(--kalendli-rule-hairline) solid var(--kalendli-rule);
}

.kalendli-calendar__dialog-title {
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
	color: var(--kalendli-muted);
}

.kalendli-calendar__dialog-close {
	border: 2px solid currentColor;
	border-radius: 999px;
	background: transparent;
	color: inherit;
	font-size: var(--kalendli-text-meta);
	line-height: 1;
	padding: 0.35rem 0.65rem;
	cursor: pointer;
}

.kalendli-calendar__dialog-close:hover,
.kalendli-calendar__dialog-close:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.15em;
	outline: 2px solid currentColor;
	outline-offset: 3px;
}

.kalendli-calendar__dialog-body {
	padding: var(--kalendli-gap-lg);
	overflow-y: auto;
	overscroll-behavior: contain;
}

.kalendli-calendar__dialog-body .kalendli-event {
	gap: var(--kalendli-gap-lg);
}

/* == 7. Empty state =======================================================
   A printed "nothing on this week" line, not an apology. */

/* Opt-in filter bar (spec 08): one server-rendered GET form, no JS. */
.kalendli-filters {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kalendli-gap-sm);
	align-items: flex-end;
	margin: 0 0 var(--kalendli-gap-md);
	font: inherit;
	max-width: 100%;
}
.kalendli-filters__field { display: flex; flex-direction: column; gap: 2px; margin: 0; min-width: 0; max-width: 100%; flex: 1 1 8rem; }
.kalendli-filters__field label { font-size: var(--kalendli-text-micro); text-transform: uppercase; letter-spacing: var(--kalendli-track-caps); }
.kalendli-filters__field select { font: inherit; padding: 2px 4px; min-width: 0; max-width: 100%; width: 100%; }
.kalendli-filters__actions { display: flex; gap: var(--kalendli-gap-sm); align-items: baseline; margin: 0; }
.kalendli-filters__apply { font: inherit; padding: 2px 8px; cursor: pointer; }
.kalendli-filters__apply:focus-visible, .kalendli-filters__reset:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.kalendli-years { margin: 0 0 var(--kalendli-gap-md); font: inherit; }
.kalendli-years__list { display: flex; flex-wrap: wrap; gap: var(--kalendli-gap-sm); margin: 0; padding: 0; list-style: none; }
.kalendli-years__item a { display: inline-block; padding: 1px 6px; border: var(--kalendli-rule-structural) solid var(--kalendli-rule-strong); color: inherit; text-decoration: none; font-size: var(--kalendli-text-micro); }
.kalendli-years__item a:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.kalendli-years__item.is-current a { font-weight: 700; }
/* Self-hosted location map (archive): SVG only, no tiles or remote requests. */
.kalendli-map { margin: 0 0 var(--kalendli-gap-md); }
.kalendli-map__canvas { display: block; width: 100%; height: auto; max-width: 100%; border: var(--kalendli-rule-structural) solid var(--kalendli-rule-strong); }
.kalendli-map__sea { fill: transparent; }
.kalendli-map__graticule { stroke: currentColor; stroke-width: 0.25; opacity: 0.25; }
.kalendli-map__marker { fill: currentColor; }
.kalendli-map__caption { margin: 4px 0; font-size: var(--kalendli-text-micro); text-transform: uppercase; letter-spacing: var(--kalendli-track-caps); }
.kalendli-map__places { display: flex; flex-wrap: wrap; gap: var(--kalendli-gap-sm); margin: 0; padding: 0; list-style: none; font-size: var(--kalendli-text-micro); }
.kalendli-map__place { display: inline-flex; gap: 4px; align-items: baseline; }
.kalendli-map__place a { color: inherit; }
.kalendli-map__place a:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.kalendli-map__count { opacity: 0.7; }
.kalendli-map__groups { display: grid; gap: var(--kalendli-gap-sm); }
.kalendli-map__group { margin: 0; }
.kalendli-map__country { margin: 4px 0; font-size: var(--kalendli-text-micro); text-transform: uppercase; letter-spacing: var(--kalendli-track-caps); }

.kalendli-calendar__empty {
	margin: 0;
	padding: var(--kalendli-gap-lg) 0;
	border-top: var(--kalendli-rule-structural) solid var(--kalendli-rule-strong);
	border-bottom: var(--kalendli-rule-structural) solid var(--kalendli-rule-strong);
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
	color: var(--kalendli-muted);
}

/* == 8. Responsive: recomposition =========================================
   Mobile is not a squeezed desktop grid: the date runs inline at a reduced
   (still poster-forward) scale above the title; lead images go wide, inline
   thumbnails keep a small square beside the content; the place column joins
   the reading flow. */

@media (max-width: 600px) {
	.kalendli-calendar__item {
		grid-template-columns: 1fr;
		row-gap: var(--kalendli-gap-sm);
	}

	.kalendli-calendar__date {
		flex-direction: row;
		flex-wrap: wrap;
		align-items: baseline;
		column-gap: 0.45rem;
		min-width: 0;
	}

	.kalendli-calendar__weekday {
		margin-bottom: 0;
	}

	.kalendli-calendar__month {
		margin-top: 0;
	}

	.kalendli-calendar__day {
		font-size: calc(1em * min(2, var(--kalendli-date-scale)));
	}

	.kalendli-calendar__time {
		margin-top: 0;
	}

	.kalendli-calendar__venue {
		text-align: left;
	}

	/* Compact's dense desktop columns must yield to the same single-column
	   mobile reading flow; its more-specific desktop rule otherwise wins the
	   cascade below 600px and creates horizontal overflow in narrow themes. */
	.kalendli-calendar--compact .kalendli-calendar__item {
		grid-template-columns: 1fr;
	}

	.kalendli-calendar--compact .kalendli-calendar__venue {
		text-align: left;
	}

	.kalendli-calendar--card .kalendli-calendar__items {
		grid-template-columns: 1fr;
	}

	/* Lead images recompose to a wide cover band above the row content. */
	.kalendli-calendar--image-card .kalendli-calendar__item--with-image {
		grid-template-columns: minmax(0, 1fr);
	}

	.kalendli-calendar--image-card .kalendli-calendar__image--card {
		grid-column: 1 / -1;
		width: 100%;
		aspect-ratio: 16 / 9;
		align-self: auto;
	}

	/* Inline thumbnails keep a small square; content flows beside them. */
	.kalendli-calendar--image-inline .kalendli-calendar__item--with-image {
		grid-template-columns: 3.25rem minmax(0, 1fr);
		column-gap: var(--kalendli-gap-sm);
	}

	.kalendli-calendar--image-inline .kalendli-calendar__item--with-image .kalendli-calendar__image--inline {
		grid-row: 1 / span 3;
		width: 100%;
	}

	.kalendli-calendar--image-inline .kalendli-calendar__item--with-image .kalendli-calendar__date,
	.kalendli-calendar--image-inline .kalendli-calendar__item--with-image .kalendli-calendar__summary,
	.kalendli-calendar--image-inline .kalendli-calendar__item--with-image .kalendli-calendar__venue {
		grid-column: 2;
	}
}

/* == 9. Accessibility =====================================================
   Focus is the fourth rule weight: a deliberate outline on every link.
   Reduced motion removes transitions and the hover preview entirely;
   forced-colors mode keeps the status outline legible. */

.kalendli-calendar__title a:focus-visible,
.kalendli-calendar__action a:focus-visible {
	outline: 2px solid var(--kalendli-accent);
	outline-offset: 3px;
}

@media (prefers-reduced-motion: no-preference) {
	.kalendli-calendar__title a,
	.kalendli-calendar__item--linked {
		transition: opacity 120ms ease, background-color 140ms ease, box-shadow 140ms ease;
	}
}

@media (prefers-reduced-motion: reduce) {
	.kalendli-calendar *,
	.kalendli-calendar *::before,
	.kalendli-calendar *::after {
		transition-duration: 0.01ms !important;
	}

	.kalendli-calendar__preview {
		display: none !important;
	}
}

@media (forced-colors: active) {
	.kalendli-calendar__status,
	.kalendli-calendar__sold-out {
		border-color: CanvasText;
	}

	.kalendli-calendar__preview {
		display: none;
	}
}

/* == 10. Event detail (single Event) =========================== */
/* The canonical detail surface (`event_detail` view). Reuses the shared
   date-register classes; every section is optional and omitted when the
   record has no data, so a minimal Event still looks intentional. */

.kalendli-event {
	display: grid;
	gap: 1.5rem;
}

.kalendli-event__header {
	display: grid;
	gap: 0.5rem;
}

.kalendli-event__title {
	margin: 0;
	font-size: clamp(1.75rem, 1.1rem + 2.8vw, 3rem);
	line-height: var(--kalendli-leading-display);
	letter-spacing: -0.02em;
	text-wrap: balance;
	overflow-wrap: anywhere;
}

.kalendli-event__programme {
	margin: 0;
	color: var(--kalendli-muted);
}

.kalendli-event__when {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.35rem 0.75rem;
	margin: 0;
}

.kalendli-event__allday {
	font-size: var(--kalendli-text-meta);
	color: var(--kalendli-muted);
}

.kalendli-calendar__image--hero img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 3 / 2;
	object-fit: cover;
}

.kalendli-event__actions {
	margin: 0;
}

/* The detail banner sits between the hero image and the actions, so it takes
   the wider section rhythm rather than the tight row rhythm. */

.kalendli-event__availability {
	margin: var(--kalendli-gap-md) 0 0;
	font-size: var(--kalendli-text-meta);
}

.kalendli-event__action {
	display: inline-block;
	padding: 0.5rem 1.25rem;
	border: 2px solid currentColor;
	text-decoration: none;
}

.kalendli-event__action:hover,
.kalendli-event__action:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

.kalendli-event__description > :first-child {
	margin-top: 0;
}

.kalendli-event__description > :last-child {
	margin-bottom: 0;
}

.kalendli-event__facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
	gap: 0.75rem 1.5rem;
	margin: 0;
	font-variant-numeric: tabular-nums lining-nums;
}

.kalendli-event__fact dt {
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
	color: var(--kalendli-muted);
}

.kalendli-event__fact dd {
	margin: 0.15rem 0 0;
}

.kalendli-event__location {
	display: grid;
	gap: 0.25rem;
}

.kalendli-event__location p {
	margin: 0;
}

.kalendli-event__website {
	overflow-wrap: anywhere;
}

.kalendli-event__dates-title {
	margin: 0;
	font-size: var(--kalendli-text-micro);
	font-weight: 600;
	letter-spacing: var(--kalendli-track-caps);
	text-transform: uppercase;
	color: var(--kalendli-muted);
}

.kalendli-event__dates {
	list-style: none;
	margin: 0;
	padding: 0;
}

.kalendli-event__date-row {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.35rem 1rem;
	padding: 0.75rem 0;
	border-top: 1px solid currentColor;
}

.kalendli-event__date-row:last-child {
	border-bottom: 1px solid currentColor;
}

.kalendli-event__doors {
	font-size: var(--kalendli-text-meta);
	color: var(--kalendli-muted);
}
