/* KCG theme styles. Tokens come from theme.json; this file holds structure
   that block supports cannot express. Bump KCG_VERSION in functions.php on
   substantive changes so caches pick them up. */

/* ---------------------------------------------------------------- header */

.kcg-header {
	position: sticky;
	top: 0;
	z-index: 100;
	background: var(--wp--preset--color--base);
	border-bottom: 1px solid var(--wp--preset--color--border);
	backdrop-filter: saturate(180%) blur(12px);
}

.kcg-header .wp-block-site-title a {
	text-decoration: none;
	color: var(--wp--preset--color--contrast);
}

.kcg-header .wp-block-navigation a:where(:not(.wp-element-button)) {
	text-decoration: none;
	color: var(--wp--preset--color--contrast);
}

.kcg-header .wp-block-navigation a:where(:not(.wp-element-button)):hover {
	color: var(--wp--preset--color--primary-dark);
}

.kcg-header .wp-block-navigation .wp-block-navigation__submenu-container {
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 0.6rem;
	box-shadow: var(--wp--preset--shadow--card);
	padding-block: 0.4rem;
}

/* Login / rental slot */

.kcg-header__actions {
	display: flex;
	align-items: center;
	gap: 0.75rem;
}

.kcg-login {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.55rem 1.15rem;
	border-radius: 999px;
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
	white-space: nowrap;
	transition: background-color 0.15s ease, color 0.15s ease;
}

.kcg-login:hover,
.kcg-login:focus-visible {
	background: var(--wp--preset--color--primary-dark);
	color: var(--wp--preset--color--base);
}

.kcg-login__icon {
	width: 1.05em;
	height: 1.05em;
	flex: none;
	background-color: currentColor;
	-webkit-mask: var(--kcg-icon-user) center / contain no-repeat;
	mask: var(--kcg-icon-user) center / contain no-repeat;
}

:root {
	--kcg-icon-user: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='12' cy='7' r='4'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------------ hero */

.kcg-hero {
	position: relative;
	min-height: clamp(28rem, 70vh, 44rem);
	display: flex;
	align-items: flex-end;
}

.kcg-hero .wp-block-cover__inner-container {
	padding-bottom: var(--wp--preset--spacing--50);
}

/* --------------------------------------------------------------- section */

.kcg-section {
	scroll-margin-top: 5rem; /* sticky header offset for the #anchor links */
}

.kcg-section__eyebrow {
	text-transform: uppercase;
	letter-spacing: 0.14em;
	font-size: 0.8125rem;
	font-weight: 700;
	color: var(--wp--preset--color--primary-dark);
	margin-bottom: 0.5rem;
}

/* ----------------------------------------------------------------- cards */

.kcg-card {
	position: relative;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 0.9rem;
	overflow: hidden;
	height: 100%;
	transition: transform 0.18s ease, box-shadow 0.18s ease;
}

/* Whole-card click target.

   Note: a stretched ::after on the title does NOT work inside these cards.
   WordPress applies position:relative to the inner constrained group, so an
   absolutely positioned pseudo-element resolves against the text box and stops
   short of the image. Hence a real overlay element, a direct child of the
   card, where the positioning context is ours. */
.kcg-card__overlay {
	position: absolute;
	inset: 0;
	z-index: 1;
	border-radius: inherit;
}

/* Real links stay clickable above the overlay. */
.kcg-card a:not(.kcg-card__overlay) {
	position: relative;
	z-index: 2;
}

/* Query-loop cards (news) get no overlay element — they are core blocks — so
   the title link is stretched instead. Two things have to be neutralised for
   that to reach the card edges:
     1. the inner group, which WordPress gives position:relative
     2. the link itself, which the rule above would otherwise position, making
        its ::after resolve against the text rather than the card
   Both must come after that rule to win on order. */
.kcg-card > .wp-block-group {
	position: static;
}

.kcg-card .wp-block-post-title a {
	position: static;
}

.kcg-card .wp-block-post-title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.kcg-card:hover {
	border-color: var(--wp--preset--color--primary);
}

.kcg-card:focus-within {
	box-shadow: 0 0 0 3px var(--wp--preset--color--primary);
}

.kcg-card:hover {
	transform: translateY(-3px);
	box-shadow: var(--wp--preset--shadow--card);
}

.kcg-card img {
	aspect-ratio: 3 / 2;
	object-fit: cover;
	width: 100%;
}

/* News / query loop */

.kcg-posts .wp-block-post-title {
	font-size: var(--wp--preset--font-size--large);
	margin-block: 0.35em 0.25em;
}

.kcg-posts .wp-block-post-date {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
}

/* --------------------------------------------------------------- content */

.kcg-content :where(img) {
	height: auto;
	border-radius: 0.6rem;
}

.kcg-content :where(table) {
	width: 100%;
	border-collapse: collapse;
}

.kcg-content :where(th, td) {
	border: 1px solid var(--wp--preset--color--border);
	padding: 0.55rem 0.75rem;
	text-align: left;
}

/* Download links replacing the old PDF viewer embeds */

.kcg-file {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.55rem 1rem;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 0.5rem;
	background: var(--wp--preset--color--surface);
	text-decoration: none;
	font-weight: 600;
}

.kcg-file:hover {
	border-color: var(--wp--preset--color--primary);
}

/* ---------------------------------------------------------------- footer */

/* Brand mark */

.kcg-brand {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	text-decoration: none;
	color: var(--wp--preset--color--contrast);
}

.kcg-brand__mark {
	width: auto;
	height: 2.1rem;
	flex: none;
	color: var(--wp--preset--color--primary-dark);
	transition: transform 0.25s ease;
}

.kcg-brand:hover .kcg-brand__mark {
	transform: translateY(-2px) rotate(-4deg);
}

.kcg-brand__text {
	font-weight: 700;
	letter-spacing: -0.01em;
	font-size: 1.05rem;
	white-space: nowrap;
}

/* Footer with a wave contour instead of a straight edge.

   The dark area is made of two pieces: the wave (which reaches up into the
   light content above) and the body below it. The footer element itself has
   no background, otherwise its own straight top edge would show through. */

.kcg-footer {
	background: none;
	color: var(--wp--preset--color--base);
}

/* The wave is the club's own artwork (a breaking wave with a paddler on the
   crest), used as a mask so it takes the footer colour. Tracing it to a path
   was tried first and failed: the crest curls back over itself and the paddle
   is a hairline, neither of which survives a height profile. */
.kcg-footer__wave {
	height: clamp(52px, 8vw, 118px);
	margin-bottom: -1px; /* no hairline between wave and body */
	background: var(--wp--preset--color--contrast);
	-webkit-mask: url("wave.png") no-repeat left bottom / 100% 100%;
	mask: url("wave.png") no-repeat left bottom / 100% 100%;
}

/* The footer group is a flow layout, so blockGap would insert a light strip
   between the wave and the dark body. */
.kcg-footer > * {
	margin-block-start: 0 !important;
}

.kcg-footer__body {
	background: var(--wp--preset--color--contrast);
}

.kcg-footer__brand {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	font-weight: 700;
	font-size: 1.15rem;
	margin-bottom: 0.75rem;
}

.kcg-footer__brand .kcg-brand__mark {
	height: 2.4rem;
	color: var(--wp--preset--color--primary);
}

.kcg-footer__legal {
	margin-top: 2rem;
	padding-top: 1rem;
	border-top: 1px solid rgba(255, 255, 255, 0.14);
	font-size: 0.85rem;
}

.kcg-footer__legal p {
	margin: 0;
}

.kcg-footer a {
	color: var(--wp--preset--color--base);
	text-decoration: none;
}

.kcg-footer a:hover {
	color: var(--wp--preset--color--primary);
}

.kcg-sponsors {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: clamp(1.5rem, 4vw, 3.5rem);
}

/* Sponsors keep their own colours — desaturating a partner's logo is both
   unfriendly and, with these light detailed marks, simply harder to read. */
.kcg-sponsors img {
	max-height: 3.5rem;
	max-width: 11rem;
	width: auto;
	object-fit: contain;
	transition: transform 0.2s ease;
}

.kcg-sponsors a {
	display: grid;
	place-items: center;
	padding: 0.5rem 0.75rem;
	min-height: 4.5rem;
}

.kcg-sponsors img:hover {
	transform: scale(1.04);
}

/* --------------------------------------------------------------- a11y/UX */

@media (prefers-reduced-motion: reduce) {
	* {
		animation-duration: 0.01ms !important;
		transition-duration: 0.01ms !important;
	}
}

:where(a):focus-visible,
:where(button):focus-visible {
	outline: 2px solid var(--wp--preset--color--primary-dark);
	outline-offset: 2px;
}

/* ------------------------------------------------------ homepage bits */

.kcg-hero .wp-block-cover__inner-container {
	max-width: 1240px;
	margin-inline: auto;
	width: 100%;
	padding-inline: var(--wp--preset--spacing--40);
}

.kcg-hero h1 {
	margin-bottom: 0.35em;
	text-wrap: balance;
}

.kcg-grid,
.kcg-stats,
.kcg-funcs {
	gap: 1.5rem;
}

/* WordPress lays these grids out with auto-fill, which keeps empty tracks:
   three news posts in a container wide enough for four leave a hole on the
   right and the row reads as left-aligned. auto-fit collapses the empty track
   so the items share the full width. */
.kcg-posts .wp-block-post-template {
	grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
}

/* Card grids: tracks have a fixed maximum rather than 1fr, so leftover space
   collects at the edges and justify-content can centre them. That also centres
   a partly filled last row — 5 services across 4 columns no longer leaves a
   lone card hugging the left.

   --kcg-col is tuned per section so the item count divides evenly at desktop
   width; below that the tracks simply reflow. */
.kcg-grid.wp-block-group.is-layout-grid {
	grid-template-columns: repeat(auto-fit, minmax(min(var(--kcg-col, 16rem), 100%), var(--kcg-col-max, 18rem)));
	justify-content: center;
}

/* 5 services → 5 across */
#services .kcg-grid.is-layout-grid {
	--kcg-col: 12.5rem;
	--kcg-col-max: 14rem;
}

/* 6 trainings and 6 board members → 3 across, 2 rows */
#training .kcg-grid.is-layout-grid,
#team .kcg-grid.is-layout-grid {
	--kcg-col: 19rem;
	--kcg-col-max: 24rem;
}

/* 14 athletes → 5 across, last row centred */
#athletes .kcg-grid.is-layout-grid {
	--kcg-col: 12rem;
	--kcg-col-max: 14rem;
}

/* 7 galleries → 4 across, last row of 3 centred */
#galerie .kcg-grid.is-layout-grid {
	--kcg-col: 15rem;
	--kcg-col-max: 17.5rem;
}

/* Card links inherit the heading colour; the whole card lifts on hover. */
.kcg-card h3 a {
	color: inherit;
	text-decoration: none;
}

.kcg-card h3 a:hover {
	color: var(--wp--preset--color--primary-dark);
}

.kcg-card :where(figure) {
	margin: 0;
}

.kcg-card :where(figure) img {
	display: block;
	width: 100%;
}

