/* ==========================================================================
   Bluefort Stat Cards — Figma 6497:39

   A grid of statistic cards whose figures count up, with an optional
   full-width note bar under them.

   Every rule that names a package class is written TWICE in one selector list:
   the bare form and the `#top #wrap_all` form. Enfold scopes everything to
   #top, and its generated colour CSS sits at (2,1,1) — two ids — so a single
   `#top` prefix loses. Both halves, always, including the defensive ones.

   No !important. No margin or padding shorthand, `margin-block` included.

   1. Registered properties
   2. Tokens
   3. Cap-height trimming
   4. The grid
   5. The card
   6. The note bar
   7. The counting figures
   8. Responsive
   ========================================================================== */

/* 1. Registered properties ==================================================
   The trim tokens MUST be registered: getComputedStyle().getPropertyValue()
   on an unregistered custom property returns the literal calc() token stream,
   so parseFloat(...) || 0 is 0 — and every harness that converts border boxes
   to cap boxes silently stops converting.

   --bf-fb is the ONE fallback switch, and it is deliberately project-wide, not
   package-scoped: bf-stats declares it identically, and whichever sheet loads
   first the value is the same.
   ========================================================================== */

@property --bf-fb {
	syntax: "<number>";
	inherits: true;
	initial-value: 0;
}

@property --bf-cards-tt {
	syntax: "<length>";
	inherits: false;
	initial-value: 0px;
}

@property --bf-cards-tb {
	syntax: "<length>";
	inherits: false;
	initial-value: 0px;
}

/* 2. Tokens ================================================================
   Colour and margin tokens are re-emitted INLINE by the render. The values
   below are their fallbacks and must match it value for value — asserted by
   preview/validate.php.
   ========================================================================== */

.bf-cards,
#top #wrap_all .bf-cards {
	--bf-fb: 0;

	/* Re-emitted inline by the render. */
	--bf-cards-mt: 0px;
	--bf-cards-mb: 0px;
	--bf-cards-card-bg: #E6EDF6;
	--bf-cards-value-c: #1C1C1C;
	--bf-cards-label-c: #595959;
	--bf-cards-note-bg: #D9E4F1;
	--bf-cards-note-c: #1C1C1C;

	/* The responsive ramp reads the margin into this and never re-declares
	   the token itself — re-declaring it would discard the panel value. */
	--bf-cards-mt-now: var(--bf-cards-mt);

	--bf-cards-font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

	--bf-cards-gap: 8px;
	--bf-cards-radius: 8px;

	/* 40px across the design's 1408px frame. A proportion of the CONTAINER,
	   not the viewport: written as a length it eats a much larger share of a
	   narrow card than of the design's 275px one. */
	--bf-cards-pad: clamp(24px, 2.8409cqi, 40px);
	--bf-cards-note-pad-x: clamp(24px, 2.8409cqi, 40px);
	--bf-cards-note-pad-y: clamp(20px, 1.7045cqi, 24px);

	--bf-cards-value-fs: 1.875rem;       /* 30 */
	--bf-cards-value-lh-ratio: 1.13333;  /* 34 / 30 */
	--bf-cards-value-ls: -0.04em;        /* −1.2px at 30px */

	--bf-cards-label-fs: 1rem;
	--bf-cards-label-lh-ratio: 1.5;      /* 24 / 16 */

	--bf-cards-note-fs: 1.25rem;         /* 20 */
	--bf-cards-note-lh-ratio: 1.2;       /* 24 / 20 */
	--bf-cards-note-ls: -0.01em;         /* −0.2px at 20px */

	--bf-cards-stack: 32px;              /* figure cap box → label cap box */

	/* Inter, read from the variable font: upem 2048, hhea ascender 1984,
	   descender −494, cap height 1490, USE_TYPO_METRICS set. Design constants
	   — never overridden by a harness. */
	--bf-cards-asc: 0.96875;
	--bf-cards-desc: 0.2412109375;
	--bf-cards-cap: 0.7275390625;

	/* Unregistered copies the trim reads. A harness overrides THESE to force
	   its own fallback pass; the constants above also feed rhythm values, so
	   overriding them wholesale would move the design and report the
	   difference as a trim bug. */
	--bf-cards-asc-t: var(--bf-cards-asc);
	--bf-cards-desc-t: var(--bf-cards-desc);
	--bf-cards-cap-t: var(--bf-cards-cap);
}

/* 3. Cap-height trimming ===================================================
   Figma positions this grid by CAP boxes: the 30px figure is 22px tall, not
   34px, and the 32px gap below it is cap box to last baseline. The card is
   40 + 22 + 32 + 36 + 40 = 170 tall because of it.

     half-leading = (line box − (asc + desc) × font-size) ÷ 2
     trim-top     = half-leading + (asc − cap) × font-size
     trim-bottom  = half-leading + desc × font-size

   The full formula, not (lh − fs × cap) ÷ 2: the short form is only equal to
   it when asc − desc happens to equal cap.
   ========================================================================== */

