/*
 * Components (BEM).
 *
 *   Primitives  .container .heading .eyebrow .label .lead .standfirst .caption
 *               .prose .button .arrow-link
 *   Layout      .spread (margin column 1–3 + body 4–12, the one grid of the site)
 *   Patterns    .section-head .carousel
 *   Templates   .text-page (Insights index and article: insights.css)
 *   Motion      see motion.css
 */
@layer components {
	/* =====================================================================
	   Primitives
	   ===================================================================== */
	.container {
		width: 100%;
		max-width: calc(var(--container) + var(--gutter) * 2);
		margin-inline: auto;
		padding-inline: var(--gutter);
		container-type: inline-size;
	}


	.container--prose {
		max-width: calc(44rem + var(--gutter) * 2);
	}

	/* Classical inscriptional serif: authority from proportion and space, not weight. */
	.heading {
		font-family: var(--font-heading);
		font-weight: 400;
		color: var(--heading);
		letter-spacing: 0;
		text-wrap: balance;
	}

	.heading--display {
		font-size: var(--type-display-size);
		line-height: var(--type-display-line);
	}

	.heading--h2 {
		font-size: var(--type-h2-size);
		line-height: var(--type-h2-line);
	}

	.heading--h3 {
		font-size: var(--type-h3-size);
		line-height: var(--type-h3-line);
	}

	.heading--h4 {
		font-size: var(--type-h4-size);
		line-height: var(--type-h4-line);
	}

	.heading--h5 {
		font-size: var(--type-h5-size);
		line-height: var(--type-h5-line);
		letter-spacing: 0;
	}

	/* Eyebrow: small, widely spaced capitals; "|" parts set apart by a hairline (cf_eyebrow()). */
	.eyebrow {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: var(--space-2) var(--space-4);
		font-size: var(--type-label-size);
		line-height: var(--type-label-line);
		letter-spacing: var(--type-label-tracking);
		font-weight: 500;
		text-transform: uppercase;
		color: var(--eyebrow);
	}

	/* The tracking also follows the last letter; pull the rule back by it,
	   so it sits midway between the parts. */
	.eyebrow__divider {
		width: var(--border-width);
		height: var(--space-3);
		margin-left: calc(var(--type-label-tracking) * -1);
		background: var(--rule);
	}

	/* Label: small, widely spaced burgundy capitals for categories and meta. */
	.label {
		font-size: var(--type-label-size);
		line-height: var(--type-label-line);
		letter-spacing: var(--type-label-tracking);
		font-weight: 500;
		text-transform: uppercase;
		color: var(--eyebrow);
	}

	.lead {
		font-size: var(--type-lead-size);
		line-height: var(--type-lead-line);
		color: var(--muted-foreground);
	}

	/*
	 * Standfirst: the lead paragraph under a heading. Sans, a size up from
	 * body text: the serif is kept for headings and the Brief's statement
	 * (content master, section 14: "a classical serif for headings and a
	 * restrained body typeface").
	 */
	.standfirst {
		max-width: 36rem;
		font-family: var(--font-body);
		font-weight: 400;
		font-size: var(--type-standfirst-size);
		line-height: var(--type-standfirst-line);
		color: var(--muted-foreground);
		text-wrap: pretty;
	}

	/* Caption: image captions, sources and notes; always in the margin column on desktop. */
	.caption {
		max-width: 20rem;
		font-size: var(--type-caption-size);
		line-height: var(--type-caption-line);
		color: var(--muted-foreground);
	}

	.prose {
		color: var(--muted-foreground);
	}

	:where(.prose) > * + * {
		margin-top: 1em;
	}

	:where(.prose) > :where(h2, h3, h4) {
		margin-top: 1.75em;
		font-family: var(--font-heading);
		color: var(--heading);
		line-height: 1.25;
	}

	:where(.prose) > :where(h2) {
		font-size: var(--type-h4-size);
	}

	:where(.prose) > :where(h3, h4) {
		font-size: var(--type-h5-size);
	}

	:where(.prose) > :where(h2, h3, h4) + * {
		margin-top: 0.75em;
	}

	:where(.prose) > :first-child {
		margin-top: 0;
	}

	:where(.prose) :where(ul, ol) {
		padding-left: 1.25em;
	}

	:where(.prose) :where(a) {
		color: var(--heading);
		text-decoration-thickness: 1px;
		text-underline-offset: 0.2em;
	}

	:where(.prose) :where(strong) {
		font-weight: 600;
		color: var(--foreground);
	}

	/* Set-apart statement inside article text (Insights articles only). */
	:where(.prose) :where(blockquote) {
		padding: 1.5rem 1.75rem;
		background: var(--card);
		border-left: 1px solid var(--heading);
		color: var(--foreground);
	}

	/*
	 * Button (design draft V2): a fine outline with the top-right corner cut
	 * away. Built only from plain borders, which browsers always snap to
	 * whole pixels, so every edge stays crisp wherever the button lands:
	 *   ::after          top, left and bottom edges, stopping short of the cut
	 *   .button__corner  the right edge below the cut and the last stretch
	 *                    of the bottom edge; its ::after is the 1px diagonal
	 *   ::before         the fill, under the frame and cut to the same corner;
	 *                    it tints in on hover (motion.css, Tint)
	 * Buttons from cf_button() carry the corner (CF_BUTTON_CORNER).
	 */
	.button {
		--button-line: var(--primary);
		--button-foreground: var(--primary);
		--button-fill: var(--button-line);
		--button-fill-foreground: var(--primary-foreground);
		--button-notch: 0.625rem;

		position: relative;
		isolation: isolate;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		min-height: 2.25rem;
		padding: var(--space-2) var(--space-8);
		border: 0;
		border-radius: var(--radius);
		background: none;
		color: var(--button-foreground);
		font-size: var(--type-button-size);
		font-weight: 500;
		letter-spacing: var(--type-button-tracking);
		text-transform: uppercase;
		line-height: var(--type-button-line);
		text-align: center;
		text-decoration: none;
	}

	.button::before {
		content: "";
		position: absolute;
		inset: 0;
		z-index: -1;
		background-color: transparent;
		clip-path: polygon(0 0, calc(100% - var(--button-notch)) 0, 100% var(--button-notch), 100% 100%, 0 100%);
	}

	.button::after,
	.button__corner,
	.button__corner::before,
	.button__corner::after {
		position: absolute;
		pointer-events: none;
	}

	.button::after {
		content: "";
		inset: 0 var(--button-notch) 0 0;
		border: var(--border-width) solid var(--button-line);
		border-right: 0;
	}

	.button__corner {
		top: 0;
		right: 0;
		bottom: 0;
		width: var(--button-notch);
		border-bottom: var(--border-width) solid var(--button-line);
	}

	.button__corner::before {
		content: "";
		top: var(--button-notch);
		right: 0;
		bottom: 0;
		width: var(--border-width);
		background: var(--button-line);
	}

	.button__corner::after {
		content: "";
		top: 0;
		left: 0;
		width: calc(var(--button-notch) * 1.4142);
		height: var(--border-width);
		background: var(--button-line);
		transform-origin: 0 0;
		rotate: 45deg;
	}

	/* Light button: on burgundy panels and on photographs. */
	.button--light {
		--button-line: var(--ramp-white);
		--button-foreground: var(--ramp-white);
		--button-fill-foreground: var(--ramp-burgundy-900);
	}

	/*
	 * Arrow link: small capitals, then a chevron. Set inline (not flex), so
	 * the words stay an inline box: on a narrow screen a long label wraps
	 * and the hover line follows each line. The chevron is an inline box
	 * around a no-break space, so it never wraps away from the last word;
	 * it is painted by the mask, 8px after the words (nudged in motion.css).
	 * --arrow-link-pad centres the words in a taller target.
	 */
	.arrow-link {
		display: inline-block;
		max-width: 100%;
		padding-block: var(--arrow-link-pad, var(--space-1));
		color: var(--eyebrow);
		font-weight: 500;
		font-size: var(--type-button-size);
		line-height: var(--type-button-line);
		letter-spacing: var(--type-button-tracking);
		text-transform: uppercase;
		text-decoration: none;
	}

	.arrow-link::after {
		content: "\00a0";
		letter-spacing: var(--space-4);
		background: currentColor;
		mask: var(--icon-arrow) no-repeat;
		mask-size: var(--space-3) var(--space-3);
		mask-position: var(--arrow-link-shift, var(--space-2)) 50%;
	}

	/* =====================================================================
	   Spread: the one grid of the site (desktop).
	     .spread__margin  columns 1–3: section number and label, captions,
	                      notes, carousel counter (the "margin" of a page)
	     .spread__body    columns 4–12: everything else
	   Below 64rem the margin sits above the body.
	   ===================================================================== */
	.spread {
		display: grid;
		gap: var(--space-6);
	}

	@media (min-width: 64rem) {
		.spread {
			grid-template-columns: repeat(12, minmax(0, 1fr));
			column-gap: var(--grid-gap);
			row-gap: 0;
		}

		.spread__margin {
			grid-column: 1 / 4;
		}

		.spread__body {
			grid-column: 4 / -1;
		}
	}

	/* Section headings share typography; each block owns their composition. */
	.section-head {
		display: grid;
		gap: var(--space-6);
		margin: 0;
	}

	/* Eyebrow above the title; on desktop a long hairline runs in from the margin. */
	.section-head__eyebrow {
		position: relative;
		margin-bottom: var(--space-3);
	}

	@media (min-width: 64rem) {
		.section-head__eyebrow::before {
			content: "";
			position: absolute;
			top: 50%;
			right: calc(100% + var(--space-8));
			width: 22rem;
			height: var(--border-width);
			background: var(--hairline);
		}
	}

	.section-head__title {
		max-width: 15em;
	}

	.section-head__intro {
		display: grid;
		gap: var(--space-4);
		align-content: start;
	}

	.section-head__standfirst {
		margin: 0;
		max-width: 42ch;
		line-height: var(--type-standfirst-line);
	}

	/* =====================================================================
	   Carousel (inc/carousel.php + assets/js/carousel.js)
	     Controls: counter "01 / 05", a hairline progress track, and square
	     hairline arrow buttons. No autoplay.
	   ===================================================================== */
	.carousel {
		--carousel-gap: var(--grid-gap);
		--carousel-slide-size: 85%;

		position: relative;
	}

	.carousel__viewport {
		overflow: hidden;
	}

	.carousel__container {
		display: flex;
		margin-left: calc(var(--carousel-gap) * -1);
		touch-action: pan-y pinch-zoom;
	}

	.carousel__slide {
		flex: 0 0 var(--carousel-slide-size);
		min-width: 0;
		padding-left: var(--carousel-gap);
	}

	.carousel__controls {
		display: flex;
		align-items: center;
		gap: var(--space-6);
	}

	.carousel__counter {
		flex: none;
		min-width: 4.5em;
		font-size: var(--type-small-size);
		line-height: var(--type-small-line);
		font-variant-numeric: tabular-nums;
		letter-spacing: 0.04em;
		color: var(--heading);
	}

	.carousel__progress {
		position: relative;
		flex: 1;
		height: var(--border-width);
		overflow: hidden;
		background: var(--border);
	}

	.carousel__progress-bar {
		position: absolute;
		inset: 0 auto 0 0;
		width: 100%;
		background: var(--heading);
		transition: translate var(--duration-fast) linear;
	}

	.carousel__arrows {
		display: flex;
		flex: none;
		gap: var(--space-2);
	}

	.carousel__button {
		display: grid;
		place-items: center;
		width: var(--space-12);
		height: var(--space-12);
		border: var(--border-width) solid transparent;
		color: var(--ornament);
		transition:
			color var(--duration-base) var(--ease-out),
			opacity var(--duration-base) var(--ease-out);
	}

	.carousel__button::before {
		content: "";
		width: var(--space-4);
		height: var(--space-3);
		background: currentColor;
		mask: var(--icon-arrow) center / contain no-repeat;
	}

	.carousel__button--previous::before {
		rotate: 180deg;
	}

	.carousel__button:is(:hover, :focus-visible):not(:disabled) {
		color: var(--primary);
	}

	.carousel__button:disabled {
		opacity: 0.35;
		cursor: default;
	}


	.carousel--static .carousel__controls {
		display: none;
	}

	/* =====================================================================
	   Templates: text page (the Insights templates: insights.css)
	   ===================================================================== */
	.text-page {
		padding-block: var(--spacing-section);
	}

	.text-page__head {
		display: flex;
		flex-direction: column;
		gap: 1.5rem;
		margin-bottom: 3rem;
		padding-bottom: 2.5rem;
		border-bottom: var(--border-width) solid var(--border);
	}

	.text-page .button {
		margin-top: 1rem;
	}

	/* =====================================================================
	   Heading accent: *words* in a heading (cf_heading_html()) carry a
	   fine burgundy underline, as in design draft V2.
	   ===================================================================== */
	.heading__accent {
		text-decoration-line: underline;
		text-decoration-color: var(--accent-line, var(--primary));
		text-decoration-thickness: 1px;
		text-underline-offset: 0.16em;
	}

	[data-theme="ink"] .heading__accent {
		--accent-line: var(--ramp-gold-300);
	}

	/* =====================================================================
	   Dot list: short points with a small centred dot, as in the draft.
	   ===================================================================== */
	.dot-list {
		display: grid;
		gap: var(--space-1);
		font-size: var(--type-small-size);
		line-height: 1.75rem;
		color: var(--foreground);
	}

	.dot-list > li {
		position: relative;
		padding-left: var(--space-4);
	}

	.dot-list > li::before {
		content: "";
		position: absolute;
		top: calc(0.875rem - 1.5px);
		left: 0;
		width: 3px;
		height: 3px;
		border-radius: 50%;
		background: currentColor;
	}

	/* =====================================================================
	   Engraving: a faint line drawing of a Zurich facade behind burgundy
	   and stone surfaces. Light lines are screened onto burgundy; on stone
	   the same drawing is inverted and multiplied.
	   ===================================================================== */
	.engraving {
		position: relative;
		isolation: isolate;
	}

	.engraving::before {
		content: "";
		position: absolute;
		inset: 0;
		z-index: -1;
		background: url("../img/texture-engraving.jpg") var(--engraving-position, 70% 30%) / cover no-repeat;
		mix-blend-mode: screen;
		opacity: 0.1;
		pointer-events: none;
	}

	[data-theme="stone"].engraving::before,
	[data-theme="default"].engraving::before {
		filter: invert(1);
		mix-blend-mode: multiply;
		opacity: 0.05;
	}

	/* Over a large surface the drawing recedes further. */
	.engraving--quiet::before {
		opacity: 0.035;
	}

	/* =====================================================================
	   Fading frame: fine gold lines that run out into the surface. Each
	   user sets which edges are drawn and in which direction they fade:
	     --frame-top / --frame-right / --frame-bottom / --frame-left
	   each a gradient (see the presets below), or none.
	   ===================================================================== */
	.fade-frame {
		--frame-color: var(--ramp-gold-300);
		--frame-width: 1px;
		--frame-top: none;
		--frame-right: none;
		--frame-bottom: none;
		--frame-left: none;

		position: absolute;
		pointer-events: none;
		background:
			var(--frame-top) top / 100% var(--frame-width) no-repeat,
			var(--frame-right) right / var(--frame-width) 100% no-repeat,
			var(--frame-bottom) bottom / 100% var(--frame-width) no-repeat,
			var(--frame-left) left / var(--frame-width) 100% no-repeat;
	}

	/* Top edge strengthening to the right, right edge fading downwards. */
	.fade-frame--top-right {
		--frame-top: linear-gradient(to right, transparent, var(--frame-color) 70%);
		--frame-right: linear-gradient(to bottom, var(--frame-color), transparent);
	}

	/* Right edge rising out of nothing, bottom edge fading to the left. */
	.fade-frame--bottom-right {
		--frame-right: linear-gradient(to bottom, transparent, var(--frame-color) 45%);
		--frame-bottom: linear-gradient(to left, var(--frame-color) 10%, transparent 70%);
	}

	/* A closed frame whose lower half dissolves. */
	.fade-frame--box {
		--frame-top: linear-gradient(var(--frame-color), var(--frame-color));
		--frame-right: linear-gradient(to bottom, var(--frame-color) 40%, transparent);
		--frame-left: linear-gradient(to bottom, var(--frame-color) 40%, transparent);
	}

	/* =====================================================================
	   Form (inc/form-components.php, assets/js/forms.js)
	   Field   one underline; the label rests inside the field like the
	           placeholder of the draft and moves up, smaller, once the
	           field is focused or filled, so it never disappears. A
	           burgundy line draws across the underline on focus. Hint,
	           error and count sit in one quiet row beneath.
	   Check   a square box with a fine tick, the label beside it
	   States  hover darkens the line; focus draws it in burgundy; invalid
	           turns line, label and message to the error colour;
	           disabled fades
	   ===================================================================== */
	.field {
		display: grid;
		gap: var(--space-1);
	}

	.field__box {
		position: relative;
		padding-top: var(--space-5);
	}

	/* The underline, and the line that draws across it on focus. */
	.field__box::before,
	.field__box::after {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		bottom: 0;
		height: var(--border-width);
		pointer-events: none;
	}

	.field__box::before {
		background: var(--input);
		transition: background-color var(--duration-fast) var(--ease-out);
	}

	/* Focus: a 2 px line, so the focused field is plain to see (WCAG 2.4.7). */
	.field__box::after {
		height: 2px;
		background: var(--primary);
		scale: 0 1;
		transform-origin: 0 50%;
		transition: scale var(--duration-base) var(--ease-out);
	}

	.field__control {
		display: block;
		width: 100%;
		min-height: var(--space-10);
		padding: var(--space-2) 0 var(--space-3);
		border: 0;
		border-radius: 0;
		background: transparent;
		color: var(--heading);
		font-size: var(--type-small-size);
		line-height: var(--type-small-line);
		caret-color: var(--primary);
		appearance: none;
	}

	.field__control:focus,
	.field__control:focus-visible {
		outline: none;
	}

	.field__control::placeholder {
		color: transparent;
	}

	textarea.field__control {
		min-height: 7.5rem;
		max-height: 22rem;
		resize: none;
		field-sizing: content;
		overflow-y: auto;
	}

	/* Autofill keeps the quiet surface instead of the browser colour. */
	.field__control:-webkit-autofill {
		-webkit-text-fill-color: var(--heading);
		box-shadow: 0 0 0 100vmax var(--background) inset;
	}

	.field__label {
		position: absolute;
		top: calc(var(--space-5) + var(--space-2));
		left: 0;
		max-width: 100%;
		overflow: hidden;
		color: var(--subtle-foreground);
		font-size: var(--type-small-size);
		line-height: var(--type-small-line);
		white-space: nowrap;
		text-overflow: ellipsis;
		transform-origin: 0 0;
		pointer-events: none;
		transition:
			translate var(--duration-base) var(--ease-out),
			scale var(--duration-base) var(--ease-out),
			color var(--duration-fast) var(--ease-out);
	}

	.field__mark {
		margin-left: 0.125em;
		color: var(--primary);
	}

	/* Raised: focused or filled (an empty field shows the blank placeholder). */
	.field__control:is(:focus, :not(:placeholder-shown)) + .field__label,
	.field__control:-webkit-autofill + .field__label {
		translate: 0 calc((var(--space-5) + var(--space-1)) * -1);
		scale: 0.8;
		color: var(--muted-foreground);
	}

	.field__control:focus + .field__label {
		color: var(--primary);
	}

	.field:hover .field__box::before {
		background: var(--muted-foreground);
	}

	.field__box:focus-within::after {
		scale: 1 1;
	}

	/*
	 * Footer row: the message (left) and hint or count (right). The message
	 * is a one-row grid that eases from 0fr to 1fr when the field becomes
	 * invalid, so the form opens and closes softly instead of jumping.
	 */
	.field__footer {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		column-gap: var(--space-4);
		align-items: start;
		font-size: var(--type-caption-size);
		line-height: var(--type-caption-line);
		color: var(--subtle-foreground);
	}

	.field__message {
		display: grid;
		grid-template-rows: 0fr;
		grid-column: 1;
		grid-row: 1;
		opacity: 0;
		transition:
			grid-template-rows var(--duration-base) var(--ease-out),
			opacity var(--duration-fast) var(--ease-out);
	}

	.field[data-invalid] .field__message {
		grid-template-rows: 1fr;
		opacity: 1;
	}

	.field__error {
		display: flex;
		align-items: flex-start;
		gap: var(--space-2);
		min-height: 0;
		overflow: hidden;
		color: var(--destructive);
		font-weight: 500;
	}

	.field__error:not(:empty) {
		padding-top: var(--space-2);
	}

	.field__error-icon {
		flex: none;
		width: 0.875rem;
		height: 0.875rem;
		margin-top: 0.1875rem;
	}

	/* The hint shares the message row and gives way to an error. */
	.field__hint {
		grid-column: 1;
		grid-row: 1;
		padding-top: var(--space-2);
		transition: opacity var(--duration-fast) var(--ease-out);
	}

	.field[data-invalid] .field__hint {
		opacity: 0;
	}

	.field__count {
		grid-column: 2;
		grid-row: 1;
		padding-top: var(--space-2);
		font-variant-numeric: tabular-nums;
		transition: color var(--duration-fast) var(--ease-out);
	}

	.field__count[data-near] {
		color: var(--destructive);
	}

	/* Invalid: line, focus line, label and mark in the error colour. */
	.field[data-invalid] .field__box::before,
	.field[data-invalid] .field__box::after {
		background: var(--destructive);
	}

	.field[data-invalid] .field__label,
	.field[data-invalid] .field__mark,
	.field[data-invalid] .field__control:focus + .field__label {
		color: var(--destructive);
	}

	.field[data-invalid] .field__control {
		caret-color: var(--destructive);
	}

	.field:has(.field__control:disabled) {
		opacity: 0.5;
		pointer-events: none;
	}

	/* ---- Form-level messages ---------------------------------------- */
	.form-note {
		font-size: var(--type-caption-size);
		line-height: var(--type-caption-line);
		color: var(--subtle-foreground);
	}

	.form-note a {
		color: var(--muted-foreground);
	}

	.form-note a:is(:hover, :focus-visible) {
		color: var(--heading);
	}

	/*
	 * Status line after a round trip to the server: a quiet alert with a
	 * fine left rule, burgundy for success, the error colour otherwise.
	 */
	.form-status {
		padding: var(--space-3) var(--space-4);
		font-size: var(--type-small-size);
		line-height: var(--type-small-line);
		color: var(--heading);
		background: var(--card);
		box-shadow: inset 2px 0 var(--primary);
		animation: form-status-in var(--duration-base) var(--ease-out);
	}

	/* Focused on return only so it is read out; no ring for a message. */
	.form-status:focus,
	.form-status:focus-visible {
		outline: none;
	}

	.form-status--error {
		color: var(--heading);
		box-shadow: inset 2px 0 var(--destructive);
	}

	.form-status a {
		color: inherit;
		text-underline-offset: 0.2em;
	}

	@keyframes form-status-in {
		from { opacity: 0; translate: 0 calc(var(--motion-nudge) * -1); }
	}

	/* Submit while sending: quiet, and not clickable twice. A sending or
	   disabled button keeps its outline; the fill does not tint in. */
	.button[aria-disabled="true"] {
		cursor: progress;
		opacity: 0.7;
	}

	.button:disabled {
		cursor: not-allowed;
		opacity: 0.5;
	}

	.button:is([aria-disabled="true"], :disabled):is(:hover, :focus-visible) {
		color: var(--button-foreground);
	}

	.button:is([aria-disabled="true"], :disabled):is(:hover, :focus-visible)::before {
		background-color: transparent;
	}

	/* Honeypot: out of sight for people, present for form-filling bots. */
	.form-trap {
		position: absolute;
		left: -9999px;
		width: 1px;
		height: 1px;
		overflow: hidden;
	}
}