/* Stand-in for cards whose page has no featured image */
.kcg-card__placeholder {
	aspect-ratio: 4 / 3;
	background:
		radial-gradient(circle at 30% 30%, rgba(3, 196, 235, 0.18), transparent 60%),
		repeating-linear-gradient(45deg, #eef5f9, #eef5f9 12px, #e6eff5 12px, #e6eff5 24px);
}

/* Board member cards: centred text, mail as a badge in the corner */

.kcg-person {
	display: flex;
	flex-direction: column;
	text-align: center;
}

.kcg-person__photo {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
}

.kcg-person__body {
	padding: 0.9rem 1rem 1.1rem;
	flex: 1;
}

.kcg-person__name {
	margin: 0;
	font-size: 1.05rem;
	line-height: 1.25;
}

.kcg-person__name a {
	color: inherit;
	text-decoration: none;
}

.kcg-person .kcg-role {
	margin: 0.2rem 0 0;
}

/* Sits above the card overlay so it stays independently clickable.
   Selector needs the `a` to outrank `.kcg-card a:not(.kcg-card__overlay)`
   above, which would otherwise force position:relative and drop the badge
   back into the flow. */
.kcg-card a.kcg-person__mail {
	position: absolute;
	top: 0.6rem;
	right: 0.6rem;
	z-index: 3;
	display: grid;
	place-items: center;
	width: 2.1rem;
	height: 2.1rem;
	border-radius: 50%;
	background: var(--kcg-chip);
	color: var(--wp--preset--color--contrast);
	box-shadow: 0 2px 8px rgba(20, 35, 43, 0.22);
	backdrop-filter: blur(4px);
	transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

.kcg-person__mail svg {
	width: 1.05rem;
	height: 1.05rem;
}

.kcg-person__mail:hover,
.kcg-person__mail:focus-visible {
	background: var(--wp--preset--color--primary);
	color: var(--kcg-on-accent);
	transform: scale(1.08);
}

/* Sponsor grid on the Partner page */

.kcg-sponsorgrid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 15rem));
	justify-content: center;
	gap: 1.25rem;
	margin-block: 2rem;
}

.kcg-sponsor {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.75rem;
	padding: 1.25rem 1rem;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 0.7rem;
	background: #fff;
	text-decoration: none;
	color: inherit;
	min-height: 9rem;
	transition: border-color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}

.kcg-sponsor:hover {
	border-color: var(--wp--preset--color--primary);
	transform: translateY(-2px);
	box-shadow: var(--wp--preset--shadow--card);
}

.kcg-sponsor img {
	max-height: 3.5rem;
	max-width: 100%;
	width: auto;
	object-fit: contain;
}

.kcg-sponsor__name {
	font-size: 0.85rem;
	font-weight: 600;
	text-align: center;
	color: var(--wp--preset--color--muted);
}

/* Profile index on "Athleten und Team" */

.kcg-people {
	--kcg-col: 14rem;
	--kcg-col-max: 17rem;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(var(--kcg-col), 100%), var(--kcg-col-max)));
	justify-content: center;
	gap: 1.5rem;
	margin-block: 2rem;
}

.kcg-person--wide .kcg-person__body {
	padding: 0.85rem 1rem 1.1rem;
}

.kcg-person__blurb {
	margin: 0.4rem 0 0;
	font-size: 0.88rem;
	line-height: 1.45;
	color: var(--wp--preset--color--muted);
	text-align: left;
}

/* Role / discipline line under a name */

.kcg-role {
	margin-block: 0.15rem 0.4rem;
	font-size: 0.9rem;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--wp--preset--color--primary-dark);
}

/* Counter */

/* Full-bleed sections butt against each other and against the header; each
   carries its own padding, so the theme's blockGap only adds stray white
   stripes between them. */
.home main,
.home .kcg-content > * {
	margin-block-start: 0 !important;
}

.kcg-stats {
	gap: clamp(2rem, 6vw, 5rem);
}

.kcg-stat {
	text-align: center;
	min-width: 8rem;
}

.kcg-stat__num {
	margin: 0;
	font-size: clamp(2.5rem, 5vw, 3.5rem);
	font-weight: 800;
	line-height: 1.05;
	letter-spacing: -0.03em;
	color: var(--wp--preset--color--primary-dark);
	font-variant-numeric: tabular-nums;
}

.kcg-stat__label {
	margin: 0.25rem 0 0;
	font-size: 0.95rem;
	color: var(--wp--preset--color--muted);
}

/* Functionaries list */

.kcg-funcs {
	gap: 1rem;
}

.kcg-func {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	padding: 0.9rem 1rem;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-left: 3px solid var(--wp--preset--color--primary);
	border-radius: 0.6rem;
	transition: box-shadow 0.18s ease, transform 0.18s ease;
}

.kcg-func:hover {
	transform: translateY(-2px);
	box-shadow: var(--wp--preset--shadow--card);
}

.kcg-func p {
	margin: 0;
}

.kcg-func__role {
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.07em;
	color: var(--wp--preset--color--primary-dark);
}

.kcg-func__name {
	font-size: 1rem;
	font-weight: 600;
	line-height: 1.3;
}

.kcg-func__mail {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	margin-top: 0.35rem;
	font-size: 0.82rem;
	color: var(--wp--preset--color--muted);
	text-decoration: none;
	word-break: break-all;
}

.kcg-func__mail svg {
	width: 0.9rem;
	height: 0.9rem;
	flex: none;
}

.kcg-func__mail:hover {
	color: var(--wp--preset--color--primary-dark);
	text-decoration: underline;
}

.kcg-funcs {
	column-gap: 3rem;
}

/* Section rhythm */

.kcg-section > :where(h2) {
	margin-bottom: 0.4em;
}

.kcg-section > :where(h2) + p {
	margin-top: 0;
	margin-bottom: 2.5rem;
}

.kcg-section > :where(h2):last-of-type + .wp-block-group,
.kcg-section > :where(h2) + .wp-block-group {
	margin-top: 2rem;
}

/* ============================================================== content
   Components for pages that carried Bootstrap markup on the old site.
   Bootstrap is gone, so anything relying on .row, .col-xx, .panel or .tab-pane
   had lost its layout — these replace it with plain CSS.
   ---------------------------------------------------------------- */

/* Responsive embeds (maps, videos).
   The old markup hard-coded width="750" height="600", which overflows on a
   phone. An aspect-ratio box keeps the frame proportional at any width. */

.kcg-embed {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: 0.75rem;
	overflow: hidden;
	border: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--surface);
}

.kcg-embed--map {
	aspect-ratio: 4 / 3;
}

.kcg-embed > iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
}

@media (max-width: 600px) {
	.kcg-embed--map {
		aspect-ratio: 3 / 4;
	}
}

/* A row of embeds side by side. */

.kcg-embedgrid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
	gap: 1.25rem;
}

.kcg-embedgrid .wp-block-embed,
.kcg-embedgrid figure {
	margin: 0;
}

/* Download links, laid out as a wrapping row of pills rather than the bare
   anchors the old pages had (which ran together on one line). */

.kcg-filelist {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	margin: 1rem 0 1.75rem;
	padding: 0;
	list-style: none;
}

.kcg-filelist li {
	margin: 0;
}

.kcg-file__icon {
	flex: none;
	width: 1.05rem;
	height: 1.05rem;
	color: var(--wp--preset--color--primary);
}

/* Data tables in page content. */

.kcg-dtable {
	width: 100%;
	border-collapse: collapse;
	margin: 0 0 1.25rem;
	font-size: 0.95rem;
	background: var(--wp--preset--color--base);
	border-radius: 0.75rem;
	overflow: hidden;
	box-shadow: 0 0 0 1px var(--wp--preset--color--border);
}

.kcg-dtable caption {
	caption-side: top;
	text-align: left;
	font-weight: 700;
	padding: 0 0 0.5rem;
}

