/* Stats & Facts — About §4 (Figma 11016:4384, section 11016:4386).

   Two coordinate systems, deliberately:

   - HORIZONTAL PLACEMENT is percentages of the module box. The six tracks below
     sum to 100% and are the frame's own x-offsets over 1600, so the section holds
     its proportions at any row width (the 01-hero-banner precedent).
   - EVERY DRAWN SIZE is `calc(<frame px> * var(--tbl-sf-u))`, and --tbl-sf-u is
     measured off the BB ROW's content box by the JS — the same box the tracks are
     percentages of, so a drawn size never overflows the track holding it.

   Both systems therefore share one scale, and that scale is the row's box rather
   than the viewport. The row ships BB's default 20px side padding (Ben's call,
   the same one taken on 01-hero-banner), so at a 1600px viewport the box is 1560
   and the section renders a faithful 0.975 of the frame: proportion-congruent,
   2.5% smaller than Chris drew. Setting the row's left/right padding to 0 is the
   one change that makes it pixel-congruent as well.

   Numbers are 127px because 127 is where Sequel Sans puts its figures at the
   frame's measured 91px figure height and 263px "1999" — measured off the live
   face via canvas actualBoundingBox, not inferred. Tracking is 0: the same probe
   returns 262.64px with no letter-spacing at all.

   Frame defect NOT reproduced: stat 3's number box is 139 tall in Figma where the
   other four are 168. It is a stale text box, not an intent — all five render at
   one treatment (ticket 03).

   BB owns section spacing — no padding, width or min-height here. */

.tbl-stats-facts {
	/* Written by the JS from the BB ROW's content box, not the viewport: the grid
	   tracks below are percentages of that box, so scaling the drawn sizes off
	   anything else puts the two out of step (round 1 measured a 203.86px card in a
	   178.38px track inside a fixed-width 1400 row). 100vw is the pre-JS fallback
	   only, and only correct on a full-width row. */
	--tbl-sf-vw: 100vw;
	/* Proportional to the frame from 1024 up, pinned at 1.0 from 1600 up. */
	--tbl-sf-u: clamp(0.64px, calc(var(--tbl-sf-vw) / 1600), 1px);

	--tbl-sf-card-w: calc(203.86 * var(--tbl-sf-u));
	/* Derived from the width, not from --u, so it stays true in the tablet tier
	   where the card takes a viewport clamp instead. 303.03 / 203.86. */
	--tbl-sf-card-h: calc(var(--tbl-sf-card-w) * 1.48646);
	/* The frame draws the deck group 382 against a 303.03 card (11016:4733), so 78.97
	   is the depth of the WHOLE stack. The JS splits it across the gaps — every card
	   behind the top one steps down and back by a share of it. Kept here as the
	   frame's number; the JS derives its own from the measured card, never by reading
	   this back (an unregistered custom property returns its token stream, not a px). */
	--tbl-sf-sliver: calc(78.97 * var(--tbl-sf-u));
	--tbl-sf-radius: calc(10 * var(--tbl-sf-u));
	--tbl-sf-item-gap: calc(82 * var(--tbl-sf-u));
	--tbl-sf-number-size: calc(127 * var(--tbl-sf-u));
	--tbl-sf-number-lh: calc(168 * var(--tbl-sf-u));

	display: grid;
	/* 60 / 498.92 / 332.08 / 191.07 / 203.86 / 314.07 over 1600. */
	grid-template-columns: 3.75% 31.1825% 20.755% 11.9419% 12.74125% minmax(0, 1fr);
	grid-template-areas: ". eyebrow stats . deck .";
	align-items: start;
	padding: 0;
}

/* The one rule in this file that reaches outside the module, and it is here because
   the collision it fixes is caused by this module.

   §4's top card exits UPWARD out of its own row, and §3 — a full-bleed photo strip —
   is still on screen above it for the whole of the first step. Beaver Builder rows
   are siblings at the same stacking level, so §4 paints over §3 by DOM order and the
   departing card lands on top of §3's photographs: two photo modules of the same
   visual family overlapping, which reads as a mistake rather than as depth. Fading
   the card out there is not available — it enters that band while still half on
   screen, so it would vanish mid-viewport and read as a bug.

   Lifting §3's row one level instead makes the card pass BEHIND the strip, which is
   the read the motion wants anyway. #tb-site-header is z-index 9998, so 1 stays well
   under it. Scoped by :has() to the row that actually holds §3, and this stylesheet
   is only enqueued on a page carrying §4. */
