/*
 * bpd-two/timeline pattern (Who we are). Horizontal scroll + scroll-position-driven active
 * milestone: the item whose center is nearest the track's leading edge (left edge at desktop,
 * top edge at mobile) gets the green treatment (year+title text, dashed connector, dot); the
 * rest stay muted. The script's initial pass sets item 1 (2002) green — the Figma frame's
 * resting state (desktop 4788:30780 / mobile 4788:31108).
 *
 * DESKTOP LAYOUT IS CSS GRID + SUBGRID. Figma geometry (4788:30780): each item is 477px wide,
 * and the start-to-start pitch alternates 410px (above->below) / 434px (below->above).
 * Successive items interleave between an "above" row and a "below" row on opposite sides of the
 * base line, so adjacent items overlap horizontally without colliding. The track grid is
 * repeat(3, 410px 434px) columns + a tail, by three rows: above content / 4px base line /
 * below content. Each .bpd-timeline__item spans all three rows with grid-template-rows: subgrid, which
 * is what lets its copy block, dashed connector (::after) and dot (::before) each sit in the
 * correct shared row — the dot centered on the line row, the connector filling the content row
 * flush against the line, content offset 44px (spacing-1100; Figma measures 42–46px) from the
 * line. Auto-placement puts the six items in columns 1–6 in source order.
 *
 * Structure is real wp:group blocks only (.bpd-timeline > .bpd-timeline__item x6, alternating
 * --above/--below, each a constrained-layout group holding the copy + photo) — no bare decorative
 * wrapper elements, since core/group's save() is a plain InnerBlocks passthrough and any
 * hand-authored HTML between recognized children fails block validation (see timeline.php's
 * header). The track group's layout is "default" (not flex) so core emits no display/gap rules
 * against this grid. The base line, the per-item dashed connector (Figma "Line 30/32/33/34":
 * 224x2, stroke-dasharray "2 2") and the 12px dots (Figma "Ellipse 16") are pseudo-elements —
 * on a grid container, ::before/::after are real grid items, so they are placed with grid-row
 * rather than absolute positioning. The connector/dot sit 24px/28px left of the item's column
 * edge (Figma: item x=45, connector x=21, dot x=16), via negative margin-left.
 *
 * Figma values (4788:30780 design context): base line #b5bec9 (blue-300), 4px solid; the active
 * item's connector + dot + year/title are #78bf26 (green-600); inactive connectors are #b5bec9
 * (blue-300), inactive dots #f4f6f8 (blue-100), inactive year/title text neutral-100; the copy
 * stays neutral-100 in both states (Figma keeps it white on the active item too). Mobile
 * (4788:31108): same active treatment, but the track runs vertically — 2px base line down the
 * left edge, items stacked, the item nearest the top edge is the green one. No dashed connector
 * on mobile (the frame shows base line + dots only); the item ::after is reused to draw the base
 * line itself, one dot-to-dot segment per item — see the mobile block at the end of this file.
 *
 * Active-state switching is timeline.js (assets/js/timeline.js, page-gated in functions.php with
 * this sheet): it toggles an .is-active class on the nearest item. All transitions use
 * --wp--custom--motion--duration-sm (300ms) + ease, the theme's standard state-change token.
 *
 * Only loaded on the Who we are page (functions.php, is_page('who-we-are')) — .bpd-timeline is a
 * unique class, safe to also load into the editor canvas per the contact-form.css/columns-2up.css
 * exception to CLAUDE.md's page-gated-sheet exclusion (rule 7 parity).
 */

