/*
 * Section: Ranking factors.
 *
 * Loaded only on pages carrying the `factors` layout.
 *
 * ---------------------------------------------------------------------------
 * REUSABILITY IS THE PRIMARY CONSTRAINT. This renders on 20+ pages.
 *
 * Rules that keep it portable, all mechanically checkable:
 *
 *   1. Role tokens only (--sq-fg, --sq-border, --sq-rule, --sq-accent). No raw
 *      --sq-color-* palette values, so the section works on paper, concrete,
 *      cool, ink or black without a per-band variant.
 *   2. Surfaces are mixed from the foreground rather than named, so a tint is
 *      a faint dark wash on a light band and a faint light wash on a dark one,
 *      automatically.
 *   3. No selector reaches outside the section — no sibling combinators, no
 *      assumptions about what precedes or follows it.
 *   4. Nothing depends on the page. Only on the factor count, which comes from
 *      the content.
 * ---------------------------------------------------------------------------
 */


.factors__header {
	max-width: 68ch;
}


.factors__intro > * {
	margin: 0;
	text-wrap: pretty;
}

.factors__intro > * + * {
	margin-top: var(--sq-space-4);
}


/* ============================================================ FACTORS == */

.factors__list {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--sq-space-card-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.factors__cell {
	display: flex;
	margin: 0;
}

/* Equal heights: the cell stretches to the row, the factor fills the cell. */
.factor {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: var(--sq-space-3);
	padding: var(--sq-space-5);
}

/*
 * Three ways to draw a factor, and all three are painted from role tokens for
 * the reason at the top of this file: the section runs on 20+ pages across
 * every band, so a named colour anywhere here means a per-band variant.
 *
 * `rule` is what the comps draw and stays the default.
 */
.factors--style-rule .factor {
	border-top: 3px solid var(--sq-border);
}

.factors--style-bordered .factor {
	border: var(--sq-border-width) solid var(--sq-border);
}

/*
 * The shadow takes --sq-border, not --sq-shadow-raised. That token is declared
 * as ink, which is invisible the moment this section lands on the dark ramp —
 * and this is the one section guaranteed to get there eventually. --sq-border
 * is ink on a light band and paper on a dark one, so the shadow follows.
 *
 * The box is filled with the band's own colour so the shadow cannot show
 * through it; on any band that is exactly the surface behind it, which is what
 * keeps the offset reading as a shadow rather than as a second border.
 */
.factors--style-raised .factor {
	border: var(--sq-border-width) solid var(--sq-border);
	background-color: var(--sq-bg);
	box-shadow: 6px 6px 0 var(--sq-border);
}

/*
 * The numeral. Trust colour, above the title — `--sq-link` is Trade Blue on a
 * light band and paper on a dark one, so it stays legible where a literal blue
 * would go to about 2:1 on near-black.
 *
 * Generated in PHP and aria-hidden; see the note in the template.
 */
.factors--numbered .factor__number {
	margin: 0;
	color: var(--sq-link);
	font-family: var(--sq-font-display);
	font-size: var(--sq-text-h3);
	font-weight: var(--sq-weight-bold);
	line-height: 0.9;
}

.factor__title {
	margin: 0;
	font-size: var(--sq-text-h3);
	font-weight: var(--sq-weight-semibold);
	line-height: 1.25;
	text-wrap: balance;
}

.factor__body > * {
	margin: 0;
}

.factor__body > * + * {
	margin-top: var(--sq-space-3);
}


/* ========================================================== LIMITATION ==
 *
 * Candour, not caution.
 *
 * The differentiation is a stated label plus the faintest wash — no colour
 * shift, no icon, no heavier border, nothing borrowed from an error state.
 * The label is what makes the tint legible as honesty; without it the reader
 * only knows this one looks different.
 *
 * color-mix from the foreground rather than a named surface, so it stays a
 * faint wash whichever band the section lands on. Browsers without support
 * drop the declaration and get no tint, which is a fine outcome — the label
 * still carries the meaning.
 */

.factor--limitation {
	background-color: color-mix(in srgb, var(--sq-fg) 5%, transparent);
}

.factor__label {
	margin: 0;
	color: var(--sq-fg-muted);
	font-size: var(--sq-text-label-sm);
	font-weight: var(--sq-weight-bold);
	letter-spacing: var(--sq-tracking-label-sm);
	line-height: 1.4;
	text-transform: uppercase;
}


/* ============================================================ DIAGRAM == */

.factors__diagram {
	margin: 0;
}

.factors__diagram-image {
	display: block;
	width: 100%;
	height: auto;
	border: var(--sq-border-width) solid var(--sq-border);
}

/*
 * A vector figure draws its own frame, so the theme must not draw a second
 * one. Same rule and same reasoning as `narrative` — a raster upload is a
 * screenshot with no edge of its own, a vector here is a schematic drawn in
 * the theme's own vocabulary that already carries its border.
 */
.factors--diagram-vector .factors__diagram-image,
.factors--detail-vector .factors__detail-image {
	border: 0;
}


/* ============================================================== DETAIL ==
 *
 * Prose beside a figure — the "measured from where?" block in the Maps SEO
 * comp. Optional, and absent it costs nothing: the wrapper is a flex column,
 * so a gap only exists between children that exist.
 *
 * Stacked by default and two columns from 980px, because a 430px figure beside
 * a 62ch measure needs the full container before either is worth having.
 */

.factors__detail {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sq-space-6);
	align-items: start;
}

