/**
 * Machinery cards and grids.
 *
 * The signature commercial component. One available card and one sold card,
 * used unchanged on the homepage, the machinery archive, every machine_type
 * term page and the related strip on a machine page. There is no homepage
 * variant of either, and no page overrides card styling.
 *
 * Two rules keep the layout stable at every width:
 *
 * 1. Cards are grid children with min-width: 0, so content can never set a
 *    track's width. The image fits the card; the card never fits the image.
 * 2. The media box owns its size through aspect-ratio and the image fills it
 *    with object-fit, so the photograph's intrinsic dimensions are irrelevant.
 *
 * Sections declare no padding here: templates pick a level from .ajp-section.
 */

@layer ajp.components {

	/* ----------------------------------------------------------------------
	 * Grids
	 *
	 * Explicit column counts at explicit breakpoints. auto-fit and auto-fill
	 * are not used: both counts are design decisions rather than consequences
	 * of available space, and an intrinsic minimum can silently collapse at
	 * intermediate widths — which it once did, producing a single ~900px card.
	 *
	 *   Available   <688px 1 col   688-1099px 2 col   >=1100px 3 col
	 *   Sold        <688px 2 col   688-1099px 4 col   >=1100px 5 col
	 *
	 * The sold counts are chosen so a curated set of ten never leaves a single
	 * orphan on the last row: 10 divides by 5 and by 2, and 4 leaves a pair.
	 * -------------------------------------------------------------------- */

	.ajp-machines__grid {
		display: grid;
		gap: var(--ajp-gap-grid);
		grid-template-columns: minmax(0, 1fr);
	}

	/* 688px */
	@media (min-width: 43em) {
		.ajp-machines__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	}

	/* 1100px */
	@media (min-width: 68.75em) {
		.ajp-machines__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	}

	.ajp-machines__grid--sold {
		gap: var(--ajp-gap-grid-dense);
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	@media (min-width: 43em) {
		.ajp-machines__grid--sold { grid-template-columns: repeat(4, minmax(0, 1fr)); }
	}

	@media (min-width: 68.75em) {
		.ajp-machines__grid--sold { grid-template-columns: repeat(5, minmax(0, 1fr)); }
	}

	/* Content must never set a track's width. */
	.ajp-machines__grid > * { min-width: 0; }

	.ajp-machines__more { margin-block-start: var(--ajp-space-block); }

	/* ----------------------------------------------------------------------
	 * Available card
	 *
	 * The one component in the design that is allowed to be an object. It
	 * earns that: it is the product. Everything else on the site — category
	 * navigation, services, the acquisition band — is set as ruled rows or
	 * plain type, so the card grid is unmistakably the commercial content.
	 *
	 * A tinted panel rather than a border. A border would put a rectangle
	 * around a photograph that already has hard edges of its own; a surface
	 * shift separates the card from the page without drawing anything.
	 * -------------------------------------------------------------------- */

	.ajp-machine {
		position: relative;
		display: flex;
		min-width: 0;
		flex-direction: column;
		overflow: hidden;
		border-radius: var(--ajp-radius);
		background-color: var(--ajp-color-surface);
		transition: background-color var(--ajp-duration-base) var(--ajp-ease);
	}

	/*
	 * The hover indicator: one red rule that wipes in along the bottom edge.
	 * It is the only red on the card, it appears only on intent, and it is
	 * drawn rather than moved, so nothing reflows.
	 */
	.ajp-machine--available::after {
		content: "";
		position: absolute;
		inset-inline: 0;
		bottom: 0;
		height: 3px;
		background-color: var(--ajp-color-brand);
		transform: scaleX(0);
		transform-origin: left;
		transition: transform var(--ajp-duration-base) var(--ajp-ease);
	}

	.ajp-machine--available:hover,
	.ajp-machine--available:focus-within { background-color: var(--ajp-color-surface-hover); }

	.ajp-machine--available:hover::after,
	.ajp-machine--available:focus-within::after { transform: scaleX(1); }

	.ajp-machine__body {
		display: flex;
		flex: 1 1 auto;
		flex-direction: column;
		padding: var(--ajp-space-card-pad);
	}

	/*
	 * The machine type is a quiet label above the title. Sentence case and
	 * muted: it was condensed uppercase red, which put a shouted line above
	 * every one of the fifty-two cards on the archive.
	 */
	.ajp-machine__type {
		margin: 0 0 var(--ajp-space-meta-title);
		color: var(--ajp-color-muted);
		font-size: var(--ajp-text-meta);
	}

	/*
	 * One size at every column count. The title used to step up at 48em,
	 * which made it largest exactly where the card is narrowest.
	 */
	.ajp-machine__title {
		margin: 0;
		font-size: var(--ajp-text-card);
		font-weight: var(--ajp-weight-semibold);
		line-height: var(--ajp-leading-snug);
		letter-spacing: var(--ajp-tracking-snug);
		text-wrap: pretty;
	}

	.ajp-machine__link {
		color: var(--ajp-color-heading);
		text-decoration: none;
	}

	/* One anchor, one tab stop, whole card clickable. Do not add a second
	 * link inside a card without removing this. */
	.ajp-machine__link::after {
		content: "";
		position: absolute;
		inset: 0;
		z-index: var(--ajp-z-raised);
	}

	.ajp-machine__link:focus-visible { outline: none; }

	.ajp-machine:has(.ajp-machine__link:focus-visible) {
		outline: var(--ajp-focus-width) solid var(--ajp-focus-color);
		outline-offset: var(--ajp-focus-offset);
	}

	/*
	 * A consistent two-line title region, so a one-line title does not pull the
	 * price of its card above its neighbours in the same row.
	 */
	.ajp-machine__title { min-height: calc(2em * var(--ajp-leading-snug)); }

	/*
	 * The only red on the card. Set below the title: the machine's name is what
	 * a buyer scans for, and weight plus colour give the price the prominence it
	 * needs without it having to be the largest thing in the body.
	 *
	 * --ajp-color-brand-hover, not --ajp-color-brand. At 16px bold the price is
	 * no longer WCAG large text, so it needs 4.5:1 rather than 3:1, and the
	 * brand red is 4.35:1 on the card surface and 4.02:1 on the hover surface.
	 * The darker step of the same red clears both at 5.88:1 and 5.43:1.
	 */
	.ajp-machine__price {
		display: flex;
		flex-wrap: wrap;
		align-items: baseline;
		gap: var(--ajp-space-1) var(--ajp-space-2);
		/*
		 * The top margin is smaller than it looks: the title's line box carries
		 * half its leading below the last line, so 12px here read as roughly 15
		 * and left the price drifting away from the machine it belongs to.
		 *
		 * The bottom margin is the gap to the footer divider. It has to live
		 * here, not on the footer, because the footer's margin-block-start is
		 * auto and would override any top margin of its own.
		 */
		margin: var(--ajp-space-2) 0 var(--ajp-space-4);
		color: var(--ajp-color-brand-hover);
		font-size: var(--ajp-text-body);
		font-weight: var(--ajp-weight-bold);
		/* Not 1: at 1 the comma in "£3,500" sat on the divider below it. */
		line-height: var(--ajp-leading-heading);
		letter-spacing: var(--ajp-tracking-heading);
		font-variant-numeric: tabular-nums;
	}

	.ajp-machine__price-value--secondary {
		color: var(--ajp-color-muted);
		font-size: var(--ajp-text-meta);
		font-weight: var(--ajp-weight-medium);
		letter-spacing: var(--ajp-tracking-none);
	}

	/*
	 * Footer. margin-block-start: auto pushes it to the foot of the card, so
	 * the divider lands on the same line across every card in a row however
	 * many lines the titles take — structure, not a fixed height.
	 *
	 * Decoration, not a control: the title anchor is stretched over the whole
	 * card, so the card stays the link and this stays a paragraph.
	 */
	.ajp-machine__foot {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: var(--ajp-space-3);
		margin: 0;
		padding-block-start: var(--ajp-space-4);
		border-top: var(--ajp-border-width) solid var(--ajp-color-line);
		margin-block-start: auto;
		color: var(--ajp-color-muted);
		font-size: var(--ajp-text-meta);
		font-weight: var(--ajp-weight-medium);
		transition: color var(--ajp-duration-fast) var(--ajp-ease);
	}

	.ajp-machine__cue { white-space: nowrap; }

	.ajp-machine__arrow {
		transition: transform var(--ajp-duration-fast) var(--ajp-ease);
	}

	/* Part of the card hover that already exists — not a second animation. */
	.ajp-machine--available:hover .ajp-machine__foot,
	.ajp-machine--available:focus-within .ajp-machine__foot { color: var(--ajp-color-heading); }

	.ajp-machine--available:hover .ajp-machine__arrow,
	.ajp-machine--available:focus-within .ajp-machine__arrow {
		transform: translateX(var(--ajp-space-1));
	}

	/* ----------------------------------------------------------------------
	 * Sold card
	 *
	 * Not a panel. Sold stock is a record of trade, not inventory, so it is
	 * set as a plain photograph with a name under it: denser, quieter, and
	 * visibly a different class of thing from a machine that can be bought.
	 * -------------------------------------------------------------------- */

	/* Said when a category has nothing in it — see grid-available.php. */
	.ajp-machines__empty {
		max-width: var(--ajp-measure);
		margin: 0;
		color: var(--ajp-color-body);
	}

	.ajp-machine--sold {
		background-color: transparent;
		border-radius: 0;
		overflow: visible;
	}

	.ajp-machine--sold .ajp-machine__media {
		border-radius: var(--ajp-radius);
	}

	.ajp-machine--sold .ajp-machine__image {
		filter: brightness(var(--ajp-sold-dim));
		transition: filter var(--ajp-duration-base) var(--ajp-ease);
	}

	.ajp-machine--sold:hover .ajp-machine__image,
	.ajp-machine--sold:focus-within .ajp-machine__image { filter: brightness(1); }

	.ajp-machine--sold .ajp-machine__body {
		padding: var(--ajp-space-3) 0 0;
	}

	.ajp-machine--sold .ajp-machine__type {
		margin-block-end: var(--ajp-space-1);
		font-size: var(--ajp-text-label);
	}

	/* Sold cards carry only a name, so the name is worth reading. */
	.ajp-machine--sold .ajp-machine__title { font-size: var(--ajp-text-body); }

	.ajp-machine--sold .ajp-machine__link:hover { color: var(--ajp-color-brand); }

	/*
	 * Status is a text label, not a colour or an opacity, so the distinction
	 * survives for anyone who can perceive neither.
	 *
	 * Ink rather than red: red belongs to live commerce, and ten red stamps on
	 * the homepage would outnumber and outshout the one primary action.
	 */
	.ajp-machine__status {
		position: absolute;
		top: 0;
		left: 0;
		z-index: var(--ajp-z-raised);
		margin: 0;
		padding: var(--ajp-space-1) var(--ajp-space-2);
		background-color: var(--ajp-ink);
		color: var(--ajp-white);
		font-size: var(--ajp-text-label);
		font-weight: var(--ajp-weight-semibold);
		letter-spacing: var(--ajp-tracking-label);
		text-transform: uppercase;
	}

	/* ----------------------------------------------------------------------
	 * Related strip
	 *
	 * The canonical cards at a denser count, not a third card design.
	 * -------------------------------------------------------------------- */

	.ajp-machines__grid--related { gap: var(--ajp-gap-grid-dense); }

	@media (min-width: 43em) {
		.ajp-machines__grid--related { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	}

	@media (min-width: 64em) {
		.ajp-machines__grid--related { grid-template-columns: repeat(4, minmax(0, 1fr)); }
	}

	.ajp-machines__grid--related .ajp-machine__body { padding: var(--ajp-space-4); }
	.ajp-machines__grid--related .ajp-machine__title { font-size: var(--ajp-text-body); }
	.ajp-machines__grid--related .ajp-machine__price { font-size: var(--ajp-text-meta); }
	.ajp-machines__grid--related .ajp-machine__foot { display: none; }
}