/* ============================= HOW THE DESKTOP GRID IS BUILT =============================
 *
 * One scrollable grid, 7 columns x 3 rows. Items are WIDER than their column on purpose —
 * each is 477px wide and overhangs into the next column. Because horizontal neighbours always
 * sit in opposite rows (above/below), the overhang never collides; it is what produces the
 * Figma interleave.
 *
 * The column pitch alternates rather than being uniform: 410px above->below, 434px below->above,
 * an 844px cycle. The "above" milestones sit on that 844px rhythm and each "below" milestone is
 * offset 13px back from the pair's midpoint.
 *
 *  col:      1          2          3          4          5          6        7(tail)
 *        |---410---|---434---|---410---|---434---|---410---|---434---|-43+gut-|
 * row 1  [ 2002==copy|photo==]         [ 2022==copy|photo==]  ...              (above)
 * row 2  ●---●------●--------●-------- 4px base line (::before, col 1/-1) --   (line)
 * row 3            [ 2005==copy|photo==]        [ 2023==copy|photo==]  ...     (below)
 *
 * - Track (.bpd-timeline): grid + overflow-x:auto = the scroll container.
 * - Rows: minmax(226px, auto) / 4px / minmax(226px, auto). 226px = Figma line-top (230)
 *   minus item-top (4); minmax lets a tall copy block grow the row for ALL items at once
 *   (they share rows via subgrid), keeping every connector/dot on the same axis.
 * - Base line: the track's own ::before, a grid item in row 2 spanning every column.
 * - Item (.bpd-timeline__item): spans rows 1-3, grid-template-rows: subgrid, so its three
 *   pieces are placed into the SHARED track rows:
 *       .bpd-timeline__row (the copy|photo flex row, the item's only content child)
 *                      -> row 1 (--above, anchored to the line: align-self end + 44px
 *                         padding-bottom) or row 3 (--below: align-self start + 44px
 *                         padding-top);
 *       ::after        -> dashed 224px connector in the item's content row, flush against
 *                         the line, 24px left of the item edge (negative margin);
 *       ::before       -> 12px dot in row 2, align-self center = centred on the line,
 *                         28px left of the item edge.
 * - Column placement is explicit (nth-child) — see the note on that rule.
 * ========================================================================================= */
.bpd-timeline {
	display: grid;
	/* Tail = the last milestone's 43px overhang past column 6 (477 - 434), without which the
	 * grid's scrollable width would clip it, plus one gutter of run-out. No more than that:
	 * timeline.js compresses its activation points into whatever scroll range exists, so the
	 * trailing milestones need no extra room to take their turn. */
	grid-template-columns: repeat( 3, 410px 434px ) calc( 43px + var( --wp--preset--spacing--gutter ) );
	/* Above content / base line / below content. 226px = Figma line-top (230) minus item-top (4). */
	grid-template-rows: minmax( 226px, auto ) var( --wp--custom--border--lg ) minmax( 226px, auto );
	overflow-x: auto;
	overflow-y: hidden;
	/* No scroll-snap: snap points are the geometric item starts, but timeline.js's activation
	 * points are compressed into the available scroll range, so the two don't coincide and a pip
	 * click gets pulled back to the previous milestone. */
	/* Track edge to the first milestone. The edge already sits on the section gutter (see the
	 * escape rule below), so this is just the dot's hang, which lands the rail on the gutter
	 * (Figma: milestone x=125, dot x=97, gutter 96). Shared with scroll-padding-inline. */
	--bpd-timeline-lead: var( --wp--preset--spacing--700 );
	/* Leading inset for programmatic scrolls, so a target lands flush with the first milestone
	 * rather than under the track's padding. Matches the padding set in the escape rule below. */
	scroll-padding-inline: calc( var( --wp--preset--spacing--gutter ) + var( --bpd-timeline-lead ) ) 0;
	-webkit-overflow-scrolling: touch;
	/* The pip band below is the scroll indicator in the Figma frame; a native scrollbar alongside
	 * it reads as a doubled affordance. */
	scrollbar-width: none;
	/* Gap down to the pip band (Figma: last "below" copy ends ~y774, band top y847). */
	padding-top: var( --wp--preset--spacing--1300 );
	padding-bottom: var( --wp--preset--spacing--1800 );
	cursor: grab;
}