.factors__detail-copy {
	display: flex;
	flex-direction: column;
	gap: 1.125rem; /* 18 — the comp's paragraph rhythm in this block */
	/* The comp's 62ch, in `ch` so the line length tracks the font rather than
	 * a pixel guess. Inside 60–72 either way. */
	max-width: 62ch;
}

.factors__detail-title {
	margin: 0;
	font-size: var(--sq-text-h3);
	font-weight: var(--sq-weight-semibold);
	line-height: 1.15;
	text-wrap: balance;
}

/*
 * The statement. Set in the BODY face rather than the condensed one, and that
 * is the point: condensed at this size is the vocabulary of a heading, and
 * this is a paragraph said louder. It sits under an H3 that is already the
 * lowest rung this section uses.
 */
.factors__detail-lead {
	margin: 0;
	font-family: var(--sq-font-body);
	font-size: var(--sq-text-lead);
	font-weight: var(--sq-weight-bold);
	line-height: 1.3;
	text-wrap: pretty;
}

/*
 * Type rules target the elements at any depth, never `> *`. A wysiwyg that has
 * been pasted into arrives wrapped, and `> *` would then style the wrapper
 * while base.css sizes the paragraph inside it — see the long note in
 * narrative.css.
 */
.factors__detail-body > * {
	margin: 0;
	text-wrap: pretty;
}

.factors__detail-body > * + * {
	margin-top: 1.125rem; /* 18 */
}

.factors__detail-body :is(p, ul, ol) {
	line-height: 1.55;
}

.factors__detail-body ul,
.factors__detail-body ol {
	padding-left: 1.25em;
}

.factors__detail-figure {
	margin: 0;
	max-width: 26.875rem; /* 430 — the comp's cap */
}

.factors__detail-image {
	display: block;
	width: 100%;
	height: auto;
	border: var(--sq-border-width) solid var(--sq-border);
}

.factors__detail-caption {
	margin-top: var(--sq-space-3);
	color: var(--sq-fg-muted);
	font-size: var(--sq-text-small);
	line-height: var(--sq-leading-normal);
}


/* ============================================================ CONTROLS ==
 *
 * What can and cannot be moved, as two lists side by side. Fenced off by a
 * rule above rather than by air — the design system's own rule for separating
 * one thing from another, and what stops this reading as a third factor row.
 *
 * THE BOXES ARE BORDERED AND UNFILLED, which is a deliberate trade against the
 * comp. The comp paints them #FFFFFF on a concrete band, and this section may
 * not name a colour: it runs on 20+ pages across every band, and the role set
 * has no "one step lighter than the band" token to spend here — `--sq-bg` IS
 * the band. A tint mixed from --sq-fg goes the wrong way, darker rather than
 * lighter. So the border carries the box, exactly as `factors--style-bordered`
 * already does for the factors themselves. One vocabulary, no per-band variant.
 */

.factors__controls {
	padding-top: var(--sq-space-6);
	border-top: var(--sq-border-width) solid var(--sq-border);
}

.factors__controls-title {
	margin: 0 0 var(--sq-space-5);
	font-size: var(--sq-text-h3);
	font-weight: var(--sq-weight-semibold);
	line-height: 1.15;
	text-wrap: balance;
}