.bf-cards .bf-cards-t,
#top #wrap_all .bf-cards .bf-cards-t {
	/* A block container with inline content — never a flex row, a list, or a
	   box carrying padding or a background. The card and the note bar both
	   have both, which is exactly why the trim sits on the <p> inside them:
	   text-box shrinks the CONTENT box while the fallback's negative margins
	   move the BORDER box, so a padded box would lose its padding in one
	   branch only. */
	display: block;

	--bf-cards-lead: calc((var(--bf-cards-lh) - (var(--bf-cards-asc-t) + var(--bf-cards-desc-t)) * var(--bf-cards-fs)) / 2);
	--bf-cards-tt: calc(var(--bf-fb) * (var(--bf-cards-lead) + (var(--bf-cards-asc-t) - var(--bf-cards-cap-t)) * var(--bf-cards-fs)));
	--bf-cards-tb: calc(var(--bf-fb) * (var(--bf-cards-lead) + var(--bf-cards-desc-t) * var(--bf-cards-fs)));

	text-box-trim: trim-both;
	text-box-edge: cap alphabetic;
	text-box: trim-both cap alphabetic;

	margin-block-start: calc(-1 * var(--bf-cards-tt));
	margin-block-end: calc(-1 * var(--bf-cards-tb));
}

/* `@supports not (shorthand)` is not "no support": `text-box` shipped as the
   two longhands first, so a browser that is ALREADY trimming answers true to
   `not (text-box: …)` and would get the fallback on top of a trim that has
   already happened. Guard on both. One declaration in the block, so a harness
   can undo exactly one thing to force the other branch. */
@supports not ((text-box: trim-both cap alphabetic) or (text-box-trim: trim-both)) {

	.bf-cards,
	#top #wrap_all .bf-cards {
		--bf-fb: 1;
	}
}

/* 4. The grid ============================================================== */

.bf-cards,
#top #wrap_all .bf-cards {
	display: grid;

	/* So the padding above can size itself against THIS box rather than the
	   viewport. A container cannot query itself, and nothing here does — the
	   cqi is read by the card and the note bar. */
	container-type: inline-size;

	grid-template-columns: minmax(0, 1fr);
	column-gap: var(--bf-cards-gap);
	row-gap: var(--bf-cards-gap);
	align-items: stretch;
	margin-top: var(--bf-cards-mt-now);
	margin-bottom: var(--bf-cards-mb);
	font-family: var(--bf-cards-font);
}

/* One block per count the render can emit; preview/validate.php asserts this
   set and the --n* set match in both directions. n0 is the note bar on its
   own, which is a legal instance. */
.bf-cards--n0,
#top #wrap_all .bf-cards--n0 {
	grid-template-columns: minmax(0, 1fr);
}

.bf-cards--n1,
#top #wrap_all .bf-cards--n1 {
	grid-template-columns: minmax(0, 1fr);
}

.bf-cards--n2,
#top #wrap_all .bf-cards--n2 {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.bf-cards--n3,
#top #wrap_all .bf-cards--n3 {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.bf-cards--n4,
#top #wrap_all .bf-cards--n4 {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

.bf-cards--n5,
#top #wrap_all .bf-cards--n5 {
	grid-template-columns: repeat(5, minmax(0, 1fr));
}

/* Six wraps to three and three rather than leaving one card alone on a row. */
.bf-cards--n6,
#top #wrap_all .bf-cards--n6 {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* 5. The card ============================================================== */

.bf-cards .bf-cards__card,
#top #wrap_all .bf-cards .bf-cards__card {
	display: flex;
	flex-direction: column;
	align-items: stretch;

	/* Top, not centre. The design draws five cards whose labels are one or two
	   lines, and the grid already makes them equal height; centring would
	   float each figure to its own height the moment a label runs long. */
	justify-content: flex-start;
	row-gap: var(--bf-cards-stack);

	padding-block-start: var(--bf-cards-pad);
	padding-block-end: var(--bf-cards-pad);
	padding-inline-start: var(--bf-cards-pad);
	padding-inline-end: var(--bf-cards-pad);

	background-color: var(--bf-cards-card-bg);
	border-radius: var(--bf-cards-radius);
	text-align: center;
	overflow-wrap: break-word;
}

.bf-cards .bf-cards__value,
#top #wrap_all .bf-cards .bf-cards__value {
	--bf-cards-fs: var(--bf-cards-value-fs);
	--bf-cards-lh: calc(var(--bf-cards-value-lh-ratio) * var(--bf-cards-fs));

	margin-inline-start: 0;
	margin-inline-end: 0;
	padding-block-start: 0;
	padding-block-end: 0;
	padding-inline-start: 0;
	padding-inline-end: 0;
	max-width: 100%;
	font-family: var(--bf-cards-font);
	font-size: var(--bf-cards-fs);
	font-weight: 600;
	font-style: normal;
	line-height: var(--bf-cards-lh);
	letter-spacing: var(--bf-cards-value-ls);
	color: var(--bf-cards-value-c);
	text-align: center;
}