.kcg-dtable th,
.kcg-dtable td {
	padding: 0.6rem 0.9rem;
	text-align: left;
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.kcg-dtable thead th {
	background: var(--wp--preset--color--primary);
	color: #fff;
	font-weight: 600;
	border-bottom: 0;
	white-space: nowrap;
}

.kcg-dtable tbody tr:nth-child(even) {
	background: var(--wp--preset--color--surface);
}

.kcg-dtable tbody tr:last-child td {
	border-bottom: 0;
}

/* Water levels: grey = low, green = ideal, red = high. */

.kcg-lvl--low   { color: #6b7280; }
.kcg-lvl--mid   { color: #2e8540; font-weight: 600; }
.kcg-lvl--high  { color: #c02626; }

.kcg-tablewrap--content {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

/* --------------------------------------------------------- CSS-only tabs

   The old page used Bootstrap pills, which need Bootstrap's JavaScript. This
   is the same idea with radio inputs, so it works with no script at all: the
   checked input selects its panel through a sibling selector. Supports up to
   six tabs, which is all any page here needs.                             */

.kcg-ctabs {
	margin: 1.5rem 0 2rem;
}

.kcg-ctabs > input {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

.kcg-ctabs__nav {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin-bottom: 1.25rem;
	border-bottom: 1px solid var(--wp--preset--color--border);
	padding-bottom: 0.6rem;
}

.kcg-ctabs__nav label {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.5rem 1.05rem;
	border-radius: 999px;
	border: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--surface);
	font-weight: 600;
	line-height: 1.2;
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
	user-select: none;
}

.kcg-ctabs__nav label:hover {
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--primary-dark);
}

.kcg-ctabs__panels > .kcg-ctab {
	display: none;
}

/* One rule per index: the nth input selects the nth label and nth panel. */

.kcg-ctabs > input:nth-of-type(1):checked ~ .kcg-ctabs__panels > .kcg-ctab:nth-child(1),
.kcg-ctabs > input:nth-of-type(2):checked ~ .kcg-ctabs__panels > .kcg-ctab:nth-child(2),
.kcg-ctabs > input:nth-of-type(3):checked ~ .kcg-ctabs__panels > .kcg-ctab:nth-child(3),
.kcg-ctabs > input:nth-of-type(4):checked ~ .kcg-ctabs__panels > .kcg-ctab:nth-child(4),
.kcg-ctabs > input:nth-of-type(5):checked ~ .kcg-ctabs__panels > .kcg-ctab:nth-child(5),
.kcg-ctabs > input:nth-of-type(6):checked ~ .kcg-ctabs__panels > .kcg-ctab:nth-child(6) {
	display: block;
}

.kcg-ctabs > input:nth-of-type(1):checked ~ .kcg-ctabs__nav label:nth-child(1),
.kcg-ctabs > input:nth-of-type(2):checked ~ .kcg-ctabs__nav label:nth-child(2),
.kcg-ctabs > input:nth-of-type(3):checked ~ .kcg-ctabs__nav label:nth-child(3),
.kcg-ctabs > input:nth-of-type(4):checked ~ .kcg-ctabs__nav label:nth-child(4),
.kcg-ctabs > input:nth-of-type(5):checked ~ .kcg-ctabs__nav label:nth-child(5),
.kcg-ctabs > input:nth-of-type(6):checked ~ .kcg-ctabs__nav label:nth-child(6) {
	background: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
	color: #fff;
}

/* Keyboard users: the input keeps the focus ring, drawn on its label. */

.kcg-ctabs > input:nth-of-type(1):focus-visible ~ .kcg-ctabs__nav label:nth-child(1),
.kcg-ctabs > input:nth-of-type(2):focus-visible ~ .kcg-ctabs__nav label:nth-child(2),
.kcg-ctabs > input:nth-of-type(3):focus-visible ~ .kcg-ctabs__nav label:nth-child(3),
.kcg-ctabs > input:nth-of-type(4):focus-visible ~ .kcg-ctabs__nav label:nth-child(4),
.kcg-ctabs > input:nth-of-type(5):focus-visible ~ .kcg-ctabs__nav label:nth-child(5),
.kcg-ctabs > input:nth-of-type(6):focus-visible ~ .kcg-ctabs__nav label:nth-child(6) {
	outline: 2px solid var(--wp--preset--color--primary-dark);
	outline-offset: 2px;
}

/* Where a page prints nothing but tabs, print every panel. */

@media print {
	.kcg-ctabs__nav { display: none; }
	.kcg-ctabs__panels > .kcg-ctab { display: block !important; }
}

/* An image that links somewhere, with a caption bar over it. */

.kcg-figlink {
	display: block;
	position: relative;
	max-width: 40rem;
	margin: 1.5rem auto;
	border-radius: 0.75rem;
	overflow: hidden;
	text-decoration: none;
	box-shadow: 0 0 0 1px var(--wp--preset--color--border);
}

.kcg-figlink img {
	display: block;
	width: 100%;
	height: auto;
	transition: transform 0.35s ease;
}

.kcg-figlink:hover img,
.kcg-figlink:focus-visible img {
	transform: scale(1.03);
}

.kcg-figlink__label {
	position: absolute;
	inset: auto 0 0 0;
	padding: 0.7rem 1rem;
	background: linear-gradient(to top, rgba(0, 0, 0, 0.72), rgba(0, 0, 0, 0));
	color: #fff;
	font-weight: 600;
}

/* A short note under a chart or table. */

.kcg-note {
	margin: 0.35rem 0 1.5rem;
	font-size: 0.9rem;
	color: var(--wp--preset--color--muted, #5b6670);
}

.kcg-note--center {
	text-align: center;
}

/* ----------------------------------------------------- membership form */

.kcg-form {
	max-width: 44rem;
	margin: 1.5rem 0 0;
}

.kcg-form__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
	gap: 1rem;
}

.kcg-form__field {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
}

.kcg-form__field--wide {
	grid-column: 1 / -1;
}

.kcg-form label {
	font-weight: 600;
	font-size: 0.92rem;
}

.kcg-form .kcg-req {
	color: #c02626;
}

.kcg-form input[type="text"],
.kcg-form input[type="email"],
.kcg-form input[type="tel"],
.kcg-form input[type="date"] {
	width: 100%;
	padding: 0.6rem 0.75rem;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 0.5rem;
	background: var(--wp--preset--color--base);
	font: inherit;
	color: inherit;
}

.kcg-form input:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 1px;
	border-color: var(--wp--preset--color--primary);
}

.kcg-form__check {
	display: flex;
	gap: 0.6rem;
	align-items: flex-start;
	margin-top: 1rem;
	font-size: 0.92rem;
	line-height: 1.45;
}

.kcg-form__check input {
	margin-top: 0.2rem;
	flex: none;
	width: 1.05rem;
	height: 1.05rem;
	accent-color: var(--wp--preset--color--primary);
}

.kcg-form__actions {
	margin-top: 1.5rem;
}

.kcg-form__hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.kcg-notice {
	padding: 0.9rem 1.1rem;
	border-radius: 0.6rem;
	border: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--surface);
	margin: 1rem 0;
}

.kcg-notice--error {
	border-color: #e6b3b3;
	background: #fdf3f3;
	color: #8a1f1f;
}

.kcg-notice--success {
	border-color: #b6ddc0;
	background: #f2fbf4;
	color: #17632f;
}

.kcg-notice ul {
	margin: 0.4rem 0 0 1.1rem;
	padding: 0;
}

/* Icons for download and gallery links. Drawn with a mask so the glyph takes
   the link's own colour and follows the hover state. */

.kcg-file--pdf::before,
.kcg-file--photo::before {
	content: "";
	flex: none;
	width: 1.1rem;
	height: 1.1rem;
	background: var(--wp--preset--color--primary);
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
}

.kcg-file--pdf::before {
	-webkit-mask-image: var(--kcg-icon-pdf);
	mask-image: var(--kcg-icon-pdf);
}

.kcg-file--photo::before {
	-webkit-mask-image: var(--kcg-icon-photo);
	mask-image: var(--kcg-icon-photo);
}

:root {
	--kcg-icon-pdf: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpath d='M14 2v6h6'/%3E%3Cpath d='M12 18v-6'/%3E%3Cpath d='m9 15 3 3 3-3'/%3E%3C/svg%3E");
	--kcg-icon-photo: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='18' height='18' rx='2'/%3E%3Ccircle cx='9' cy='9' r='2'/%3E%3Cpath d='m21 15-4.35-4.35a2 2 0 0 0-2.83 0L6 18'/%3E%3C/svg%3E");
}

/* An image inside a raw-HTML block does not get core's block styles, so it
   keeps its intrinsic width and pushes the page sideways. Constrain the ones
   in the components above ourselves. */

.kcg-ctab img,
.kcg-embedgrid img,
.kcg-figlink img,
.kcg-notice img {
	max-width: 100%;
	height: auto;
}

.kcg-ctab figure {
	margin: 1.25rem 0;
	text-align: center;
}

/* Size a linked figure to its image rather than stretching a small file to
   the full column, which only makes it soft. */

.kcg-figlink {
	width: fit-content;
}

.kcg-figlink--tall {
	max-width: 26rem;
}

/* Without this an input is 100% of its cell *plus* its padding and border,
   so every field in the right-hand column hangs over the edge. */

.kcg-form input,
.kcg-form select,
.kcg-form textarea {
	box-sizing: border-box;
}

/* Classic (non-block) content keeps plain <img> tags, which core styles only
   inside a block wrapper. Without this a wide photo pushes the whole page
   sideways on anything narrower than the image. */

.kcg-content img {
	max-width: 100%;
	height: auto;
}

/* An auto-embedded video in classic content is a bare iframe with the
   provider's own width="500". Let it fill its column and keep 16:9. */

.kcg-embedgrid {
	grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
	align-items: start;
}

.kcg-embedgrid iframe {
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	border: 0;
	border-radius: 0.75rem;
	display: block;
}

.kcg-embedgrid p {
	margin: 0;
}

/* ------------------------------------------------------------- card text

   Cards sit in a grid, so every tile in a row is drawn as tall as the
   tallest one. A single long description therefore left a band of empty
   space in all its neighbours. Clamping the text to three lines — and
   reserving those three lines whether or not they are used — gives every
   tile the same height, so nothing has to stretch to match. */

.kcg-card__text {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
	line-height: 1.5;
	min-height: calc(3 * 1.5 * 0.95rem);
	margin-bottom: 0;
}

/* The picture, the heading and the text are all fixed, so the body no longer
   needs to grow: pin it to the top of the card instead of centring the gap. */

.kcg-card > .wp-block-group:not(.kcg-card__placeholder) {
	align-self: start;
}

/* News covers are supplied as 270x135 strips — a shape the club produced for
   the old theme's small thumbnails. Cropping one into the 3:2 box the other
   cards use scales it to nearly twice its size, which is what makes it look
   washed out. 16:9 is close to the shape the files actually have and takes a
   third off that magnification. Other cards keep 3:2: their pictures are
   full-size photographs. */

.kcg-posts .kcg-card img {
	aspect-ratio: 16 / 9;
}

/* News cards sit in the same kind of grid, so give their excerpt the same
   fixed three lines the service cards have. */

.kcg-posts .wp-block-post-excerpt__excerpt {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
	line-height: 1.5;
	min-height: calc(3 * 1.5 * 1em);
}

.kcg-posts .wp-block-post-excerpt {
	margin-bottom: 0.75rem;
}

/* A heading that wraps to two lines made its whole row of tiles taller than
   the rest. Reserve two lines for every card title, and cut anything longer,
   so the tiles keep the same shape whatever the wording. */

.kcg-card__title,
.kcg-posts .wp-block-post-title {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
	line-height: 1.3;
	min-height: calc(2 * 1.3em);
}

/* ------------------------------------------------------- membership CTA

   The old markup was a <form> whose submit button carried inline colours:
   slate grey text on a yellow rectangle, at whatever size the browser draws
   a default button. Nothing else on the site is yellow, so it read as a
   stray element rather than as the page's main action.

   This is the one button that should stop the eye, so it is larger than a
   normal one and carries the club blue, with an arrow that slides on hover. */

.kcg-cta .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	padding: 1rem 2.5rem;
	font-size: 1.1rem;
	font-weight: 700;
	border-radius: 999px;
	background: linear-gradient(135deg,
		var(--wp--preset--color--primary, #03c4eb),
		var(--wp--preset--color--primary-dark, #0284a8));
	color: #fff;
	box-shadow: 0 8px 20px rgba(2, 132, 168, 0.28);
	transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease;
}

.kcg-cta .wp-block-button__link::after {
	content: "→";
	font-size: 1.15em;
	line-height: 1;
	transition: transform 0.18s ease;
}

.kcg-cta .wp-block-button__link:hover,
.kcg-cta .wp-block-button__link:focus-visible {
	color: #fff;
	filter: brightness(1.06);
	transform: translateY(-2px);
	box-shadow: 0 12px 26px rgba(2, 132, 168, 0.36);
}

.kcg-cta .wp-block-button__link:hover::after,
.kcg-cta .wp-block-button__link:focus-visible::after {
	transform: translateX(3px);
}

.kcg-cta {
	margin-block: 2rem;
}

@media (prefers-reduced-motion: reduce) {
	.kcg-cta .wp-block-button__link,
	.kcg-cta .wp-block-button__link::after {
		transition: none;
	}
}

/* Classic content stacks images with no gap — two photos one under the other
   touch. The theme spaces blocks, but a bare <img> in classic markup is not a
   block, so give those their own rhythm. */

.kcg-content img.aligncenter,
.kcg-content img.alignnone {
	display: block;
	margin-inline: auto;
	margin-block: 1.25rem;
}

/* A floated photo needs air between itself and the text it sits beside, and
   the paragraph after a float must not wrap around the next section. */

.kcg-content img.alignleft {
	float: left;
	margin: 0.35rem 1.5rem 1rem 0;
}

.kcg-content img.alignright {
	float: right;
	margin: 0.35rem 0 1rem 1.5rem;
}

.kcg-content h2,
.kcg-content h3 {
	clear: both;
}

@media (max-width: 600px) {
	.kcg-content img.alignleft,
	.kcg-content img.alignright {
		float: none;
		display: block;
		margin: 1.25rem auto;
	}
}

/* A card that is itself a link: without this the heading and the description
   inside it inherit link colour and underline, so the whole tile reads as one
   long blue hyperlink instead of a title with text under it. */

a.kcg-card {
	display: block;
	text-decoration: none;
	color: inherit;
}

a.kcg-card h2,
a.kcg-card h3,
a.kcg-card h4 {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	transition: color 0.15s ease;
}

a.kcg-card p,
a.kcg-card li,
a.kcg-card span {
	color: var(--wp--preset--color--muted);
	text-decoration: none;
}

a.kcg-card:hover h2,
a.kcg-card:hover h3,
a.kcg-card:hover h4,
a.kcg-card:focus-visible h2,
a.kcg-card:focus-visible h3,
a.kcg-card:focus-visible h4 {
	color: var(--wp--preset--color--primary-dark);
}

a.kcg-card:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary-dark);
	outline-offset: 3px;
}

/* ---------------------------------------------------------- social links

   One shortcode feeds two shapes: a plain list in the footer column and a
   row of badges over the hero image. */

.kcg-social {
	list-style: none;
	margin: 0;
	padding: 0;
}

.kcg-social__link {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	text-decoration: none;
}

.kcg-social__icon {
	flex: none;
	width: 1.15rem;
	height: 1.15rem;
}

/* Footer: keeps the wording that was there, with the mark in front of it. */

.kcg-social--list {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	margin-top: 0.35rem;
	font-size: 0.95rem;
}

.kcg-social--list .kcg-social__link {
	color: inherit;
	opacity: 0.92;
	transition: opacity 0.15s ease, color 0.15s ease;
}

.kcg-social--list .kcg-social__link:hover,
.kcg-social--list .kcg-social__link:focus-visible {
	opacity: 1;
	color: var(--wp--preset--color--primary);
}

/* Hero: a pill that reads over a photograph without hiding it. The blur is
   a nicety — where it is unsupported the flat tint alone is enough. */

.kcg-social--badges {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	margin-top: 1.5rem;
}

.kcg-social--badges .kcg-social__link {
	padding: 0.45rem 0.95rem;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.14);
	border: 1px solid rgba(255, 255, 255, 0.35);
	color: #fff;
	font-size: 0.88rem;
	font-weight: 600;
	line-height: 1;
	backdrop-filter: blur(6px);
	transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}

.kcg-social--badges .kcg-social__link:hover,
.kcg-social--badges .kcg-social__link:focus-visible {
	background: rgba(255, 255, 255, 0.26);
	border-color: rgba(255, 255, 255, 0.65);
	color: #fff;
	transform: translateY(-2px);
}

.kcg-social--badges .kcg-social__icon {
	width: 1.05rem;
	height: 1.05rem;
}

@media (prefers-reduced-motion: reduce) {
	.kcg-social__link {
		transition: none;
	}
}

/* On a narrow screen the pair is about a dozen pixels too wide for one line,
   so it wrapped into two stacked pills. A slightly tighter badge keeps them
   side by side. */

@media (max-width: 420px) {
	.kcg-social--badges {
		gap: 0.45rem;
	}

	.kcg-social--badges .kcg-social__link {
		padding: 0.4rem 0.7rem;
		font-size: 0.8rem;
		gap: 0.4rem;
	}

	.kcg-social--badges .kcg-social__icon {
		width: 0.95rem;
		height: 0.95rem;
	}
}

/* The header slides out of the way on the way down and returns on the way
   up. It keeps its place in the flow, so nothing jumps when it moves. */

.kcg-header {
	transition: transform 0.28s ease, box-shadow 0.2s ease;
	will-change: transform;
}

.kcg-header.is-hidden {
	transform: translateY(-100%);
}

/* Once the page has moved at all, lift the bar off the content. */

.kcg-header.is-stuck {
	box-shadow: 0 2px 14px rgba(20, 35, 43, 0.09);
}

/* An anchor target must clear the bar when it slides back in. */

:target,
[id^="kcg-"],
.kcg-section {
	scroll-margin-top: 5.5rem;
}

@media (prefers-reduced-motion: reduce) {
	.kcg-header {
		transition: none;
	}
}

/* Sticky applies to the element itself, and the element only stays put while
   its parent is on screen. The bar lives inside the template part's <header>,
   which is a couple of hundred pixels tall — so pinning the inner div meant
   it unpinned again after that much scrolling. The outer element is the one
   that has to stick. */

.wp-site-blocks > header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 100;
	transition: transform 0.28s ease;
	will-change: transform;
}