/* ---- Escape the section band's constrained layout. The band is a core CONSTRAINED group with
 * padding-inline: gutter, so it caps non-aligned children at contentSize, and the track's own
 * gutter padding stacked on top of the band's. Done in CSS rather than by adding alignfull to the
 * group because this section is baked block markup in the page body — a pattern change would need
 * a database write, CSS ships by deploy.
 *
 * The bleed is a width plus a paint offset, not a negative margin: core's rule sets
 * `margin-left/right: auto !important`, which no selector can override. Widening by two gutters
 * and shifting the box one gutter toward the start puts both edges on the viewport, and `left`
 * moves only the painted position, so the band's layout is untouched.
 *
 *   containing block = band content box = viewport - 2 x gutter
 *   width            = 100% + 2 x gutter, left = -gutter  -> both edges at the viewport
 *
 * The start inset lives in padding, not on the box, so it holds the first milestone off the edge
 * at rest but scrolls away with the content, leaving the track full width once it moves. End is 0
 * so the run-out isn't shortened. margin-inline restates what core forces. ---- */
.wp-block-group.bpd-timeline {
	max-width: none;
	width: calc( 100% + 2 * var( --wp--preset--spacing--gutter ) );
	margin-inline: auto;
	position: relative;
	left: calc( -1 * var( --wp--preset--spacing--gutter ) );
	padding-inline: calc( var( --wp--preset--spacing--gutter ) + var( --bpd-timeline-lead ) ) 0;
}

/* timeline.js toggles this while a mouse drag is in progress. */
.bpd-timeline.is-dragging {
	cursor: grabbing;
	user-select: none;
}

/* Chromium/WebKit ignore scrollbar-width. */
.bpd-timeline::-webkit-scrollbar {
	display: none;
}

/* Base line: 4px solid blue-300, spanning every column in the line row (Figma #b5bec9). The
 * -28px pulls it left under the first item's dot (Figma: line x=21 vs dot x=16). */
.bpd-timeline::before {
	content: '';
	grid-row: 2;
	grid-column: 1 / -1;
	margin-left: -28px;
	background-color: var( --wp--preset--color--blue-300 );
	pointer-events: none;
}

/* Each item spans all three track rows and re-exposes them via subgrid, so its content,
 * connector and dot land in shared rows that stay aligned across every item. */
.bpd-timeline__item {
	display: grid;
	grid-template-rows: subgrid;
	grid-row: 1 / -1;
	width: 477px;
	margin-block: 0; /* core flow-layout blockGap margin would shift items within their rows */
}

/* Explicit column per item, in source order. Auto-placement can't be used here: the base-line
 * pseudo occupies row 2 of every column, so an auto-placed item spanning all three rows finds
 * no free explicit column and overflows into implicit ones — explicit placement may overlap. */
.bpd-timeline__item:nth-child( 1 ) { grid-column: 1; }
.bpd-timeline__item:nth-child( 2 ) { grid-column: 2; }
.bpd-timeline__item:nth-child( 3 ) { grid-column: 3; }
.bpd-timeline__item:nth-child( 4 ) { grid-column: 4; }
.bpd-timeline__item:nth-child( 5 ) { grid-column: 5; }
.bpd-timeline__item:nth-child( 6 ) { grid-column: 6; }

/* ----- Inside one item: copy column + photo, side by side -----
 * The item's single content child is .bpd-timeline__row, a core FLEX group (declared in
 * timeline.php: flexWrap nowrap, verticalAlignment center, blockGap 400) holding exactly two
 * children: [copy group][figure]. Core's flex layout supplies display:flex, the 16px gap and
 * align-items:center — the centering is what vertically aligns the copy column (year -> title
 * -> description, in DOM order) against the 192px thumbnail. This wrapper row is load-bearing:
 * without it the copy group and figure would be *separate* grid items of the item's subgrid
 * (an earlier build had exactly that bug — the "row" flex styles landed on the copy group
 * itself and laid the year/title/description out side by side). */

/* The copy column MUST take all width the photo doesn't (477 - 192 - 16 = 269px). Without an
 * explicit flex it sizes to its own content and the browser is free to shrink it, which is what
 * made titles ("10 years of great places to work") wrap into a cramped multi-line block.
 * min-width: 0 lets long words still shrink the column instead of overflowing the item. */
.bpd-timeline__row > .wp-block-group {
	flex: 1 1 0;
	min-width: 0;
}