.bf-cards .bf-cards__label,
#top #wrap_all .bf-cards .bf-cards__label {
	--bf-cards-fs: var(--bf-cards-label-fs);
	--bf-cards-lh: calc(var(--bf-cards-label-lh-ratio) * var(--bf-cards-fs));

	margin-inline-start: 0;
	margin-inline-end: 0;
	padding-block-start: 0;
	padding-block-end: 0;
	padding-inline-start: 0;
	padding-inline-end: 0;
	max-width: 100%;
	font-family: var(--bf-cards-font);
	font-size: var(--bf-cards-fs);
	font-weight: 400;
	font-style: normal;
	line-height: var(--bf-cards-lh);
	letter-spacing: normal;
	color: var(--bf-cards-label-c);
	text-align: center;
}

/* 6. The note bar ==========================================================
   Spans every column, whatever the column count. flow-root so the trimmed
   paragraph's negative margins cannot escape the bar.
   ========================================================================== */

.bf-cards .bf-cards__note,
#top #wrap_all .bf-cards .bf-cards__note {
	grid-column: 1 / -1;
	display: flow-root;

	padding-block-start: var(--bf-cards-note-pad-y);
	padding-block-end: var(--bf-cards-note-pad-y);
	padding-inline-start: var(--bf-cards-note-pad-x);
	padding-inline-end: var(--bf-cards-note-pad-x);

	background-color: var(--bf-cards-note-bg);
	border-radius: var(--bf-cards-radius);
}

.bf-cards .bf-cards__note-text,
#top #wrap_all .bf-cards .bf-cards__note-text {
	--bf-cards-fs: var(--bf-cards-note-fs);
	--bf-cards-lh: calc(var(--bf-cards-note-lh-ratio) * var(--bf-cards-fs));

	margin-inline-start: 0;
	margin-inline-end: 0;
	padding-block-start: 0;
	padding-block-end: 0;
	padding-inline-start: 0;
	padding-inline-end: 0;
	max-width: 100%;
	font-family: var(--bf-cards-font);
	font-size: var(--bf-cards-fs);
	font-weight: 500;
	font-style: normal;
	line-height: var(--bf-cards-lh);
	letter-spacing: var(--bf-cards-note-ls);
	color: var(--bf-cards-note-c);
	text-align: center;
}

/* Enfold underlines and border-bottoms every link inside #top #wrap_all. */
.bf-cards .bf-cards__label a,
#top #wrap_all .bf-cards .bf-cards__label a,
.bf-cards .bf-cards__note-text a,
#top #wrap_all .bf-cards .bf-cards__note-text a {
	color: inherit;
	text-decoration: underline;
	border-bottom-width: 0;
	border-bottom-style: none;
}

/* 7. The counting figures ==================================================
   Tabular figures and an inline-block box, so the script can pin the width to
   the FINAL figure before the count starts: 0 … 92 is never wider than 92, so
   nothing beside it moves while the number changes. The span's line-height is
   the parent's, so the line box — and therefore the cap box — is unchanged.
   ========================================================================== */

.bf-cards .bf-cards__num,
#top #wrap_all .bf-cards .bf-cards__num {
	display: inline-block;
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum" 1;

	/* Right, not centre. The box is pinned to the FINAL figure's width, so a
	   shorter intermediate value leaves slack inside it; centred, that slack
	   splits and "100%" reads as "89 %" all the way up. Ending the digits at
	   the box's right edge keeps the suffix against them. */
	text-align: right;
	white-space: pre;
}

/* 8. Responsive ============================================================
   The ramp reads the inline margin token into --bf-cards-mt-now and never
   re-declares the token itself. With "Scale the top margin" off, the render
   omits .bf-cards--scale and none of these can match.
   ========================================================================== */

@media (max-width: 1199px) {

	.bf-cards--scale,
	#top #wrap_all .bf-cards--scale {
		--bf-cards-mt-now: calc(var(--bf-cards-mt) * 0.75);
	}
}

@media (max-width: 899px) {

	.bf-cards--scale,
	#top #wrap_all .bf-cards--scale {
		--bf-cards-mt-now: calc(var(--bf-cards-mt) * 0.6);
	}
}

/* Below the design's own width there is not enough room for five cards of
   readable text. Three across, then two, then one. Every block names the
   counts it changes, at one specificity, later in the file than the base. */
@media (min-width: 901px) and (max-width: 1300px) {

	.bf-cards--n4,
	#top #wrap_all .bf-cards--n4,
	.bf-cards--n5,
	#top #wrap_all .bf-cards--n5,
	.bf-cards--n6,
	#top #wrap_all .bf-cards--n6 {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (min-width: 601px) and (max-width: 900px) {

	.bf-cards--n3,
	#top #wrap_all .bf-cards--n3,
	.bf-cards--n4,
	#top #wrap_all .bf-cards--n4,
	.bf-cards--n5,
	#top #wrap_all .bf-cards--n5,
	.bf-cards--n6,
	#top #wrap_all .bf-cards--n6 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 600px) {

	.bf-cards,
	#top #wrap_all .bf-cards {
		grid-template-columns: minmax(0, 1fr);
	}
}
