/*
 * The course listing.
 *
 * Everything here is drawn with eight custom properties, declared below with
 * defaults that work on any theme. A theme that wants the listing to match its
 * own palette redeclares them - that is the whole of the styling contract, and
 * nothing else in this file needs touching:
 *
 *   :root {
 *     --cl-heading: ...;      headings and course titles
 *     --cl-muted: ...;        secondary text
 *     --cl-accent-ink: ...;   link hover and dates
 *     --cl-hover-bg: ...;     rules and separators
 *     --cl-logo-backing: ...; behind a transparent accreditation logo
 *     --cl-radius-image: ...; picture corners
 *     --cl-radius-panel: ...; panel corners
 *     --cl-size-small: ...;   small text
 *   }
 */

:root {
	--cl-heading:      currentColor;
	--cl-muted:        currentColor;
	--cl-accent-ink:   currentColor;
	--cl-hover-bg:     rgba(128, 128, 128, 0.25);
	--cl-logo-backing: #ffffff;
	--cl-radius-image: 6px;
	--cl-radius-panel: 6px;
	--cl-size-small:   0.875rem;
}

.cl-courses { margin-block: clamp(36px, 6vw, 68px); }

/* The heading a shortcode or a template passes in. */
.cl-courses__title {
	font-size: clamp(24px, 3.2vw, 32px);
	margin-bottom: 0.7em;
	padding-bottom: 0.35em;
	border-bottom: 1px solid var(--cl-hover-bg);
}

.cl-courses__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: clamp(16px, 2vw, 24px);
}

.cl-course {
	display: flex;
	flex-wrap: wrap;
	gap: clamp(16px, 2.5vw, 28px);
	align-items: flex-start;
	margin: 0;
	padding: clamp(18px, 2.5vw, 26px);
	background: var(--cl-hover-bg);
	border-radius: var(--cl-radius-panel);
}

/* The picture sits on the right. It comes second in the markup too, so a
   screen reader and a narrow screen both get the title and dates first, which
   is the useful order - the photograph is supporting. */
.cl-course__image {
	flex: 0 0 clamp(180px, 28%, 280px);
	order: 2;
}

.cl-course__image img {
	width: 100%;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	border-radius: var(--cl-radius-image);
	display: block;
}

.cl-course__body { flex: 1 1 260px; min-width: 0; order: 1; }

@media (max-width: 599px) {
	.cl-course__image { flex-basis: 100%; }
}

.cl-course__title { font-size: clamp(22px, 3vw, 28px); margin: 0 0 10px; }
.cl-course__title a { color: var(--cl-heading); text-decoration: none; }
.cl-course__title a:hover,
.cl-course__title a:focus-visible { color: var(--cl-accent-ink); }

.cl-course__dates {
	display: flex;
	align-items: baseline;
	gap: 8px;
	color: var(--cl-accent-ink);
	font-size: var(--cl-size-small);
	text-transform: uppercase;
	letter-spacing: 1px;
	margin: 0 0 6px;
}

.cl-course__dates .icon { width: 14px; height: 14px; flex: none; }

/* Stacked, one set of dates per line. The baseline alignment above keeps the
   calendar beside the first line rather than floating against the middle of
   the stack. */
.cl-course__dates-list span { display: block; }
.cl-course__dates-list { line-height: 1.7; }

/* Up to three lines: an early price, the ordinary one, and a concession. So
   the paragraph stacks and each line is its own row with its own icon. A
   course with nothing to say about an early price collapses to one line and
   reads exactly as it did before there were ever three. */
.cl-course__price {
	color: var(--cl-muted);
	font-size: var(--cl-size-small);
	margin: 0 0 10px;
}

.cl-price {
	display: flex;
	align-items: baseline;
	gap: 8px;
}

.cl-price .icon { width: 14px; height: 14px; flex: none; }

/* No colour of its own on the early line. It was briefly given the accent, to
   tie it to the dates, and read as an inconsistency rather than as emphasis.
   The words already say which line is which. */

/* An early price whose date has gone, kept on the page instead of removed.
   The strike goes on the text span, which carries the whole line, words and
   figure together. Putting it on the flex container instead would leave it
   to the browser whether the decoration reached the text at all, and putting
   it on the number alone would read as a correction to a typing mistake
   rather than as a deadline that has passed. */
.cl-price--over { color: var(--cl-muted); opacity: 0.75; }
.cl-price--over > span { text-decoration: line-through; }

.cl-course__summary { margin: 0; max-width: none; }

.cl-course__accred { margin: 14px 0 0; }

/* The CoSH logo is a transparent PNG with dark artwork, so on this site's
   background it would be all but invisible. It gets its own white panel
   rather than being recoloured - it is somebody else's mark and should be
   shown as they drew it. */
.cl-course__cosh,
.cl-course-accreditation img {
	display: block;
	background: var(--cl-logo-backing);
	padding: 10px 14px;
	border-radius: var(--cl-radius-image);
	max-width: 148px;
	width: auto;
	height: auto;
}

.cl-courses-empty { color: var(--cl-muted); font-style: italic; }

/* --------------------------------------------------------------------------
   Cards
   --------------------------------------------------------------------------
   Same markup as a row; the grid and a change of order are the whole
   difference. The body still comes first in the markup, so the reading order
   stays title, dates, price whichever way it is laid out - order moves the
   picture above it on screen without moving it in the document.

   Order rather than column-reverse, and deliberately. Reversing the direction
   AND setting order cancel each other out: the row layout already gives the
   body order 1 and the picture order 2, so under column-reverse the body came
   out on top and the picture below it, which is exactly what this is not
   supposed to look like.

   The picture is cropped to whatever height its size asks for, by the browser
   rather than by a new image size, so it works on pictures already uploaded.
   Which part survives the crop is the focal point set on the course, written
   onto the image as an inline object-position. Without one it crops from the
   middle.
   -------------------------------------------------------------------------- */