.wp-site-blocks > header.wp-block-template-part.is-hidden {
	transform: translateY(-100%);
}

.wp-site-blocks > header.wp-block-template-part.is-stuck .kcg-header {
	box-shadow: 0 2px 14px rgba(20, 35, 43, 0.09);
}

@media (prefers-reduced-motion: reduce) {
	.wp-site-blocks > header.wp-block-template-part {
		transition: none;
	}
}

/* A heading normally clears a floated image so a new section starts on a
   fresh line. The exception is a heading that *belongs* to the picture next
   to it — image left, title and text to its right — which is the shape the
   training pages use. Without this the first such block dropped its heading
   below the photo while the next kept it alongside. */

.kcg-content img.alignleft + h2,
.kcg-content img.alignright + h2,
.kcg-content img.alignleft + h3,
.kcg-content img.alignright + h3,
.kcg-content a + h2,
.kcg-content a + h3 {
	clear: none;
}

/* ------------------------------------------------- room for the admin bar

   For a logged-in editor WordPress fixes its toolbar across the top of the
   window at a z-index far above anything a theme sets, so a header stuck at
   top:0 spends its first 32 or 46 pixels underneath it. WordPress publishes
   the toolbar's height as a custom property, which also tracks its own
   breakpoint — 32px on a wide screen, 46px on a narrow one. */

body.admin-bar .wp-site-blocks > header.wp-block-template-part {
	top: var(--wp-admin--admin-bar--height, 0px);
}

body.admin-bar :target,
body.admin-bar .kcg-section {
	scroll-margin-top: calc(5.5rem + var(--wp-admin--admin-bar--height, 0px));
}

/* Below 601px the toolbar becomes position:absolute and scrolls away with
   the page, so the header goes back to the very top of the window. */

@media screen and (max-width: 600px) {
	body.admin-bar .wp-site-blocks > header.wp-block-template-part {
		top: 0;
	}

	body.admin-bar :target,
	body.admin-bar .kcg-section {
		scroll-margin-top: 5.5rem;
	}
}

/* ================================================================ square

   Corners everywhere are square. The radius is set in dozens of places —
   theme.json presets, block styles, the plugin's own components — so rather
   than hunt each one down, everything is squared off and only the few round
   shapes that are meant to be round are exempted: the avatar in the header
   menu, the status dots, and the toggle switches in the member table. */

*,
*::before,
*::after {
	border-radius: 0;
}

.kcg-usermenu__avatar,
.kcg-tab__dot,
.kcg-switch,
.kcg-switch::after,
.kcg-switch span,
.kcg-status,
.kcg-tag,
.kcg-badge,
.kcg-social--badges .kcg-social__link,
.wp-block-avatar img,
.kcg-func::before {
	border-radius: 999px;
}

/* ------------------------------------------------------------- counters */

.kcg-stat__num {
	font-weight: 400;
}

.kcg-stat__label {
	font-size: 1rem;
}

/* --------------------------------------------------------- news as a list

   The old site listed the news rather than tiling it: a row per post with a
   rule between, which reads faster than three boxes. */

.kcg-posts .wp-block-post-template {
	display: block;
}

.kcg-newsitem {
	display: grid;
	grid-template-columns: minmax(0, 15rem) 1fr;
	gap: 1.5rem;
	align-items: start;
	padding: 1.75rem 0;
	border-bottom: 1px solid var(--wp--preset--color--border);
	transition: background 0.15s ease;
}

.kcg-newsitem:first-child {
	border-top: 1px solid var(--wp--preset--color--border);
}

/* The whole row reacts, so it is clear the item can be opened even without
   a "read more" link at the end of it. */

.kcg-newsitem:hover {
	background: var(--wp--preset--color--surface);
}

.kcg-newsitem:hover .wp-block-post-title a {
	color: var(--wp--preset--color--primary-dark);
}

.kcg-newsitem .wp-block-post-featured-image {
	margin: 0;
}

.kcg-newsitem .wp-block-post-featured-image img {
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	display: block;
}

.kcg-newsitem .wp-block-post-date {
	font-size: 0.85rem;
	color: var(--wp--preset--color--muted);
	margin: 0 0 0.25rem;
}

.kcg-newsitem .wp-block-post-title {
	margin: 0 0 0.5rem;
}

.kcg-newsitem .wp-block-post-excerpt {
	margin: 0;
}

.kcg-newsitem .wp-block-post-excerpt__excerpt {
	color: var(--wp--preset--color--muted);
	min-height: 0;
}

/* Nothing to hide if the block emits no more-link, but belt and braces. */

.kcg-newsitem .wp-block-post-excerpt__more-text {
	display: none;
}

@media (max-width: 600px) {
	.kcg-newsitem {
		grid-template-columns: 1fr;
		gap: 0.85rem;
	}
}

/* -------------------------------------------------- grids that stay even

   auto-fit fills the row, so five cards at four columns leave one alone on
   the left. Capping the count keeps the split at 3 + 2. */

.kcg-grid--balanced {
	justify-content: center;
}