/* Balance multi-line title wraps (even line lengths, no orphaned last word). Progressive
 * enhancement — unsupported browsers just wrap normally. */
.bpd-timeline__title {
	text-wrap: balance;
}

/* Above items anchor their row to the line from track row 1, below items from track row 3
 * (grid-row placement into the item's SUBGRID rows = the shared track rows). The spacing-1100
 * pad is the constant 44px content-to-line offset; align-self end/start pins the row against
 * the line side, so taller copy grows away from the line, never into it. */
.bpd-timeline__item--above > .bpd-timeline__row {
	grid-row: 1;
	align-self: end;
	padding-bottom: var( --wp--preset--spacing--1100 );
}

.bpd-timeline__item--below > .bpd-timeline__row {
	grid-row: 3;
	align-self: start;
	padding-top: var( --wp--preset--spacing--1100 );
}

/* Thumbnail: fixed 192px square, never allowed to grow or shrink — the copy column absorbs all
 * remaining width. photo-frame.css's width:100% would otherwise stretch the figure to the full
 * item width, hence the explicit cap. The source images are 313x243 (the mobile frame size), so
 * photo-frame.css's object-fit: cover takes the centred square crop here. */
.bpd-timeline__item .wp-block-image {
	flex: 0 0 192px;
	max-width: 192px;
	border-radius: var( --wp--custom--radius--xlg );
}

.bpd-timeline__item .wp-block-image img {
	width: 192px;
	height: 192px;
}

/* Per-item dashed connector: 224px long, 2px, dash "2 2" (Figma). A grid item in the content
 * row, flush against the base line, 24px left of the item's column edge. */
.bpd-timeline__item::after {
	content: '';
	grid-column: 1;
	justify-self: start;
	margin-left: -24px;
	width: var( --wp--custom--border--md );
	height: 224px;
	background-image: repeating-linear-gradient(
		to bottom,
		var( --wp--preset--color--blue-300 ) 0,
		var( --wp--preset--color--blue-300 ) 2px,
		transparent 2px,
		transparent 4px
	);
	transition: background-image var( --wp--custom--motion--duration-sm ) ease;
	pointer-events: none;
}

.bpd-timeline__item--above::after {
	grid-row: 1;
	align-self: end;
}

.bpd-timeline__item--below::after {
	grid-row: 3;
	align-self: start;
}

/* 12px dot centered on the base line row, 28px left of the item's column edge. */
.bpd-timeline__item::before {
	content: '';
	grid-row: 2;
	grid-column: 1;
	justify-self: start;
	align-self: center;
	margin-left: -28px;
	width: 12px;
	height: 12px;
	border-radius: var( --wp--custom--radius--full );
	background-color: var( --wp--preset--color--blue-100 );
	transition: background-color var( --wp--custom--motion--duration-sm ) ease;
	pointer-events: none;
}

/* Active (leading-edge) milestone — timeline.js toggles .is-active on it. The script's initial
 * pass sets item 1 (2002) active, matching the Figma frame's resting state; no-JS pages show
 * every item muted (the section is fully readable — the green highlight is a progressive
 * enhancement, not content).
 * Text colors are owned here, not via Gutenberg textColor attributes: has-*-color utility
 * classes carry !important (theme.json element color), which no CSS could override — so the
 * year/title paragraphs ship without a textColor and this sheet styles both states. */
.bpd-timeline__item p {
	color: var( --wp--preset--color--neutral-100 );
	transition: color var( --wp--custom--motion--duration-sm ) ease;
}

.bpd-timeline__item.is-active .bpd-timeline__year,
.bpd-timeline__item.is-active .bpd-timeline__title {
	color: var( --wp--preset--color--green-600 );
}

.bpd-timeline__item.is-active::after {
	background-image: repeating-linear-gradient(
		to bottom,
		var( --wp--preset--color--green-600 ) 0,
		var( --wp--preset--color--green-600 ) 2px,
		transparent 2px,
		transparent 4px
	);
}

.bpd-timeline__item.is-active::before {
	background-color: var( --wp--preset--color--green-600 );
}