.cl-courses--cards .cl-courses__list {
	grid-template-columns: repeat(var(--cl-cols, 3), minmax(0, var(--cl-card-max, 1fr)));
	justify-content: center;
}

/* Each card is its own container, so the type inside it is sized against the
   card rather than against the window. Three across and four across then read
   the same, and a card given an explicit width brings its text with it - which
   is the whole point of being able to set a size at all. The clamps stop it
   becoming unreadable at one extreme or comical at the other. */
.cl-courses--cards .cl-course {
	container-type: inline-size;
	max-width: var(--cl-card-max, none);
}

.cl-courses--cards .cl-course__title { font-size: clamp(17px, 7.5cqi, 26px); }
.cl-courses--cards .cl-course__dates,
.cl-courses--cards .cl-course__price { font-size: clamp(12px, 4.4cqi, 16px); }
.cl-courses--cards .cl-course__summary { font-size: clamp(12px, 4.2cqi, 16px); }

/* The size sets the picture's height exactly and the card's width at most, and
   says nothing about how tall a card is.

   That is the whole design. The picture is what has to match across a row, and
   its height has nothing to do with how much a course has to say; the words then
   take what they need and the grid makes every card in a row as tall as the
   tallest. Nothing is ever clipped, and the pictures still line up.

   Fixing the card's height instead, with the picture taking a share of it, was
   tried and thrown out: a course with five sets of dates needs 213px for its
   words where one with a single date needs about 120, so any fixed height either
   clips one or leaves the other half empty. */
.cl-courses--cards .cl-course__image img {
	aspect-ratio: auto;
	height: var(--cl-card-picture, 210px);
	width: 100%;
	object-fit: cover;
	border-radius: 0;
}

/* One is a real answer, and had no rule until now: a display set to one
   column, or a three-column one with a single course in it, fell through to
   the default of three and drew two empty tracks. */
.cl-courses--cols-1 { --cl-cols: 1; }
.cl-courses--cols-2 { --cl-cols: 2; }
.cl-courses--cols-3 { --cl-cols: 3; }
.cl-courses--cols-4 { --cl-cols: 4; }

/* Fewer cards than the display asked for, so the row starts at the left and
   the first card begins under the first letter of the heading. A row that
   fills still centres. */
.cl-courses--short .cl-courses__list { justify-content: start; }

.cl-courses--cards .cl-course {
	display: flex;
	flex-direction: column;
	flex-wrap: nowrap;
	gap: clamp(12px, 1.5vw, 18px);
	padding: 0;
	overflow: hidden;
}

.cl-courses--cards .cl-course__image {
	flex: 0 0 auto;
	order: 0;
	margin: 0;
}

/* Picture under the words instead of over them. Only the two orders swap; the
   padding follows, so whichever end the body is at keeps its breathing room and
   the picture stays flush to the card's edge. */
.cl-courses--picture-bottom .cl-course__image { order: 1; }
.cl-courses--picture-bottom .cl-course__body {
	order: 0;
	padding: clamp(16px, 2.2vw, 22px) clamp(14px, 2vw, 20px) 0;
}


.cl-courses--cards .cl-course__body {
	flex: 1 1 auto;
	order: 1;
	padding: 0 clamp(14px, 2vw, 20px) clamp(16px, 2.2vw, 22px);
}

.cl-courses--cards .cl-course.has-no-image .cl-course__body {
	padding-top: clamp(16px, 2.2vw, 22px);
}

/* Four across stops being four across long before a phone. Each step down is
   where the cards get narrower than about 220px, which is where a title starts
   wrapping to three lines. */
@media (max-width: 1100px) {
	.cl-courses--cols-4 { --cl-cols: 3; }
}

@media (max-width: 860px) {
	.cl-courses--cols-3,
	.cl-courses--cols-4 { --cl-cols: 2; }
}

@media (max-width: 560px) {
	.cl-courses--cards .cl-courses__list { --cl-cols: 1; }
	.cl-courses--cards .cl-course__image img { aspect-ratio: 3 / 2; }
}

/* -------------------------------------------------------------------------
   The Find out more button
   ------------------------------------------------------------------------- */

/* Written with :where(), which carries no specificity at all, so a theme's own
   .button rule wins without having to be more specific. That matters here: this
   stylesheet loads after the theme's, so an ordinary class selector of the same
   weight would have beaten it on source order and the button would have come
   out plugin-shaped on a themed site. A theme with no button styling of its own
   still gets a button rather than a bare link. */
:where(.cl-course__more-link) {
	display: inline-block;
	padding: 0.6em 1.2em;
	border: 1px solid currentColor;
	border-radius: var(--cl-radius-panel);
	color: var(--cl-accent-ink);
	font-size: var(--cl-size-small);
	line-height: 1.2;
	text-decoration: none;
}

:where(.cl-course__more-link):hover,
:where(.cl-course__more-link):focus-visible {
	background: var(--cl-hover-bg);
}

.cl-course__more { margin: 14px 0 0; }

/* The course's name: read out, never shown. */
.cl-course__more-name {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* The buttons line up across a row, however much each course has to say.

   The card is already a flex column and its body already takes the space left
   over, so the body becomes a column too and the button takes up the slack
   above it. Switching the body from block flow to a flex column changes no
   spacing: every paragraph in it sets its own margins with a top of zero, so
   there were never any adjoining margins to collapse. */
.cl-courses--cards .cl-course__body {
	display: flex;
	flex-direction: column;
}

.cl-courses--cards .cl-course__more {
	margin-top: auto;
	padding-top: 14px;
}