.fl-row:has(.tbl-rotating-photos) {
	position: relative;
	z-index: 1;
}

/* ---------------------------------------------------------------- eyebrow ---- */

.tbl-stats-facts__eyebrow {
	grid-area: eyebrow;
	min-width: 0;
	/* Frame y=100 against the section's own top edge. */
	margin: calc(100 * var(--tbl-sf-u)) 0 0;
	font-family: var(--body-font);
	/* H6: 16 at every viewport, but the theme's heading defaults are lh 0.95 and
	   ls -0.01em, so both need saying out loud. Weight 410 is unreachable. */
	font-size: 16px;
	line-height: 30.91px;
	letter-spacing: 0.32px;
	font-weight: 400;
	/* --header-color is #0f0f0f; the frame draws pure black. */
	color: var(--Black);
	/* NOT cased here: text-transform rewrites the accessible name in Chromium. */
	text-transform: none;
}

/* ------------------------------------------------------------------ stats ---- */

.tbl-stats-facts__stats {
	grid-area: stats;
	min-width: 0;
	display: flex;
	flex-direction: column;
	/* The frame's gap is a uniform 82 between item boxes on all four gaps. Held as
	   a flex gap so a caption that wraps to a third line pushes the column down
	   rather than eating the rhythm. */
	gap: var(--tbl-sf-item-gap);
	margin: calc(59 * var(--tbl-sf-u)) 0 0;
	padding: 0;
	list-style: none;
}

.tbl-stats-facts__stat {
	display: block;
	margin: 0;
	/* A theme rule puts padding-bottom: 6px on every li:not(:last-child); margin: 0
	   does not cancel it and it would inflate every item box but the last. */
	padding: 0;
	list-style: none;
}

.tbl-stats-facts__number {
	display: block;
	font-family: var(--header-font);
	font-size: var(--tbl-sf-number-size);
	/* 168 is the frame's number box. Holding it as the line box is also what puts
	   the caption's top edge exactly on the number's bottom edge — 0px gap. */
	line-height: var(--tbl-sf-number-lh);
	letter-spacing: 0;
	font-weight: 400;
	color: var(--Black);
	text-transform: none;
}

.tbl-stats-facts__label {
	display: block;
	/* The frame's caption box is a FIXED 63 in all five items, which is what makes
	   every stat item 231 tall (168 + 63) and the column 1454. A min-height rather
	   than a height: it reproduces the frame's two-line rhythm on the captions Chris
	   hard-broke to one line, without capping a caption that runs longer. */
	min-height: calc(63 * var(--tbl-sf-u));
	margin: 0;
	font-family: var(--body-font);
	/*
	 * NOT Paragraph - Large. Round 2 shipped 20/30 and the captions stopped
	 * wrapping, which cost the section ~200px of its height and the design its
	 * two-line rhythm. Measured off the frame instead, three ways that agree:
	 *   - the 63px box is two lines at Figma's "Auto" leading for this face
	 *     (fontBoundingBox 1.1732em), so 63 / 2 / 1.1732 = 26.85;
	 *   - "Best Places to Work Awards" fills the 332.08 column to 98% at 26.85 and
	 *     renders on ONE line in the frame, which caps the size at 27.31;
	 *   - "The year we founded the company" wraps at anything over 22.2.
	 * Tracking is 0, not the +1% the other captions on this site carry: at +1%
	 * "Best Places to Work Awards" measures 333.2 in a 332.08 column and would
	 * wrap, and the frame does not wrap it.
	 */
	font-size: max(18px, calc(26.85 * var(--tbl-sf-u)));
	line-height: calc(31.5 / 26.85);
	letter-spacing: 0;
	font-weight: 400;
	color: var(--Black);
}

/* ------------------------------------------------------------------- deck ---- */

.tbl-stats-facts__deck {
	grid-area: deck;
	min-width: 0;
	margin: calc(59 * var(--tbl-sf-u)) 0 0;
	/* Stretched, so the sticky child's containing block is as tall as the stats
	   column and the deck unpins at the section's end rather than over §5. */
	align-self: stretch;
}