/* ---- PIP NAVIGATION BAND. The purple strip under the track, one pip per milestone
 * (Figma 4788:30780). Injected by timeline.js rather than authored in patterns/timeline.php:
 * this section is baked block markup in the page body, so pattern changes need a database write.
 * Progressive enhancement — without JS the track still scrolls and the section is complete.
 *
 * FULL-BLEED: unlike the track, which only escapes rightward, this has to escape both sides, and
 * a negative left margin can't beat core's `margin: auto !important`. So the injected element
 * carries `alignfull`, which core's constraint selector excludes outright, leaving the margins
 * here free. Available because this is script-injected and not block markup, where a
 * hand-authored class would have to survive Gutenberg's round-trip validation. */
.bpd-timeline-nav {
	display: flex;
	max-width: none;
	/* Escape the section's gutter on both sides. Block margins zeroed because core's blockGap
	 * rule (`> *`) would otherwise push the band 32px clear of the track it belongs to. */
	margin-block: 0;
	margin-inline: calc( -1 * var( --wp--preset--spacing--gutter ) );
	justify-content: center;
	gap: var( --wp--preset--spacing--200 );
	padding-block: var( --wp--preset--spacing--300 );
	background-color: var( --wp--preset--color--purple-900 );
}

/* A real <button>: these are navigation, so they must be keyboard-operable. */
.bpd-timeline-nav__pip {
	appearance: none;
	position: relative;
	width: 11px;
	height: 11px;
	border: 0;
	border-radius: var( --wp--custom--radius--full );
	background-color: var( --wp--preset--color--neutral-100 );
	padding: 0;
	cursor: pointer;
	transition: background-color var( --wp--custom--motion--duration-sm ) ease;
}

/* WCAG 2.2 target size: 11px is under the 24px minimum, so the hit area is grown with a
 * pseudo-element, leaving the visual pip and the 19px pitch untouched. */
.bpd-timeline-nav__pip::after {
	content: '';
	position: absolute;
	inset: -7px;
}

.bpd-timeline-nav__pip[aria-current='true'] {
	background-color: var( --wp--preset--color--green-600 );
}

.bpd-timeline-nav__pip:focus-visible {
	outline: var( --wp--custom--border--md ) solid var( --wp--preset--color--neutral-100 );
	outline-offset: var( --wp--preset--spacing--100 );
}

@media ( prefers-reduced-motion: reduce ) {
	.bpd-timeline__item p,
	.bpd-timeline__item::before,
	.bpd-timeline__item::after,
	.bpd-timeline-nav__pip {
		transition: none;
	}
}

/* ---- Mobile (node 4788:31108): vertical timeline — base line down the left, items stacked,
 *   the item nearest the top edge is the green one. The desktop grid is undone here: the track
 *   goes back to a flex column and both the dot and the base line become per-item elements.
 *
 * Figma geometry, read off the 375px frame (I4788:31108;33864:416;4788:31057 "Timeline"):
 *   - the copy column is 313px wide at x=46;
 *   - the base line is 2px at x=22–24, and every 12px dot is CENTRED on it (x=17–29 — the
 *     metadata reports the ellipse x as 29, but the rendered frame puts its centre on the line);
 *   - the line runs from the FIRST dot's centre to the LAST dot's centre and no further: it
 *     starts at 2002's dot and stops at 2026's, with no rail above or below.
 * The track's own ::before can't draw that: it is absolutely positioned, so top/bottom resolve
 * against the scroll container's padding box (540px) rather than the ~2900px of scrolled
 * content — the old rule left the line ending a third of the way down, and at 21px it also ran
 * straight through copy that started at 38px. So on mobile the line is drawn per item instead:
 * each item's ::after (the desktop dashed connector, unused here) becomes the segment from that
 * item's dot down to the next item's dot, and the last item has none. Segments are in normal
 * flow inside the item, so they scroll with the content and cover its full length by
 * construction. ---- */