@media (min-width: 900px) {
	.kcg-grid--balanced {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* The universal selector carries no specificity, so every rule with a class
   in it — and there are many, from theme.json, the block library and this
   file — beat it. Squaring the corners is a deliberate override of all of
   them, which is what !important is for. The exceptions carry it too, and
   win on specificity. */

*,
*::before,
*::after {
	border-radius: 0 !important;
}

.kcg-usermenu__avatar,
.kcg-tab__dot,
.kcg-switch,
.kcg-switch::after,
.kcg-switch span,
.kcg-status,
.kcg-tag,
.kcg-badge,
.kcg-social--badges .kcg-social__link,
.wp-block-avatar img,
.kcg-stat__dot {
	border-radius: 999px !important;
}

/* WordPress writes its own grid rule for the container, with one class in
   it, and prints it after this stylesheet — so matching its specificity is
   not enough to win. Two classes are. */

@media (min-width: 900px) {
	.wp-block-group.kcg-grid--balanced {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* The theme's own grid rule is .kcg-grid.wp-block-group.is-layout-grid —
   three classes, so it outranks a two-class override. Match it. */

@media (min-width: 900px) {
	.kcg-grid--balanced.wp-block-group.is-layout-grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* ------------------------------------------------- hand-written card grids

   The Trainings and Vereinsstätten pages build their tiles as plain markup
   inside the content — <a class="kcg-card"> with an image, a heading and a
   paragraph. Without the picture being pinned to one shape and the text to a
   fixed number of lines, every tile ends up a different height and the grid
   stops reading as a grid. */

.kcg-content .kcg-card {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.kcg-content .kcg-card:hover {
	transform: translateY(-3px);
	box-shadow: var(--wp--preset--shadow--card);
}

.kcg-content .kcg-card > img,
.kcg-content .kcg-card > .kcg-card__placeholder {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	margin: 0;
	background: var(--wp--preset--color--surface);
}

.kcg-content .kcg-card > h2,
.kcg-content .kcg-card > h3 {
	font-size: 1.15rem;
	margin: 1rem 1.15rem 0.5rem;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
	line-height: 1.3;
	min-height: calc(2 * 1.3em);
}

.kcg-content .kcg-card > p {
	font-size: 0.95rem;
	line-height: 1.5;
	margin: 0 1.15rem 1.25rem;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
	min-height: calc(3 * 1.5 * 0.95rem);
}

/* These grids are built by hand, so they get their own column rule rather
   than the block editor's. */

.kcg-content .kcg-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
	gap: 1.5rem;
	margin: 1.75rem 0;
}

@media (min-width: 900px) {
	.kcg-content .kcg-grid--balanced {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* alignwide raises the max-width, but a child cannot outgrow a parent that is
   itself only 780px — the content column is the limit, not the rule. So the
   grid steps out of the column the same way the member table does, capped at
   the theme's wide measure and inset from the window edge. */

.kcg-content > .kcg-grid.alignwide {
	width: min(1240px, 100vw - 3rem);
	max-width: none;
	margin-left: calc(50% - min(620px, 50vw - 1.5rem));
}

@media (max-width: 830px) {
	.kcg-content > .kcg-grid.alignwide {
		width: auto;
		margin-left: 0;
	}
}

/* Centring by margin depends on a percentage of the parent, which is the
   narrow column — the arithmetic came out as no shift at all and the grid
   ran off the right edge. Shifting by half the element's own width with a
   transform is independent of the parent and does not disturb the flow. */

.kcg-content > .kcg-grid.alignwide {
	width: min(1240px, calc(100vw - 3rem));
	max-width: none;
	margin-left: 50%;
	transform: translateX(-50%);
}

@media (max-width: 830px) {
	.kcg-content > .kcg-grid.alignwide {
		width: auto;
		margin-left: 0;
		transform: none;
	}
}

/* Third time, using the arithmetic that already works for the member table:
   plain calc, no min() nested inside it — that is what was not resolving.
   Two branches instead: fill the window below the wide measure, sit at the
   wide measure above it. 50% is half the parent, and the parent is centred,
   so 50% marks the middle of the window. */

.kcg-content > .kcg-grid.alignwide {
	width: calc(100vw - 3rem);
	max-width: none;
	margin-left: calc(50% - 50vw + 1.5rem);
	transform: none;
}

@media (min-width: 1288px) {
	.kcg-content > .kcg-grid.alignwide {
		width: 1240px;
		margin-left: calc(50% - 620px);
	}
}

@media (max-width: 830px) {
	.kcg-content > .kcg-grid.alignwide {
		width: auto;
		margin-left: 0;
	}
}

/* The reason none of the margins took: WordPress's constrained layout sets
   margin-left/right to auto with !important on every direct child, so no
   ordinary rule can shift one. Matching that is the only way out. */

.kcg-content > .kcg-grid.alignwide {
	width: calc(100vw - 3rem);
	max-width: none;
	margin-left: calc(50% - 50vw + 1.5rem) !important;
	margin-right: 0 !important;
	transform: none;
}

@media (min-width: 1288px) {
	.kcg-content > .kcg-grid.alignwide {
		width: 1240px;
		margin-left: calc(50% - 620px) !important;
	}
}

@media (max-width: 830px) {
	.kcg-content > .kcg-grid.alignwide {
		width: auto;
		margin-left: 0 !important;
	}
}

/* A grid cannot centre a partial last row: the two leftover cards sit in
   columns one and two and the third stays empty on the right. Flex can —
   items wrap and each line is centred on its own. Three per line is set by
   the basis, and the gap has to be subtracted from it by hand because
   percentages resolve against the container, not the space left over. */

@media (min-width: 900px) {
	.kcg-grid--balanced.wp-block-group.is-layout-grid,
	.kcg-content .kcg-grid--balanced {
		display: flex;
		flex-wrap: wrap;
		justify-content: center;
		gap: 1.5rem;
		grid-template-columns: none;
	}

	.kcg-grid--balanced.wp-block-group.is-layout-grid > *,
	.kcg-content .kcg-grid--balanced > * {
		flex: 0 1 calc((100% - 3rem) / 3);
		max-width: calc((100% - 3rem) / 3);
	}
}

/* (100% - 3rem)/3 is right on paper but lands a pixel or two over once the
   browser rounds, and three cards no longer fit. With a 1.5rem gap the exact
   form is 33.333% minus 1rem: three of those plus two gaps come to 100% with
   nothing left over, because 3 × 1rem is exactly the 2 × 1.5rem of gap. */

@media (min-width: 900px) {
	.kcg-grid--balanced.wp-block-group.is-layout-grid > *,
	.kcg-content .kcg-grid--balanced > * {
		flex: 0 1 calc(33.333% - 1rem);
		max-width: calc(33.333% - 1rem);
	}
}

/* The cards are content-box, so each one's 1px border sits outside its flex
   basis and three of them come to two pixels more than the row can hold —
   which is why only two ever fitted. */

.kcg-card,
.kcg-content .kcg-card,
.kcg-grid > *,
.kcg-grid--balanced > * {
	box-sizing: border-box;
}

/* The login control in the header stays a pill. It is an <a> when logged out
   and a <summary> when logged in, both carrying .kcg-login — the earlier
   exception list named classes that do not exist in this markup, so the
   universal square rule squared it off. */

.kcg-login,
.kcg-login__icon,
.kcg-usermenu__dot,
.kcg-usermenu > summary {
	border-radius: 999px !important;
}

/* ------------------------------------------------ featured image as banner

   The single-post and page templates print the featured image at the wide
   measure with no shape of its own, so it kept whatever proportions the
   photograph had: a 2016×1512 snapshot became a 1233×856 slab — taller than
   the window, so a reader saw nothing but picture before the first line of
   text. Portrait sources were worse still.

   It becomes a banner of a fixed height instead: tall enough to carry the
   photo, short enough that the headline and the opening paragraph are on
   screen with it. The height follows the window so it stays in proportion on
   a laptop and on a phone. Only the wide variant is touched — the news list
   on the homepage sets its own 16:9 and is left alone. */

.wp-block-post-featured-image.alignwide img {
	display: block;
	width: 100%;
	height: clamp(190px, 38vh, 420px);
	object-fit: cover;
	object-position: center;
}

/* Give it a little room from the title above it. */

.wp-block-post-featured-image.alignwide {
	margin-block: 1.25rem 1.75rem;
}

/* ================================================================== dark

   Three states. No stored choice follows the system; an explicit choice wins
   in either direction, so somebody on a dark machine can still pick light.
   Every colour is defined on plain :root first and only re-declared inside
   the two dark blocks — nothing gets its only definition from a media query.

   The tokens are WordPress's own preset variables, so every block, every
   plugin component and all the theme's own CSS follow along without being
   touched individually. */

:root {
	--kcg-footer-bg: var(--wp--preset--color--contrast);
	--kcg-footer-fg: var(--wp--preset--color--base);
	--kcg-shadow: rgba(20, 35, 43, 0.09);
	--kcg-hover: #d8eef8;
	color-scheme: light;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		color-scheme: dark;

		--wp--preset--color--base: #111b21;
		--wp--preset--color--contrast: #e6edf1;
		--wp--preset--color--surface: #18262e;
		--wp--preset--color--border: #2a3c46;
		--wp--preset--color--muted: #9bacb6;
		--wp--preset--color--primary: #23cdf0;
		--wp--preset--color--primary-dark: #63dcf7;
		--wp--preset--color--secondary: #5aa6cb;

		/* The footer keeps a dark ground in both schemes — inverting it would
		   turn the wave and the whole block below it light. It goes a shade
		   deeper than the page so the wave still reads as a boundary. */
		--kcg-footer-bg: #0a1216;
		--kcg-footer-fg: #e6edf1;

		--kcg-shadow: rgba(0, 0, 0, 0.5);
		--kcg-hover: #1f3a46;
	}
}

:root[data-theme="dark"] {
	color-scheme: dark;

	--wp--preset--color--base: #111b21;
	--wp--preset--color--contrast: #e6edf1;
	--wp--preset--color--surface: #18262e;
	--wp--preset--color--border: #2a3c46;
	--wp--preset--color--muted: #9bacb6;
	--wp--preset--color--primary: #23cdf0;
	--wp--preset--color--primary-dark: #63dcf7;
	--wp--preset--color--secondary: #5aa6cb;

	--kcg-footer-bg: #0a1216;
	--kcg-footer-fg: #e6edf1;

	--kcg-shadow: rgba(0, 0, 0, 0.5);
	--kcg-hover: #1f3a46;
}

/* The footer's own colours now come from the tokens above rather than
   straight from contrast/base, which is what let it invert. */

.kcg-footer {
	color: var(--kcg-footer-fg);
}

.kcg-footer__wave,
.kcg-footer__body {
	background: var(--kcg-footer-bg);
}

/* A few places that had a light colour written into them. */

body {
	background: var(--wp--preset--color--base);
}

.kcg-cal__nav,
.kcg-filters input,
.kcg-filters select,
.kcg-form input,
.kcg-form select,
.kcg-form textarea,
.kcg-cal__fields input,
.kcg-item__book input,
.kcg-tablewrap,
.kcg-mtable,
.kcg-dtable,
.kcg-content .kcg-card {
	background: var(--wp--preset--color--base);
	color: inherit;
}

.kcg-cal__day:hover:not(:disabled) {
	background: var(--kcg-hover);
}

.kcg-newsitem:hover {
	background: var(--wp--preset--color--surface);
}

.wp-site-blocks > header.wp-block-template-part.is-stuck .kcg-header {
	box-shadow: 0 2px 14px var(--kcg-shadow);
}

/* Photographs are a touch hot against a dark ground. */

:root[data-theme="dark"] .kcg-content img,
:root[data-theme="dark"] .kcg-card img {
	filter: brightness(0.92);
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .kcg-content img,
	:root:not([data-theme="light"]) .kcg-card img {
		filter: brightness(0.92);
	}
}

/* ------------------------------------------------------------- the toggle */

.kcg-themetoggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.5rem;
	height: 2.5rem;
	flex: none;
	padding: 0;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 999px !important;
	background: transparent;
	color: var(--wp--preset--color--contrast);
	cursor: pointer;
	transition: background 0.15s ease, border-color 0.15s ease;
}

.kcg-themetoggle:hover,
.kcg-themetoggle:focus-visible {
	background: var(--wp--preset--color--surface);
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--primary-dark);
}

.kcg-themetoggle svg {
	width: 1.15rem;
	height: 1.15rem;
}

/* Show the scheme that clicking would switch *to*: a moon while light, a sun
   while dark. */

.kcg-themetoggle__sun { display: none; }
.kcg-themetoggle__moon { display: block; }

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .kcg-themetoggle__sun { display: block; }
	:root:not([data-theme="light"]) .kcg-themetoggle__moon { display: none; }
}

:root[data-theme="dark"] .kcg-themetoggle__sun { display: block; }
:root[data-theme="dark"] .kcg-themetoggle__moon { display: none; }

:root[data-theme="light"] .kcg-themetoggle__sun { display: none; }
:root[data-theme="light"] .kcg-themetoggle__moon { display: block; }

/* Text sitting on a photograph is written as "base" — white in the light
   scheme. Swapping the palette turned base near-black, so the hero headline
   and tagline became dark text on a dark picture: a contrast ratio of 1.00,
   which is to say invisible. Over a cover image the colour is white in both
   schemes, because what it sits on is the photo, not the page. */

.wp-block-cover .has-base-color,
.wp-block-cover .has-base-color a,
.kcg-hero .has-base-color,
.kcg-hero h1,
.kcg-hero p {
	color: #ffffff;
}

.kcg-footer .has-base-color,
.kcg-footer a {
	color: var(--kcg-footer-fg);
}

/* WordPress prints its preset colour classes with !important, so an ordinary
   rule cannot repaint text that is marked "base". Over a cover image the
   colour has to be white in both schemes regardless. */

.wp-block-cover .has-base-color,
.wp-block-cover .has-base-color a,
.kcg-hero h1,
.kcg-hero p {
	color: #ffffff !important;
}

/* A filled button is the club cyan in both schemes, so its label has to be
   dark in both. It was taking "contrast" for its colour, which flips light
   in dark mode and left pale text on a bright cyan pill — a ratio of 1.6.
   Outline, ghost and quiet buttons are see-through, and the delete button
   carries its own dark red, so all four keep following
   the scheme -- a dark label on them would vanish into a dark page. */

.wp-block-button:not(.is-style-outline) .wp-block-button__link,
.kcg-btn:not(.kcg-btn--ghost):not(.kcg-btn--quiet):not(.kcg-btn--danger),
.kcg-login,
.kcg-cta .wp-block-button__link {
	color: #10222b !important;
}

.kcg-cta .wp-block-button__link,
.wp-block-button:not(.is-style-outline) .wp-block-button__link:hover,
.kcg-btn:not(.kcg-btn--ghost):not(.kcg-btn--quiet):not(.kcg-btn--danger):hover,
.kcg-login:hover {
	color: #10222b !important;
}

/* The hero photograph is left exactly as shot. The dark-mode dimming was
   meant for pictures sitting on a dark page; the cover image is the
   background itself and already carries its own overlay. */

:root[data-theme="dark"] .kcg-hero img,
:root[data-theme="dark"] .wp-block-cover__image-background,
:root[data-theme="dark"] .wp-block-cover img {
	filter: none;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .kcg-hero img,
	:root:not([data-theme="light"]) .wp-block-cover__image-background,
	:root:not([data-theme="light"]) .wp-block-cover img {
		filter: none;
	}
}

/* ------------------------------------------------- the whole news row links

   The title keeps the only real anchor — so the link is still announced
   once, and copying the address still works — but its ::after is stretched
   over the entire row, which makes the picture, the date and the summary
   clickable too.

   A stretched pseudo-element resolves against the nearest positioned
   ancestor, and WordPress positions both the featured image figure and the
   inner group. Those are put back to static, or the overlay would cover only
   the text column. */

.kcg-newsitem {
	position: relative;
}

.kcg-newsitem .wp-block-post-featured-image,
.kcg-newsitem > .wp-block-group,
.kcg-newsitem .wp-block-post-title a {
	position: static;
}

.kcg-newsitem .wp-block-post-title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

/* Make it look like a target. */

.kcg-newsitem {
	cursor: pointer;
}

/* The veil over a cover image is painted in "contrast", which is dark in the
   light scheme — that is the point, it makes the white headline legible over
   a photograph. Swapping the palette turned contrast near-white, so the hero
   was being washed with 40% white: hence the grey.

   The veil is dark in both schemes, because what it darkens is a photograph,
   not the page. WordPress writes its colour classes with !important, so this
   has to as well. */

.wp-block-cover .wp-block-cover__background.has-contrast-background-color,
.kcg-hero .wp-block-cover__background {
	background-color: #14232b !important;
}

/* A featured image with fewer pixels than the banner needs is shown at its
   own size rather than magnified to fill the strip. Small and sharp reads
   better than large and mushy — and it is honest about the source. */

.wp-block-post-featured-image.kcg-featured--small {
	text-align: center;
}

.wp-block-post-featured-image.kcg-featured--small img {
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: 22rem;
	margin-inline: auto;
	object-fit: contain;
}

/* -------------------------------------------------- news list, tightened

   The list was meant to be separated by a single rule. It was drawing two,
   with a gap between them, for two reasons that compounded: each item is the
   only child of its <li>, so :first-child matched every one of them and put
   a line above each; and the list items carry the flow layout's own
   margin-block-start.

   The line above belongs to the list, not to the item, so it is drawn on the
   first list item instead. */

.kcg-posts .wp-block-post-template > li + li {
	margin-block-start: 0;
}

.kcg-newsitem:first-child {
	border-top: 0;
}

.kcg-posts .wp-block-post-template > li:first-child .kcg-newsitem {
	border-top: 1px solid var(--wp--preset--color--border);
}

/* -------------------------------------------------- lettering on cyan

   Cyan is the same colour in both schemes, so anything written on it has to
   be the same colour too. Following the contrast preset meant the label went
   pale exactly where the ground stayed bright. */

:root {
	--kcg-on-accent: #14232b;
}

.kcg-login,
.kcg-usermenu > summary.kcg-login {
	color: var(--kcg-on-accent);
}

/* -------------------------------------------------- menu dropdowns

   The submenu had a border and a shadow but no ground of its own, so it fell
   back to the white the block editor paints by default. */

.kcg-header .wp-block-navigation .wp-block-navigation__submenu-container {
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	border-color: var(--wp--preset--color--border);
}

.kcg-header .wp-block-navigation .wp-block-navigation__submenu-container a,
.kcg-header .wp-block-navigation .wp-block-navigation__submenu-container a:where(:not(.wp-element-button)) {
	color: var(--wp--preset--color--contrast);
	background-color: transparent;
}

.kcg-header .wp-block-navigation .wp-block-navigation__submenu-container a:hover,
.kcg-header .wp-block-navigation .wp-block-navigation__submenu-container a:focus-visible {
	background-color: var(--kcg-hover);
	color: var(--wp--preset--color--primary-dark);
}

/* An opened Reservieren fold turns its own button see-through, so the dark
   label meant for a filled cyan pill would be dark ink on a dark card. The
   rule above cannot express "unless it has no background", so the exception
   is stated here, after it. */

.kcg-item__reserve[open] > summary.kcg-btn {
	color: var(--kcgr-muted, var(--wp--preset--color--muted)) !important;
}

.kcg-item__reserve[open] > summary.kcg-btn:hover,
.kcg-item__reserve[open] > summary.kcg-btn:focus-visible {
	color: var(--kcgr-link, var(--wp--preset--color--primary-dark)) !important;
}

/* -------------------------------------------------- the mail chip

   The little envelope on a board member card sits on a frosted disc over
   their photograph, and the disc was a fixed near-white. In the dark scheme
   the icon colour follows the page and turns pale too, so the chip was a
   bright white dot with an invisible envelope inside it.

   The disc is what has to flip; the icon already follows. */

:root {
	--kcg-chip: rgba(255, 255, 255, 0.92);
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		--kcg-chip: rgba(10, 18, 22, 0.86);
	}
}

:root[data-theme="dark"] {
	--kcg-chip: rgba(10, 18, 22, 0.86);
}

/* -------------------------------------------------- Sparten

   The club's flyer devotes a page to its eight disciplines: a photograph, a
   coloured disc with a line drawing in it, the name in that same colour, and
   one line about what the sport is like. This is that page.

   Each card carries its own colour as a custom property, set on the element,
   because the colour is data about the discipline rather than a style rule.
   Two variants are carried: the flyer's colour, used for the disc and the
   card's edge, and a lightness-adjusted one for the lettering. On paper the
   flyer's cyan on white is fine; on a screen it is a contrast ratio of 1.9,
   so the title colour is walked along its own lightness axis until it clears
   AA -- darker for the light scheme, lighter for the dark one -- and no
   further, which keeps the hue the club actually uses. */

.kcg-sparten {
	display: grid;
	grid-template-columns: 1fr;
	gap: 1.25rem;
}

/* Two, then four. Three is skipped on purpose: eight cards divide evenly
   into one, two and four, and a last row holding two of three reads as a
   mistake. */

@media (min-width: 36rem) {
	.kcg-sparten {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 64rem) {
	.kcg-sparten {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

.kcg-sparte {
	--sparte-title: var(--sparte-light);

	display: flex;
	flex-direction: column;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--sparte);
	overflow: hidden;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .kcg-sparte {
		--sparte-title: var(--sparte-dark);
	}
}

:root[data-theme="dark"] .kcg-sparte {
	--sparte-title: var(--sparte-dark);
}

.kcg-sparte__photo {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

/* The disc sits beside the name, and the sentence underneath lines up with
   the name rather than with the disc -- as on the flyer. */

.kcg-sparte__body {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 0 0.7rem;
	padding: 0.9rem 1rem 1.1rem;
	align-items: center;
}

.kcg-sparte__badge {
	grid-column: 1;
	grid-row: 1;
	display: block;
	width: 2.5rem;
	height: 2.5rem;
	flex: none;
}

.kcg-sparte__title {
	grid-column: 2;
	grid-row: 1;
	margin: 0;
	font-size: 0.95rem;
	font-weight: 800;
	line-height: 1.2;
	text-transform: uppercase;
	letter-spacing: 0.01em;
	color: var(--sparte-title);
}

.kcg-sparte__text {
	grid-column: 2;
	grid-row: 2;
	margin: 0.35rem 0 0;
	font-size: 0.9rem;
	line-height: 1.45;
	color: var(--wp--preset--color--muted);
}

/* On the narrowest screens the card is wide enough for the sentence to sit
   under the disc as well, which wastes less of the line. */

@media (max-width: 26rem) {
	.kcg-sparte__text {
		grid-column: 1 / -1;
	}
}

/* -------------------------------------------------- stepping out of the column

   A page's text sits in a 780px column, which is right for reading and wrong
   for a grid of eight cards. `alignwide` cannot help here: the column's width
   is a max-width on the container, so a child cannot be wider than it however
   it is aligned.

   This is the same shape as the rental panel: fixed widths paired with
   margins of exactly half, so the block stays centred at every step, and
   !important because WordPress writes margin-left:auto onto direct children
   of a constrained layout. */

@media (min-width: 64rem) {
	.kcg-wide {
		width: 60rem;
		max-width: 60rem;
		margin-left: calc(50% - 30rem) !important;
		margin-right: auto;
	}
}

@media (min-width: 80rem) {
	.kcg-wide {
		width: 76rem;
		max-width: 76rem;
		margin-left: calc(50% - 38rem) !important;
		margin-right: auto;
	}
}

/* -------------------------------------------------- smaller service tiles

   Three tiles across a 1240px section make each one 400px wide, which is
   larger than anything else on the page. Four is the same size as the
   Sparten cards, and the balanced grid centres whatever is left over on the
   last row -- six services come out 4 + 2, seven Vereinsstätten 4 + 3. */

@media (min-width: 1100px) {
	.kcg-grid--balanced.wp-block-group.is-layout-grid > *,
	.kcg-content .kcg-grid--balanced > * {
		flex: 0 1 calc(25% - 1.125rem);
		max-width: calc(25% - 1.125rem);
	}
}

/* -------------------------------------------------- Sparten that open

   Six of the eight disciplines have a page behind them. Those tiles become
   clickable across their whole face, the way the news items do: the title is
   the real link and a stretched pseudo-element carries the hit area, so
   there is still exactly one link per card for a screen reader. */

.kcg-sparte__title a {
	color: inherit;
	text-decoration: none;
}

.kcg-sparte:has(.kcg-sparte__title a) {
	cursor: pointer;
	transition: border-color 0.15s ease;
}

.kcg-sparte__title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.kcg-sparte:has(.kcg-sparte__title a):hover {
	border-color: var(--sparte-title);
}

.kcg-sparte:has(.kcg-sparte__title a):hover .kcg-sparte__photo {
	filter: brightness(1.06);
}

.kcg-sparte__title a:focus-visible {
	outline: 2px solid var(--sparte-title);
	outline-offset: 3px;
}

/* -------------------------------------------------- the story's hero

   A news story leads with its photograph, full width, above the date and the
   headline. The height is capped so a tall portrait does not push the
   headline off the screen, and the picture is never enlarged past its own
   size -- the kcg-featured--small rule above still applies, so a 270px file
   is shown small and sharp instead of being stretched across the page. */

.kcg-posthero {
	margin-top: calc(var(--wp--preset--spacing--50) * -1);
	margin-bottom: 2rem;
}

.kcg-posthero img {
	display: block;
	width: 100%;
	height: clamp(220px, 44vh, 560px);
	object-fit: cover;
	object-position: center;
}

.kcg-posthero.kcg-featured--small img {
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: 22rem;
	margin-inline: auto;
	object-fit: contain;
}

/* -------------------------------------------------- the mobile menu

   The overlay is position: fixed, but `will-change: transform` on the header
   -- put there for the hide-on-scroll animation -- makes the header a
   containing block for fixed descendants. A transform is not even needed;
   the promise of one is enough. So the full-screen menu was resolving
   against a 121px-tall header: forty-five links crammed into a scrolling
   sliver, which is what made it unusable.

   WordPress marks the document with has-modal-open while the menu is open,
   and that is exactly when the header must not be animating anyway. */

html.has-modal-open header.wp-block-template-part,
html.has-modal-open .kcg-header {
	will-change: auto;
	transform: none !important;

	/* The frosted-glass effect does the same thing as will-change: any
	   backdrop-filter makes the element a containing block for fixed
	   descendants, so it has to go for as long as the menu is open. */
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
}

/* Core paints the overlay white with black lettering. Here it should be the
   page's own colours, in whichever scheme the reader is using. */

.wp-block-navigation__responsive-container.is-menu-open {
	background-color: var(--wp--preset--color--base) !important;
	color: var(--wp--preset--color--contrast) !important;
	padding: 1.5rem 1.5rem 3rem;
}

.wp-block-navigation__responsive-container.is-menu-open a,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	color: var(--wp--preset--color--contrast);
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
	gap: 0.35rem;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
	font-size: 1.05rem;
}

/* Inside the overlay a submenu is just an indented list -- it needs neither
   the panel's ground nor its shadow. The indent and the line that marks it
   as nested are set with the folding rules further down. */

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	background-color: transparent;
	box-shadow: none;
}

/* A 24px icon is a small thing to hit with a thumb. The box grows without
   moving the icon. */

.wp-block-navigation__responsive-container-open,
.wp-block-navigation__responsive-container-close {
	padding: 0.65rem;
	margin: -0.65rem;
}

/* ---------------------------------------------------- an accent that passes

   The brand colour measures 4.31:1 on the light background, under the 4.5
   that text needs; deepened by 18% black it clears. In dark it is a pale
   cyan on a near-black ground at 10.9:1 and is left alone. */

:root {
	--kcg-accent-aa: color-mix(in srgb, var(--wp--preset--color--primary-dark) 82%, #000);
}

:root[data-theme="dark"] {
	--kcg-accent-aa: var(--wp--preset--color--primary-dark);
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		--kcg-accent-aa: var(--wp--preset--color--primary-dark);
	}
}

/* The header nav is justified right, which is right for a bar and wrong for
   a full-screen list -- every label ended up hugging the edge furthest from
   the thumb. Inside the overlay the list reads from the left.

   Core sets the alignment from --navigation-layout-justification-setting on
   a selector carrying four classes, which beat the three this rule used to
   have. Naming the justification class as well makes five. */

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container.items-justified-right {
	align-items: stretch;
	justify-content: flex-start;
	gap: 0;
	width: 100%;
	text-align: left;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	text-align: left;
}

/* A top-level row: the label on the left, the chevron on the right, a rule
   underneath. The submenu is a third child and takes the whole width, which
   is what the wrap is for. */

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container > .wp-block-navigation-item {
	display: flex;
	/* Core lays these rows out as columns, which is what centred the label
	   over its chevron. Same specificity, so the direction has to be said. */
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	width: 100%;
	border-bottom: 1px solid var(--wp--preset--color--border);
	font-size: 1.05rem;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container > .wp-block-navigation-item > .wp-block-navigation-item__content {
	flex: 1 1 auto;
	padding: 0.95rem 0;
	font-weight: 700;
}

/* Core hides the chevron in the overlay -- it expects every section to be
   open -- so it comes back at a size a thumb can hit. */

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu__toggle {
	display: grid !important;
	place-items: center;
	width: 44px;
	height: 44px;
	padding: 0;
	margin-right: -0.6rem;
	background: transparent;
	border: 0;
	color: inherit;
	cursor: pointer;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu__toggle svg {
	width: 1.1rem;
	height: 1.1rem;
	transition: transform 0.18s ease;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.kcg-nav-open > .wp-block-navigation-submenu__toggle svg {
	transform: rotate(180deg);
}

/* Folded away until asked for. The !important answers core's own display
   rule for the overlay, which is what kept all 27 items on screen. */

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container > .wp-block-navigation-item > .wp-block-navigation__submenu-container {
	display: none !important;
	flex-basis: 100%;
	width: 100%;
	margin: 0 0 0.7rem;
	padding: 0.1rem 0 0.1rem 0.95rem;
	border-left: 2px solid var(--wp--preset--color--border);
	gap: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.kcg-nav-open > .wp-block-navigation__submenu-container {
	display: flex !important;
	flex-direction: column;
}

/* Sub items speak more quietly than the section they belong to. */

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item {
	font-size: 0.95rem;
	border: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	display: block;
	width: 100%;
	padding: 0.55rem 0;
	color: var(--wp--preset--color--muted);
	font-weight: 500;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content:focus-visible {
	color: var(--kcg-accent-aa);
}

/* Where the reader already is. */

.wp-block-navigation__responsive-container.is-menu-open .current-menu-item > .wp-block-navigation-item__content {
	color: var(--kcg-accent-aa);
}

/* -------------------------------------------------- cards that do nothing

   The two panels at the top of the Mittwochstraining page are plain divs:
   nothing to open, so nothing should lift or glow under the cursor. The
   animation belongs to cards that are a link or contain one. */

/* Inert means: not a link, and holding none. A tile that is itself an anchor
   contains no anchor, so testing only for the contents caught the clickable
   tiles too and stripped the only sign they could be opened. */

.kcg-card:not(a):not(:has(a)):hover,
.kcg-content .kcg-card:not(a):not(:has(a)):hover {
	transform: none;
	box-shadow: none;
	border-color: var(--wp--preset--color--border);
	cursor: default;
}

/* -------------------------------------------------- the fee table on a phone

   Three columns in 340px: the prices were being cut off the right edge. The
   long middle column is what has to give, so the table is told to divide the
   width itself and the wording wraps inside it, while the price column keeps
   just enough to stay on one line. */

@media (max-width: 640px) {
	.kcg-dtable {
		table-layout: fixed;
		width: 100%;
		font-size: 0.82rem;
	}

	.kcg-dtable th,
	.kcg-dtable td {
		padding: 0.4rem 0.35rem;
		overflow-wrap: anywhere;
		hyphens: auto;
	}

	.kcg-dtable th:nth-child(1),
	.kcg-dtable td:nth-child(1) {
		width: 27%;
	}

	.kcg-dtable th:nth-child(3),
	.kcg-dtable td:nth-child(3) {
		width: 4.7rem;
		text-align: right;
		white-space: nowrap;
	}
}

/* The footnotes under it read as three separate notes now. */

.kcg-note {
	margin-block: 0.85rem;
	font-size: 0.95rem;
}

/* -------------------------------------------------- the schedule overlay

   One picture, shown large. It is a plain <dialog>, so the browser handles
   the backdrop, the focus trap and Escape; the script only opens it. */

.kcg-lightbox {
	max-width: min(96vw, 1400px);
	max-height: 92vh;
	padding: 0;
	border: 0;
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
}

.kcg-lightbox::backdrop {
	background: rgba(6, 12, 16, 0.86);
}

.kcg-lightbox img {
	display: block;
	max-width: 100%;
	max-height: 84vh;
	width: auto;
	height: auto;
	margin: 0 auto;
}

.kcg-lightbox__bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 0.6rem 0.9rem;
	border-bottom: 1px solid var(--wp--preset--color--border);
	font-size: 0.9rem;
}

.kcg-lightbox__close {
	border: 0;
	background: transparent;
	color: inherit;
	font: inherit;
	cursor: pointer;
	padding: 0.35rem 0.5rem;
}

.kcg-lightbox__close:hover {
	color: var(--wp--preset--color--primary-dark);
}

/* -------------------------------------------------- confine the stretched link

   The clickable face of a Sparte tile is a pseudo-element with inset: 0, and
   that resolves against the nearest *positioned* ancestor. The card was
   static and nothing above it was positioned either, so all eight overlays
   resolved against the initial containing block -- one viewport-sized
   rectangle that every card shared. The last one in the markup won every
   click, which is why all eight tiles opened the Kajak Akademie.

   The card has to be the positioned ancestor. This is the third time this
   pattern has bitten in this stylesheet: the news items and the boat cards
   both needed the same line. */

.kcg-sparte {
	position: relative;
}

/* -------------------------------------------------- heroes that keep heads

   Two kinds of photograph, two treatments.

   A panoramic picture keeps the full-bleed band: trimming a little off a
   letterbox shot costs nothing. The crop is taken from below centre rather
   than from the middle, because faces sit in the upper half of a photograph
   and the middle is where a group shot's heads are.

   Anything squarer -- a 4:3 group photo, a portrait -- is shown whole,
   centred, and capped by height instead. It gives up the edge-to-edge look,
   which is a smaller loss than giving up the faces. */

.kcg-posthero img {
	object-position: 50% 38%;
}

.kcg-posthero.kcg-featured--upright img {
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: min(62vh, 560px);
	margin-inline: auto;
	object-fit: contain;
}

/* Something behind a picture that no longer reaches the edges, so the hero
   still reads as a band rather than an image floating on the page. */

.kcg-posthero.kcg-featured--upright {
	background: var(--wp--preset--color--surface);
	display: flex;
	justify-content: center;
}

/* The same for the wide featured images used elsewhere, which share the band. */

.wp-block-post-featured-image.alignwide.kcg-featured--upright img {
	height: auto;
	max-height: min(56vh, 480px);
	width: auto;
	max-width: 100%;
	margin-inline: auto;
	object-fit: contain;
}

/* -------------------------------------------------- the hero, reshaped

   The band used to be a fixed height, which imposed one shape on every
   photograph: a 1400x995 podium shot in a 3.5:1 band lost sixty per cent of
   its height, and the heads with it.

   Now the band is told the picture's ratio (from PHP, since CSS cannot ask)
   and follows it, clamped between 16:9 and 2.5:1. Inside that range nothing
   is cropped and the hero still runs edge to edge. Outside it the crop is
   small and taken from below centre, because faces sit above the middle. */

.kcg-posthero.kcg-featured--wide img,
.kcg-posthero:not(.kcg-featured--upright) img {
	width: 100%;
	height: auto;
	aspect-ratio: min(2.5, max(1.6, var(--hero-ratio, 2)));
	max-height: 76vh;
	object-fit: cover;
	object-position: 50% 38%;
}

/* A photograph squarer than 16:9 is shown whole, over a blurred copy of
   itself so the band still reaches both edges. The blur is the same picture,
   handed in as a custom property. */

.kcg-posthero.kcg-featured--upright {
	position: relative;
	display: flex;
	justify-content: center;
	align-items: center;
	overflow: hidden;
	background: var(--wp--preset--color--surface);
}

.kcg-posthero.kcg-featured--upright::before {
	content: "";
	position: absolute;
	inset: -6%;
	background-image: var(--hero-image);
	background-size: cover;
	background-position: center;
	filter: blur(34px) saturate(1.15);
	opacity: 0.55;
	z-index: 0;
}

.kcg-posthero.kcg-featured--upright img {
	position: relative;
	z-index: 1;
	width: auto;
	height: auto;
	max-width: min(100%, 62rem);
	max-height: min(66vh, 580px);
	margin-inline: auto;
	object-fit: contain;
	aspect-ratio: auto;
}

/* A picture too small to fill anything is left at its own size, as before. */

.kcg-posthero.kcg-featured--small img {
	max-height: 22rem;
}

/* A section heading that leads somewhere keeps the heading's own colour --
   it is a title first and a link second. The underline appears on hover, so
   the affordance is there without turning the heading blue. */

.kcg-section > h2 a {
	color: inherit;
	text-decoration: none;
}

.kcg-section > h2 a:hover,
.kcg-section > h2 a:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.18em;
}

/* -------------------------------------------------- the burger, on the left

   The header nav is justified right, which suits a row of links beside the
   logo. On a phone the row collapses to a single icon, and an icon pinned to
   the right edge is both far from the thumb and oddly detached from the logo
   it belongs with. Below the point where the menu collapses, the whole
   group moves to the left. */

@media (max-width: 781px) {
	.kcg-header .wp-block-group.is-content-justification-right,
	.kcg-header .wp-block-navigation.is-responsive {
		justify-content: flex-start;
	}

	.kcg-header .wp-block-navigation.items-justified-right {
		justify-content: flex-start;
	}
}

/* -------------------------------------------------- three across, on request

   The balanced grid steps up to four per row on a wide screen, which suits
   six tiles and leaves five looking lopsided -- four and a lonely one. This
   modifier holds a grid at three, so five come out three and two.

   It has to repeat both of the balanced grid's selectors and sit after them:
   the four-column rule carries two classes, so matching it is not enough on
   its own. */

@media (min-width: 900px) {
	.kcg-grid--three.wp-block-group.is-layout-grid > *,
	.kcg-content .kcg-grid--three > * {
		flex: 0 1 calc(33.333% - 1rem);
		max-width: calc(33.333% - 1rem);
	}
}

/* -------------------------------------------------- the members-only gate

   A page someone asked for, with the login form standing in for it. The
   explanation sits above the form so the reason is read before the fields. */

.kcg-gate {
	max-width: 34rem;
	margin-inline: auto;
}

.kcg-gate__hint {
	margin-bottom: 1.25rem;
	padding: 0.9rem 1.1rem;
	border-left: 3px solid var(--kcgr-accent, #03c4eb);
	background: var(--kcgr-surface-2, #f1f7fa);
	font-size: 0.95rem;
}

/* -------------------------------------------------- the training plan

   Written as a table, drawn as a week. The table is what the club edits and
   what a phone and a screen reader get; the grid is a picture of the same
   thing for wide screens, built by the script.

   It replaces a 3840x2160 PNG in which the times could not be read by a
   search engine, resized for a phone, or changed without a graphics
   program. */

.kcg-plan {
	/* White on the plain brand colour is 3.85:1 in light and 2.71:1 in dark.
	   Deepened by 30% black it is 6.8 and 5.1, clear of the 4.5 this size of
	   text needs in both schemes. */
	--plan-head: color-mix(in srgb, var(--wp--preset--color--secondary) 70%, #000);

	/* The link colour is 3.99:1 on the banded rows; this clears 4.5. It is
	   put back to the plain colour for dark below, where the link is already
	   pale against a dark band and deepening it would only hurt. */
	--plan-link: color-mix(in srgb, var(--wp--preset--color--primary-dark) 82%, #000);

	/* No radius: the theme squares every corner deliberately. */
	overflow: hidden;
	border: 1px solid var(--wp--preset--color--border);
}

:root[data-theme="dark"] .kcg-plan {
	--plan-link: var(--wp--preset--color--primary-dark);
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .kcg-plan {
		--plan-link: var(--wp--preset--color--primary-dark);
	}
}

.kcg-plan table {
	width: 100%;
	border-collapse: separate;
	border-spacing: 0;
	font-size: 0.95rem;
}

.kcg-plan th,
.kcg-plan td {
	padding: 0.7rem 0.8rem;
	border: 0;
	text-align: left;
	vertical-align: top;
}

.kcg-plan thead th {
	background: var(--plan-head);
	color: #fff;
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

/* Banding carries the row across, so the rules between them can go. */

.kcg-plan tbody tr:nth-child(even) {
	background: var(--wp--preset--color--surface);
}

.kcg-plan tbody tr:hover {
	background: color-mix(in srgb, var(--wp--preset--color--primary) 10%, transparent);
}

.kcg-plan tbody td:first-child {
	font-weight: 700;
	color: var(--wp--preset--color--contrast);
}

.kcg-plan tbody td:nth-child(2) {
	font-variant-numeric: tabular-nums;
	color: var(--wp--preset--color--contrast);
}

/* The discipline's colour, the same one its block carries in the grid, as a
   spine down the left of the row. Square, like everything else here, and it
   costs 3px where an indented dot cost 24. */

.kcg-plan__row td:first-child {
	border-left: 3px solid var(--tone, var(--wp--preset--color--secondary));
}

.kcg-plan__row--seekajak  { --tone: #e0a33c; }
.kcg-plan__row--freestyle { --tone: #c86bb0; }
.kcg-plan__row--kanupolo  { --tone: #5a9bd4; }
.kcg-plan__row--technik   { --tone: #6fb96f; }
.kcg-plan__row--hallenbad { --tone: #9aa7b0; }
.kcg-plan__row--other     { --tone: #5aa6cb; }

.kcg-plan tbody td:last-child {
	color: var(--wp--preset--color--muted);
}

/* Once the grid has been drawn, the table steps aside on wide screens. */

@media (min-width: 900px) {
	.kcg-plan--has-grid {
		display: none;
	}
}

.kcg-plan-grid {
	display: none;
}

@media (min-width: 900px) {
	.kcg-plan-grid {
		display: grid;
		grid-template-columns: 3.5rem repeat(7, minmax(0, 1fr));
		grid-template-rows: auto repeat(var(--rows), var(--row-h, 1.15rem));
		gap: 0 0.4rem;
		margin: 1.5rem 0 2rem;
	}
}

.kcg-plan-grid__day {
	padding: 0.35rem 0;
	background: var(--wp--preset--color--secondary);
	color: #fff;
	font-weight: 700;
	font-size: 0.85rem;
	text-align: center;
}

.kcg-plan-grid__hour {
	align-self: start;
	transform: translateY(-0.55em);
	padding-right: 0.5rem;
	color: var(--wp--preset--color--muted);
	font-size: 0.75rem;
	font-variant-numeric: tabular-nums;
	text-align: right;
}

.kcg-plan-grid__line {
	align-self: start;
	height: 1px;
	background: var(--wp--preset--color--border);
}

/* A session. The colours are the ones the old picture used, so anyone who
   knew it recognises the week at a glance. */

.kcg-plan-item {
	--tone: #5aa6cb;

	display: flex;
	flex-direction: column;
	gap: 0.1rem;
	overflow: hidden;
	padding: 0.4rem 0.55rem;
	border-left: 4px solid var(--tone);
	background: color-mix(in srgb, var(--tone) 22%, transparent);
	font-size: 0.78rem;
	line-height: 1.25;
}

.kcg-plan-item__time {
	color: var(--wp--preset--color--contrast);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.kcg-plan-item__title {
	font-size: 0.82rem;
	text-transform: uppercase;
	letter-spacing: 0.01em;
}

.kcg-plan-item__where {
	color: var(--wp--preset--color--muted);
}

.kcg-plan-item--seekajak  { --tone: #e0a33c; }
.kcg-plan-item--freestyle { --tone: #c86bb0; }
.kcg-plan-item--kanupolo  { --tone: #5a9bd4; }
.kcg-plan-item--technik   { --tone: #6fb96f; }
.kcg-plan-item--hallenbad { --tone: #9aa7b0; }

/* A session that leads somewhere says so, without turning into a blue link:
   the colour of the discipline is the point of the block. */

a.kcg-plan-item {
	color: inherit;
	text-decoration: none;
	transition: filter 0.15s ease, transform 0.15s ease;
}

a.kcg-plan-item:hover,
a.kcg-plan-item:focus-visible {
	filter: brightness(1.12);
	transform: translateY(-1px);
}

a.kcg-plan-item:focus-visible {
	outline: 2px solid var(--tone);
	outline-offset: 2px;
}

/* The table underneath is the editable copy, so its links are ordinary. */

.kcg-plan td a {
	color: var(--plan-link, var(--wp--preset--color--primary-dark));
}

/* A session too short to hold three lines keeps the two that matter. The
   place is still in the table below, which is the full record. */

.kcg-plan-item--tight {
	padding: 0.25rem 0.5rem;
	font-size: 0.72rem;
	line-height: 1.15;
}

.kcg-plan-item--tight .kcg-plan-item__where {
	display: none;
}

.kcg-plan-item--tight .kcg-plan-item__title {
	font-size: 0.74rem;
}

/* "Weinzödl Stausee / Slalomstrecke" wraps to three lines and pushed its
   session over the edge of the box. The place is capped at two lines here;
   the table below always carries it in full. */

.kcg-plan-item__where {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* The lane widths are percentages of the column, so the padding and the 4px
   marker on the left have to be inside that width — with content-box they
   were added on top and each box reached into the next day. The rental
   stylesheet has this same note twice; it is the third time. */

.kcg-plan-item {
	box-sizing: border-box;
}

/* The hours the plan skips. Without saying so the grid would read as one
   continuous morning-to-night axis, and every evening session would look
   like it happened hours earlier than it does. */

.kcg-plan-grid__break {
	display: flex;
	align-self: center;
	align-items: center;
	gap: 0.7rem;
	color: var(--wp--preset--color--muted);
	font-size: 0.72rem;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

.kcg-plan-grid__break::before,
.kcg-plan-grid__break::after {
	content: '';
	flex: 1;
	border-top: 1px dashed var(--wp--preset--color--border);
}

/* A session name is one long word -- Drachenboot, Kanupolo -- and a box only
   half a day wide cannot hold it on one line. The boxes have height going
   spare, so the word wraps rather than disappearing under the overflow. */

.kcg-plan-item__time,
.kcg-plan-item__title,
.kcg-plan-item__where {
	/* The break points come from the script as soft hyphens; `manual` is what
	   honours them. Breaking mid-word is the fallback for a name the script
	   does not know -- ugly, but it never swallows the text. */
	hyphens: manual;
	overflow-wrap: break-word;
}

/* Two trainings at once halve the width. The tight treatment above was for a
   box that is short; this is for one that is narrow. */

.kcg-plan-item--narrow {
	padding: 0.3rem 0.35rem;
	font-size: 0.68rem;
}

.kcg-plan-item--narrow .kcg-plan-item__title {
	font-size: 0.7rem;
	letter-spacing: 0;
}

/* On a phone the table is the plan, and it was running a little wider than
   the screen. Tighter than this and the times start to wrap. */

@media (max-width: 480px) {
	.kcg-plan table {
		font-size: 0.78rem;
	}

	.kcg-plan th,
	.kcg-plan td {
		padding: 0.5rem 0.3rem;
	}

	.kcg-plan thead th {
		letter-spacing: 0.04em;
	}

	/* The times are the one thing that must not break across two lines. */
	.kcg-plan td:nth-child(2) {
		white-space: nowrap;
	}
}

/* A box that shares its day is short of width, not of height -- it has room
   for the location over several lines. */

/* The starting point for the fit pass, which lowers it per box as needed. */

.kcg-plan-item__where {
	-webkit-line-clamp: 5;
	line-clamp: 5;
}

/* Matches the hover of every other card. It needs the extra weight because
   the resting border is set by `.kcg-content .kcg-card`, which is just as
   specific and comes later. */

.kcg-content a.kcg-card:hover,
.kcg-content a.kcg-card:focus-visible {
	border-color: var(--wp--preset--color--primary);
}

/* ------------------------------------------- pages that are a grid of tiles

   The title and the paragraphs live in a 900px column, the tiles in a 1216px
   one. Both are centred as boxes, but the text inside the narrow one was
   ranged left, so the heading began well inside the left edge of the grid
   underneath it. Centring the text lines the two up. */

.kcg-hub .wp-block-post-title,
.kcg-hub .kcg-content > p {
	text-align: center;
}

.kcg-hub .kcg-content > .wp-block-buttons {
	justify-content: center;
}

/* A heading that is a link should say so before it is clicked. Colour alone
   would not do it -- these headings keep the text colour on purpose -- so
   the underline is the signal. */

.kcg-section > h2 a:hover {
	color: var(--kcg-accent-aa);
	text-decoration: underline;
	text-underline-offset: 0.18em;
	text-decoration-thickness: 2px;
}

/* --------------------------------------------- embeds, before they load

   Stands in for a YouTube, Vimeo or Maps frame until the reader asks for
   it. Sized like the embed it replaces so the page does not jump when the
   swap happens. */

.kcg-consent {
	display: grid;
	place-items: center;
	aspect-ratio: 16 / 9;
	width: 100%;
	margin: 1.5rem 0;
	padding: 1.5rem;
	border: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--surface);
	text-align: center;
}

.kcg-consent__panel {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.6rem;
	max-width: 34rem;
}

.kcg-consent__label {
	margin: 0;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

.kcg-consent__note {
	margin: 0;
	font-size: 0.95rem;
	line-height: 1.5;
	color: var(--wp--preset--color--contrast);
}

.kcg-consent__actions { margin: 0.2rem 0 0; }

.kcg-consent__remember {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	font-size: 0.85rem;
	color: var(--wp--preset--color--muted);
	cursor: pointer;
}

.kcg-consent__always {
	width: 1rem;
	height: 1rem;
	accent-color: var(--wp--preset--color--primary);
	cursor: pointer;
}

.kcg-consent__legal {
	margin: 0;
	font-size: 0.82rem;
	color: var(--wp--preset--color--muted);
}

.kcg-consent__legal a { color: var(--kcg-accent-aa); }

/* The frame once it has been asked for. */

.kcg-embed {
	margin: 1.5rem 0;
}

.kcg-embed iframe {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	height: auto;
	border: 0;
}

/* A map is not 16:9 and looks wrong forced into it. */

.kcg-consent[data-provider="gmaps"] {
	aspect-ratio: auto;
	min-height: 18rem;
}

@media (max-width: 600px) {
	.kcg-consent {
		aspect-ratio: auto;
		min-height: 15rem;
		padding: 1.2rem;
	}
}