.factors__control-list {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	/* The comp's 8px: these two are a pair being compared, so they sit close
	 * enough to read as one object rather than as two unrelated boxes. */
	gap: var(--sq-space-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.factors__control-cell {
	display: flex;
	margin: 0;
}

.control-group {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: var(--sq-space-4);
	padding: var(--sq-space-5);
	border: var(--sq-border-width) solid var(--sq-border);
}

.control-group__label {
	margin: 0;
	color: var(--sq-fg-muted);
	font-size: var(--sq-text-label-sm);
	font-weight: var(--sq-weight-bold);
	letter-spacing: var(--sq-tracking-label-sm);
	line-height: 1.4;
	text-transform: uppercase;
}

.control-group__items {
	display: flex;
	flex-direction: column;
	gap: 0.625rem; /* 10 */
	margin: 0;
	padding: 0;
	list-style: none;
}

.control-group__item {
	display: grid;
	grid-template-columns: 0.75rem minmax(0, 1fr); /* 12 */
	gap: var(--sq-space-3);
	align-items: start;
	margin: 0; /* base.css spaces li + li; the flex gap owns it here */
	line-height: 1.45;
	text-wrap: pretty;
}

/*
 * THE MARKER CARRIES THE ARGUMENT, and it is the only difference between the
 * two lists. Filled for what we can move, hollow for what nobody can — no
 * colour shift, no icon, no strikethrough, nothing borrowed from an error
 * state. Same candour rule as `factor--limitation`: the label says it, the
 * marker shows it, and neither shouts.
 *
 * Drawn in CSS, in currentColor, so it follows the band with no dark variant
 * and never becomes a character read out before every line.
 */
.control-group__item::before {
	width: 0.75rem; /* 12 */
	height: 0.75rem;
	/* Sits on the cap height of the first line rather than its top edge. */
	margin-top: 0.4em;
	background-color: currentColor;
	content: '';
}

.control-group--limitation .control-group__item::before {
	border: var(--sq-border-width) solid currentColor;
	background-color: transparent;
}

.control-group__note > * {
	margin: 0;
	line-height: 1.55;
	text-wrap: pretty;
}

.control-group__note > * + * {
	margin-top: var(--sq-space-3);
}


/* ============================================================ CLOSING ==
 *
 * The trust moment. In the credibility style it is set apart and LARGER —
 * never smaller, never greyer. Small grey text at the end of a section is
 * what fine print looks like, and reading an admission as fine print is the
 * precise failure this style exists to prevent.
 */

.factors__closing {
	max-width: 68ch;
}

.factors__closing-body > * {
	margin: 0;
	text-wrap: pretty;
}

.factors__closing-body > * + * {
	margin-top: var(--sq-space-4);
}

.factors--closing-credibility .factors__closing {
	padding: var(--sq-space-5);
	border-left: var(--sq-border-width-accent) solid var(--sq-border);
	background-color: color-mix(in srgb, var(--sq-fg) 4%, transparent);
}

.factors--closing-credibility .factors__closing-body > * {
	font-size: var(--sq-text-lead);
	line-height: var(--sq-leading-relaxed);
}


/* ============================================================= DESKTOP ==
 *
 * Columns match the factor count, with one qualification: four columns need
 * the full container to stay readable, so four goes 2x2 between 980 and 1180
 * and only opens out above that. See the readability floors in CLAUDE.md.
 */

@media (min-width: 30em) {
	.factors__list {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 61.25em) {

	.factors--count-3 .factors__list {
		grid-template-columns: repeat(3, 1fr);
	}

	/*
	 * The detail block opens to two columns. The figure track is fixed at its
	 * 430px cap rather than a fraction, so the prose takes the slack on a wide
	 * screen and keeps its measure on a narrow one — the same arrangement
	 * `narrative` uses for a right-hand image, and for the same reason.
	 */
	.factors__detail {
		grid-template-columns: minmax(0, 1fr) minmax(0, 26.875rem); /* 430 */
		column-gap: var(--sq-space-gutter-desktop);
	}

	/* No figure: one column, and the measure already holds the prose. */
	.factors--detail-solo .factors__detail {
		grid-template-columns: minmax(0, 1fr);
	}

	/*
	 * Two lists side by side. Only at two — a lone list runs full width rather
	 * than sitting in half a row with nothing to compare it to, which is the
	 * same call `scope_of_work` makes about its divider.
	 */
	.factors--controls-2 .factors__control-list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.factors__controls {
		padding-top: var(--sq-space-6);
	}

	.factors--closing-credibility .factors__closing {
		padding: var(--sq-space-6);
	}
}

@media (min-width: 73.75em) {
	.factors--count-4 .factors__list {
		grid-template-columns: repeat(4, 1fr);
	}
}