@media ( max-width: 782px ) {
	.bpd-timeline {
		display: flex;
		position: relative;
		flex-direction: column;
		/* Figma: 32px between milestones (item tops 0/416/852/1268/1704/2140 against heights
		 * 384/404/384/404/404). Also the distance the line segments have to bridge below. */
		row-gap: var( --wp--preset--spacing--800 );
		/* Not a scroll container: all six milestones are laid out in full and the page scrolls
		 * past them. timeline.js follows — with no scrollport here it measures the active
		 * milestone against the viewport instead of the track. */
		height: auto;
		overflow: visible;
		cursor: auto;
	}

	/* Same-specificity reset of the desktop escape rule: the mobile stack stays inside the band,
	 * and the section wrapper already supplies the 16px gutter the frame measures from. */
	.wp-block-group.bpd-timeline {
		width: auto;
		margin-inline: 0;
		padding-inline: 0;
		left: 0;
	}

	/* The mobile frame (4788:31108) has no pip navigation. The band is still built — one DOM
	 * shape at every width, no resize branch — just not displayed. */
	.bpd-timeline-nav {
		display: none;
	}

	/* The track-wide base line is a desktop-only device — see the header note above. */
	.bpd-timeline::before {
		display: none;
	}

	.bpd-timeline__item {
		display: block;
		position: relative; /* containing block for the dot + line segment below */
		width: auto;
		/* Figma: copy at x=46 in the frame. The track's content box already starts at the 16px
		 * section gutter (the parent section supplies it), so the copy sits 30px further in —
		 * clear of the 12px dot, whose right edge is at 29px. */
		padding-left: 30px;
		margin: 0;
	}

	/* Items stack copy-over-photo; photo full-width below the copy (Figma 4788:31108). The
	 * two-class selector out-specifies both core's flex row (verticalAlignment center) and the
	 * desktop anchor padding above. */
	.bpd-timeline__item > .bpd-timeline__row {
		flex-direction: column;
		align-items: stretch;
		padding-top: 0;
		padding-bottom: 0;
	}

	/* 313px is the Figma frame's photo width (4788:31108) and the source images' native width, so
	 * it is a cap rather than a full-width stretch: at 375 the column is exactly 313 wide, and
	 * above that the photo holds its size instead of upscaling past its own pixels. */
	.bpd-timeline__item .bpd-timeline__item .wp-block-image,
	.bpd-timeline__item .wp-block-image {
		flex: none;
		width: 100%;
		max-width: 313px;
	}

	/* 313x243 is the source images' native size, so nothing is cropped here. aspect-ratio rather
	 * than a fixed height keeps the frame correct as the column narrows below 375px.
	 * timeline.js strips the baked inline width/height from these images; without that, the
	 * post_content style attribute pins them to 192px square and outranks this rule. */
	.bpd-timeline__item .wp-block-image img {
		width: 100%;
		height: auto;
		aspect-ratio: 313 / 243;
	}

	/* The desktop dashed connector becomes the base line SEGMENT for this item: 2px solid
	 * blue-300 from this item's dot centre (17px below the item's top) down to the next item's
	 * dot centre, i.e. the rest of this item plus the 32px row gap — height: 100% + row gap.
	 * Solid, never dashed and never green: the mobile design's line is a static rail, only the
	 * dot and the year/title change on the active item. */
	.bpd-timeline__item::after,
	.bpd-timeline__item.is-active::after {
		display: block;
		position: absolute;
		left: 6px; /* 2px line centred at 7px = the frame's x=23 minus the 16px gutter */
		top: 17px; /* dot centre: Figma dot y=28 against the item column top y=17 */
		margin-left: 0;
		width: var( --wp--custom--border--md );
		height: calc( 100% + var( --wp--preset--spacing--800 ) );
		background-image: none;
		background-color: var( --wp--preset--color--blue-300 );
	}

	/* Last milestone: the line stops at its dot (Figma — no rail below 2026). */
	.bpd-timeline__item:last-child::after {
		display: none;
	}

	/* 12px dot centred on the line (7px from the item's edge) with its centre 17px down, so it
	 * caps the segment above and starts the one below. */
	.bpd-timeline__item::before {
		position: absolute;
		left: 1px; /* 12px dot centred at 7px, same axis as the segment */
		top: 11px; /* 17px centre - 6px radius */
		margin-left: 0;
	}
}