.tbl-stats-facts__cards {
	display: flex;
	flex-direction: column;
	gap: calc(24 * var(--tbl-sf-u));
	margin: 0;
	padding: 0;
	list-style: none;
}

.tbl-stats-facts__card {
	position: relative;
	width: var(--tbl-sf-card-w);
	aspect-ratio: 203.86 / 303.03;
	margin: 0;
	padding: 0;
	overflow: hidden;
	border-radius: var(--tbl-sf-radius);
	list-style: none;
	background-color: var(--Neutral-10, #f2f2f2);
	/* Load-bearing, not decoration. The stacked cards show only ~9.6px of each
	   other's edge and nothing else separates them, so wherever two photos happen
	   to be dark at that seam the ledges merge and five cards read as one band.

	   The blur has to stay UNDER the ledge it fills. At the original 19.25px ledge
	   a 12px blur read fine; when the ledge halved, that falloff was wider than the
	   gap and stopped registering on dark-on-dark pairs. Tighter and darker instead
	   — same total weight, resolved inside 9.6px. Re-tune this if the stack depth
	   changes again; the two numbers are coupled. */
	box-shadow: 0 calc(1.5 * var(--tbl-sf-u)) calc(5 * var(--tbl-sf-u)) rgba(0, 0, 0, 0.3);
}

.tbl-stats-facts__media {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

/* --------------------------------------------------------------- stacked ---- */
/*
   Everything above is the JS-off state and it is the one a reduced-motion reader,
   a GSAP load failure and the BB editor all get: five cards in a readable column,
   in flow, nothing pinned, nothing overlapping. `is-stacked` is added by the JS
   only inside (min-width: 1024px) and (prefers-reduced-motion: no-preference).
*/

.tbl-stats-facts.is-stacked .tbl-stats-facts__deck {
	/* Both values are half the difference between a stat item's height and the
	   card's, measured by the JS. A deck sharing the stats column's top edge would
	   engage its pin after stat 1 had already crossed viewport middle and release it
	   before stat 5 got there; these two put the pin's edges exactly on the scrub's.
	   The negative tail deliberately runs the deck past the grid row — it is the
	   sticky containing block, not a visible box. */
	margin-top: calc((59 * var(--tbl-sf-u)) + var(--tbl-sf-deck-head, 0px));
	margin-bottom: var(--tbl-sf-deck-tail, 0px);
}

.tbl-stats-facts.is-stacked .tbl-stats-facts__deck-sticky {
	position: sticky;
	/* Pinned to the VERTICAL CENTRE of the viewport, not the top and not where
	   Figma draws the group (y = -26 is a drawing position). CSS sticky, not
	   ScrollTrigger's pin: .tb-reveal-content is a transformed ancestor sitewide,
	   which breaks position:fixed pinning in Chrome 116+/Safari 26+ while still
	   working in Firefox. */
	top: calc(50vh - (var(--tbl-sf-card-h) / 2));
}

.tbl-stats-facts.is-stacked .tbl-stats-facts__cards {
	display: block;
	position: relative;
	height: var(--tbl-sf-card-h);
}

.tbl-stats-facts.is-stacked .tbl-stats-facts__card {
	position: absolute;
	inset: 0 auto auto 0;
	/* The authored order is the stack order: card 0 on top, the rest behind it. */
	z-index: calc(100 - var(--tbl-sf-i, 0));
	will-change: transform;
}

/* ----------------------------------------------------------- 577 to 1023 ---- */
/* No pin. The five cards stand as a static list beside the stats. */

@media (max-width: 1023px) {

	.tbl-stats-facts {
		--tbl-sf-u: clamp(0.5px, calc(var(--tbl-sf-vw) * 0.00022082 + 0.4139px), 0.64px);
		--tbl-sf-card-w: clamp(150px, 22vw, 220px);

		/* Both tracks sized to content and the pair centred, rather than a 1fr stats
		   column shoving the deck out to the right edge (Pastel #80). */
		grid-template-columns: minmax(0, max-content) auto;
		grid-template-areas:
			"eyebrow eyebrow"
			"stats   deck";
		column-gap: calc(40 * var(--tbl-sf-u));
		justify-content: center;
	}

	.tbl-stats-facts__eyebrow {
		margin: 0 0 40px;
	}

	.tbl-stats-facts__stats,
	.tbl-stats-facts__deck {
		margin-top: 0;
	}

	.tbl-stats-facts__cards {
		gap: 24px;
	}

	/* Pair each stat with its card (Pastel #81): give the stat the card's own pitch
	   — card height + the 24px deck gap — so item N lines up with image N all the
	   way down, and centre the stat inside that box. */
	.tbl-stats-facts__stats {
		gap: 24px;
	}

	.tbl-stats-facts__stat {
		min-height: var(--tbl-sf-card-h);
		display: flex;
		flex-direction: column;
		justify-content: center;
	}
}

/* ------------------------------------------------------------ 576 and down ---- */
/* Images removed entirely — the stats stand alone (ticket 03, Round 6). */

@media (max-width: 576px) {

	.tbl-stats-facts {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			"eyebrow"
			"stats";
	}

	.tbl-stats-facts__deck {
		display: none;
	}
}

/* ------------------------------------------------------------ row layout ---- */
/* Studios "About the space" (Figma 11834:2706): eyebrow at 60/1600, stats from
   347/1600 on one line with a 60 gap. No deck. */

.tbl-stats-facts--row {
	grid-template-columns: 3.75% 17.9375% minmax(0, 1fr);
	grid-template-areas: ". eyebrow stats";
}

.tbl-stats-facts--row .tbl-stats-facts__stats {
	flex-direction: row;
	align-items: flex-start;
	gap: calc(60 * var(--tbl-sf-u));
}

/* 330 / 285 / 293: the frame's three columns (11834:2709-2716). A caption wraps
   inside its column rather than squeezing a neighbour. */
.tbl-stats-facts--row .tbl-stats-facts__stat {
	flex: 0 0 calc(300 * var(--tbl-sf-u));
	min-width: 0;
}

.tbl-stats-facts--row .tbl-stats-facts__stat:nth-child(1) {
	flex-basis: calc(330 * var(--tbl-sf-u));
}

.tbl-stats-facts--row .tbl-stats-facts__stat:nth-child(2) {
	flex-basis: calc(285 * var(--tbl-sf-u));
}

.tbl-stats-facts--row .tbl-stats-facts__stat:nth-child(3) {
	flex-basis: calc(293 * var(--tbl-sf-u));
}

/* This band sets its own type: 90/113 numbers at -1.5, 22/28 captions. */
.tbl-stats-facts--row .tbl-stats-facts__number {
	font-size: calc(90 * var(--tbl-sf-u));
	line-height: calc(113 * var(--tbl-sf-u));
	letter-spacing: calc(-1.5 * var(--tbl-sf-u));
	white-space: nowrap;
}

.tbl-stats-facts--row .tbl-stats-facts__label {
	min-height: calc(39 * var(--tbl-sf-u));
	font-size: max(16px, calc(22 * var(--tbl-sf-u)));
	line-height: calc(28 / 22);
}

@media (max-width: 1023px) {

	.tbl-stats-facts--row {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			"eyebrow"
			"stats";
		justify-content: stretch;
	}

	.tbl-stats-facts--row .tbl-stats-facts__stats {
		gap: 40px;
	}

	.tbl-stats-facts--row .tbl-stats-facts__stat {
		min-height: 0;
		display: block;
	}
}

@media (max-width: 767px) {

	.tbl-stats-facts--row .tbl-stats-facts__stats {
		flex-direction: column;
		gap: 32px;
	}

	.tbl-stats-facts--row .tbl-stats-facts__stat:nth-child(n) {
		flex-basis: auto;
	}
}

/* ------------------------------------------------------- row reveal ---- */
/* The eyebrow and the three stats carry the theme's `blur-up-in` (scroll-scrubbed
   blur + rise, theme.css) in row layout only; these rules stagger each column's
   start point so the four read as a cascade. The theme's own gates on that class
   cover reduced motion, the editor and widths under 1024. */

.tbl-stats-facts--row .tbl-stats-facts__stat:nth-child(1) {
	--start-tween: calc(clamp(80px, 20vh, 200px) + 6vh);
}

.tbl-stats-facts--row .tbl-stats-facts__stat:nth-child(2) {
	--start-tween: calc(clamp(80px, 20vh, 200px) + 12vh);
}

.tbl-stats-facts--row .tbl-stats-facts__stat:nth-child(3) {
	--start-tween: calc(clamp(80px, 20vh, 200px) + 18vh);
}
