/*!
 * Front-page section styles — a-facts-pipeline. Merged into main.css at the
 * end of the pass. Loads after main.css, so it overrides it by source order.
 *
 * Sections covered:
 *   2 Facts strip  — one bordered rail riding over the hero's lower edge
 *   3 Pipeline     — one panel: a four-station flow track + a terminus band
 *
 * Everything here reuses the v3 tokens (--sf-ground-*, --sf-e1..e4,
 * --sf-grad-brand, --sf-r-xl) and the shared section-tempo modifiers. Nothing
 * redefines a token, forks a component or invents a box-shadow: the base
 * .sf-pipeline in main.css still serves the styleguide unchanged, because every
 * rule below is scoped to the .sf-pipeline--flow modifier.
 */

/* ===========================================================================
 * 2. FACT RAIL
 *
 * One rail with hairline dividers, lifted so it overlaps the dark hero — the
 * strip belongs to the hero rather than starting the page below it.
 *
 * Polish pass (2026-09-02): the strip is a two-row grid — numerals share one
 * baseline row, captions share a second (subgrid on the wide layout). Captions
 * are one line each on the four-up layout, so the columns are content-tuned
 * fractions rather than four equal quarters. Dividers are inset pseudo-rules
 * that stop short of the card edge, and the shadow steps down one notch so
 * the rail's edge reads crisp rather than hazy.
 * ======================================================================== */

.sf-facts-strip-wrap {
	--sf-facts-lift: 0px;
	position: relative;
	z-index: 2;
	margin-top: calc(var(--sf-facts-lift) * -1);
	padding-top: 0;
	padding-bottom: var(--sf-space-6);
	/* Transparent for exactly the overlap, so the dark hero shows through
	   behind the rail's shoulders, then the band's own ground fades in.
	   The stops track --sf-ground-1 (#EFF1FA) / --sf-ground-2 (#E6EAF7). */
	background: linear-gradient(
		180deg,
		rgba(239, 241, 250, 0) 0,
		rgba(239, 241, 250, 0) var(--sf-facts-lift),
		var(--sf-ground-2) calc(var(--sf-facts-lift) + 110px),
		var(--sf-ground-1) 100%);
	border-bottom: var(--sf-border);
}
/* The lift is capped by the hero's own bottom padding: measured, the rail's
   top edge must stay ~24px clear of the hero's lowest line of text, or it
   crowds copy it does not own. 48px of hero padding below 900, 64px above. */
@media (min-width: 600px) {
	.sf-facts-strip-wrap { --sf-facts-lift: 24px; padding-bottom: 40px; }
}
@media (min-width: 900px) {
	.sf-facts-strip-wrap { --sf-facts-lift: 40px; }
}

.sf-facts-strip.sf-facts-strip--rail {
	position: relative;
	display: grid;
	grid-template-columns: 1fr;
	gap: 0;
	overflow: hidden;
	background: var(--sf-surface);
	border: 1px solid rgba(79, 70, 229, .14);
	border-radius: var(--sf-r-xl);
	/* e3, not e4: the rail still floats over the hero, but the tighter throw
	   keeps its edge crisp instead of hazing into the band below. */
	box-shadow: var(--sf-e3);
}

/* The accent rule. Decorative: 3px, no meaning, no pointer target. */
.sf-facts-strip--rail::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 3px;
	background: linear-gradient(90deg, #4F46E5 0%, #6366F1 26%, #7C3AED 58%, #A855F7 82%, #22D3EE 100%);
	border-start-start-radius: inherit;
	border-start-end-radius: inherit;
	pointer-events: none;
	z-index: 2;
}

.sf-facts-strip--rail .sf-fact {
	position: relative;
	display: flex;
	flex-direction: column;
	/* Top-aligned, not centred: centring made each cell find its own vertical
	   middle, which is exactly what made the row read as ragged. */
	justify-content: flex-start;
	min-width: 0;
	padding: var(--sf-space-5);
	background: none;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	transition: background-color .2s var(--sf-ease);
}
.sf-facts-strip--rail .sf-fact:hover { background-color: rgba(79, 70, 229, .035); }

/* Dividers are pseudo-rules, not borders, so they can stop short of the card
   edges: ::before is the horizontal rule above a cell, ::after the vertical
   rule at its start. Which of the two shows depends on the grid in play. */
.sf-facts-strip--rail .sf-fact::before,
.sf-facts-strip--rail .sf-fact::after {
	content: "";
	position: absolute;
	background: var(--sf-line);
	pointer-events: none;
}
.sf-facts-strip--rail .sf-fact::before { inset-inline: var(--sf-space-5); inset-block-start: 0; height: 1px; }
.sf-facts-strip--rail .sf-fact::after { display: none; inset-block: 18px; inset-inline-start: 0; width: 1px; }
.sf-facts-strip--rail .sf-fact:first-child::before { display: none; }

.sf-facts-strip--rail .sf-fact__value {
	font-size: clamp(2rem, 1.35rem + 2vw, 2.75rem);
	line-height: 1.05;
	letter-spacing: -0.03em;
	white-space: nowrap;
}
.sf-facts-strip--rail .sf-fact__label {
	margin-top: 10px;
	font-size: 0.75rem;
	line-height: 1.5;
	letter-spacing: 0.02em;
	color: var(--sf-muted);
}

/* Two up from small phones to laptop: horizontal rule above the second row,
   vertical rule opening each second column. */
@media (min-width: 420px) and (max-width: 1199px) {
	.sf-facts-strip.sf-facts-strip--rail { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.sf-facts-strip--rail .sf-fact:nth-child(-n+2)::before { display: none; }
	.sf-facts-strip--rail .sf-fact:nth-child(even)::after { display: block; }
}
/* The five format names never break mid-list: from tablet up the sequence is
   one unit, so a caption that must wrap does it before the list, not after
   "TXT ·". Phones stay free to wrap wherever they need to. */
@media (min-width: 700px) {
	.sf-facts-strip--rail .sf-fact__seq { white-space: nowrap; }
}
/* Four up once every caption holds one line. The columns are content-tuned —
   the formats caption is the long pole — so each cell carries a similar
   text-to-air ratio instead of the long cell wrapping while short cells float.
   Subgrid puts every numeral on one shared row and every caption on a second. */
@media (min-width: 1200px) {
	.sf-facts-strip.sf-facts-strip--rail {
		grid-template-columns: 1fr 1.8fr 1.3fr 1fr;
		grid-template-rows: auto auto;
	}
	.sf-facts-strip--rail .sf-fact {
		display: grid;
		grid-template-rows: subgrid;
		grid-row: span 2;
		align-content: start;
		padding: 26px var(--sf-space-5);
	}
	.sf-facts-strip--rail .sf-fact::before { display: none; }
	.sf-facts-strip--rail .sf-fact:not(:first-child)::after { display: block; }
	.sf-facts-strip--rail .sf-fact__label { white-space: nowrap; }
}
/* The narrowest phones: "2 → 19" at the clamp maximum is the widest thing in
   the rail, so let it shrink rather than push the page sideways. */
@media (max-width: 419px) {
	.sf-facts-strip--rail .sf-fact__value { font-size: 1.875rem; }
	.sf-facts-strip--rail .sf-fact { padding: var(--sf-space-4); }
	.sf-facts-strip--rail .sf-fact::before { inset-inline: var(--sf-space-4); }
	/* Stacked cells are wide enough (208px of list vs 256px at a 320px page)
	   to hold the format sequence unbroken here too. */
	.sf-facts-strip--rail .sf-fact__seq { white-space: nowrap; }
}

/* ===========================================================================
 * 1. HERO STATS (replaces the overlapping fact rail)
 *
 * The four-up rail that rode the hero seam is unmounted. The three DESIGN-SPEC
 * facts still live under the CTAs, but as a labelled stack rather than wrapping
 * bullets — kickers (Free / Pro / GPL) on the brand-on-dark mono, values on
 * muted, hairline-separated. Same words, readable as a closer for the hero
 * instead of a leftover list.
 *
 * Between 600 and 899 the hero is a single column, so the three items sit as
 * a glass row (full measure, one line each). Above 900 they stay stacked in
 * the copy column so they sit on the CTAs they qualify, not under the mock.
 * ======================================================================== */

.sf-hero__stats {
	list-style: none;
	margin: var(--sf-space-6) 0 0;
	padding: 0;
	border-top: 1px solid var(--sf-dark-line);
}
.sf-hero__stats li {
	display: flex;
	flex-direction: column;
	gap: 3px;
	padding: 12px 0;
	border-bottom: 1px solid var(--sf-dark-line);
}
.sf-hero__stat-k {
	font-family: var(--sf-font-mono);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--sf-on-dark-brand);
}
.sf-hero__stat-v {
	font-size: 0.9375rem;
	line-height: 1.4;
	color: var(--sf-on-dark-muted);
}

@media (min-width: 600px) and (max-width: 899px) {
	.sf-hero__stats {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		margin-top: var(--sf-space-6);
		padding: 0;
		border: 1px solid rgba(255, 255, 255, .12);
		border-radius: var(--sf-r-lg);
		background: rgba(255, 255, 255, .04);
	}
	.sf-hero__stats li {
		padding: 14px 16px;
		border-bottom: 0;
		border-inline-start: 1px solid rgba(255, 255, 255, .1);
	}
	.sf-hero__stats li:first-child { border-inline-start: 0; }
}

@media (prefers-reduced-motion: reduce) {
	.sf-hero__stats li { transition: none; }
}

/* ===========================================================================
 * 3. PIPELINE — one short band, one flow track
 *
 * Was: an 868px band — heading, diagram panel, and then three grey paragraphs
 * that restated the bullet lists sitting 20px above them. The notes are gone
 * (see template-parts/front/pipeline.php for where each of their facts still
 * lives) and the band now runs on .sf-section--compact, so this is the quick
 * beat between the tall hero and the tall walkthrough below it.
 *
 * The four processing stages are stations on a continuous track: one stroke
 * weight and one colour from the first station to the last, an arrowhead into
 * every station downstream of the source, and a conceptual icon per stage. The
 * terminus (Feed URL, with its channel chips) is a wide tinted band beneath.
 * ======================================================================== */

/* .sf-section--compact carries the block padding. Only the head spacing is
   tuned here, so the band keeps one padding rule with the rest of the page. */
.sf-pipeline-section .sf-section__head {
	max-width: none;
	margin-bottom: var(--sf-space-5);
}

/* Tempo: a short band gets a smaller head. Five other bands open with a
   full-size two-line H2 under a mono eyebrow; this one does not. */
.sf-pipeline-section .sf-h2 { font-size: clamp(1.75rem, 1.15rem + 1.8vw, 2.5rem); }
.sf-pipeline-section .sf-lead {
	margin: var(--sf-space-3) 0 0;
	max-width: 54ch;
}

/* Heading left, lead right from 900 — same split the walkthrough and scale
   bands use, so this first light section does not open as a leftover stack
   now that the fact rail no longer sits above it. */
@media (min-width: 900px) {
	.sf-pipeline-section .sf-section__head {
		display: grid;
		grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
		align-items: end;
		column-gap: var(--sf-space-8);
		margin-bottom: var(--sf-space-6);
	}
	.sf-pipeline-section .sf-h2 { max-width: 18ch; }
	.sf-pipeline-section .sf-lead { margin: 0 0 4px; max-width: 46ch; }
}

.sf-flow {
	position: relative;
	overflow: hidden;
	background: var(--sf-surface);
	border: 1px solid rgba(79, 70, 229, .14);
	border-radius: var(--sf-r-xl);
	box-shadow: var(--sf-e3);
}
/* The accent rule, ramped through the stage colours. Decorative. */
.sf-flow::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 3px;
	background: linear-gradient(90deg, #4F46E5 0%, #6640E9 30%, #7C3AED 62%, #9333EA 84%, #4F46E5 100%);
	pointer-events: none;
	z-index: 3;
}

/* --- stages: shared ------------------------------------------------------ */

.sf-pipeline.sf-pipeline--flow { display: grid; grid-template-columns: 1fr; gap: 0; }

.sf-pipeline--flow .sf-pipeline__node {
	--sf-flow-ring: var(--sf-surface);
	--sf-station-bg: #ECEEFD;
	position: relative;
	display: block;
	height: auto;
	min-width: 0;
	overflow: visible;
	background: none;
	border: 0;
	border-radius: 0;
	box-shadow: none;
}

/* Stage colours ramp indigo → violet across the four processing stages and
   return to the brand at the terminus.
   Review fix: the source used to be slate (#64748B stage, #94A3B8 wire), which
   read as a disabled step rather than as "not ours". It is the brand indigo
   now, so nothing in the flow looks switched off. Every value below clears
   4.7:1 on the station ground, well past the 3:1 a graphic needs. */
.sf-pipeline--flow .sf-pipeline__node:nth-child(1) { --sf-stage: #4F46E5; }
.sf-pipeline--flow .sf-pipeline__node:nth-child(2) { --sf-stage: #6640E9; }
.sf-pipeline--flow .sf-pipeline__node:nth-child(3) { --sf-stage: #7C3AED; }
.sf-pipeline--flow .sf-pipeline__node:nth-child(4) { --sf-stage: #9333EA; }
.sf-pipeline--flow .sf-pipeline__node--out { --sf-stage: #4F46E5; --sf-station-bg: var(--sf-surface); }

/* ::before is the connector, ::after the arrowhead that gives it direction.
   Both are decoration: empty content, pointer-events none, nothing exposed. */
.sf-pipeline--flow .sf-pipeline__node::before,
.sf-pipeline--flow .sf-pipeline__node::after { content: ""; position: absolute; pointer-events: none; }

/* One wire, one weight, from the first station to the last. It used to be a
   1px dash that stepped #94A3B8 → #A5B4FC → #C4B5FD → #D8B4FE, i.e. 2.56:1
   down to 1.77:1 against the panel, which is why it vanished before the fourth
   node. It is now a solid 2px #6366F1 rail (4.47:1) at every segment, with a
   drifting white highlight riding over it for the sense of travel. */
.sf-pipeline--flow .sf-pipeline__node::before {
	background-color: #6366F1;
	background-image: repeating-linear-gradient(var(--sf-wire-angle, 180deg), rgba(255, 255, 255, .38) 0 5px, rgba(255, 255, 255, 0) 5px 14px);
	background-repeat: repeat;
	z-index: 0;
}
/* The arrowhead: same colour, same family, pointing at the next station. */
.sf-pipeline--flow .sf-pipeline__node::after {
	background: #6366F1;
	z-index: 1;
}
/* The source has nothing upstream of it, so it carries no incoming arrow. */
.sf-pipeline--flow .sf-pipeline__node:first-child::after { display: none; }

/* --- the station: the conceptual icon, sitting on the track -------------- */

.sf-pipeline--flow .sf-pipeline__station {
	position: absolute;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 38px;
	height: 38px;
	border-radius: 12px;
	background: var(--sf-station-bg);
	/* A defined 1px edge so the chip reads as a component, not a tinted blob. */
	border: 1px solid rgba(79, 70, 229, .16);
	color: var(--sf-stage, var(--sf-brand));
	/* Punches the wire out cleanly either side of the icon, then one small
	   real shadow to seat the chip on the panel. */
	box-shadow: 0 0 0 4px var(--sf-flow-ring), var(--sf-e1);
}
.sf-pipeline--flow .sf-pipeline__station .sf-ico { display: block; width: 22px; height: 22px; }

/* --- < 600px: a stepped timeline, one spine down the left ---------------- */

.sf-pipeline--flow .sf-pipeline__node {
	padding: var(--sf-space-5) var(--sf-space-5) var(--sf-space-5) 68px;
	border-top: 1px solid var(--sf-line);
}
.sf-pipeline--flow .sf-pipeline__node:first-child { border-top: 0; }
.sf-pipeline--flow .sf-pipeline__station { inset-block-start: 24px; inset-inline-start: 16px; }
.sf-pipeline--flow .sf-pipeline__node::before {
	/* height / inset-inline-end are reset explicitly: the base component paints
	   a 3px stage bar here, and inheriting its height collapsed this spine. */
	inset-block: 0;
	inset-inline: 34px auto;
	width: 2px;
	height: auto;
	background-size: 2px 14px;
}
/* The track starts at the first station and stops at the last one. */
.sf-pipeline--flow .sf-pipeline__node:first-child::before { inset-block-start: 43px; }
.sf-pipeline--flow .sf-pipeline__node--out::before { inset-block-end: calc(100% - 43px); }
/* Arrowhead: pointing down, into the station below it. */
.sf-pipeline--flow .sf-pipeline__node::after {
	inset-block-start: 6px;
	inset-inline-start: 30px;
	width: 10px;
	height: 8px;
	clip-path: polygon(0 0, 100% 0, 50% 100%);
}

/* --- >= 600px: the track turns horizontal, two stages per row ------------ */

@media (min-width: 600px) {
	.sf-pipeline.sf-pipeline--flow { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.sf-pipeline--flow .sf-pipeline__node {
		padding: 74px var(--sf-space-4) var(--sf-space-5);
		border-top: 1px solid var(--sf-line);
		border-inline-start: 1px solid var(--sf-line);
	}
	.sf-pipeline--flow .sf-pipeline__node:nth-child(-n+2) { border-top: 0; }
	.sf-pipeline--flow .sf-pipeline__node:nth-child(odd) { border-inline-start: 0; }
	.sf-pipeline--flow .sf-pipeline__station { inset-block-start: 22px; inset-inline-start: var(--sf-space-4); }
	/* The connector runs the full column width, crossing the dividers, so it
	   reads as one line rather than a row of stubs. */
	.sf-pipeline--flow .sf-pipeline__node::before {
		--sf-wire-angle: 90deg;
		inset: 40px 0 auto 0;
		width: auto;
		height: 2px;
		background-size: 14px 2px;
	}
	/* A stage that opens a row starts its line at its own station… */
	.sf-pipeline--flow .sf-pipeline__node:first-child::before,
	.sf-pipeline--flow .sf-pipeline__node:nth-child(3)::before { inset-inline-start: calc(var(--sf-space-4) + 19px); }
	/* …and a stage that ends a row stops at its own station rather than
	   running on to die against the panel edge. No mask, no fade: the stroke
	   is at full weight right up to the last station it serves. */
	.sf-pipeline--flow .sf-pipeline__node:nth-child(2)::before,
	.sf-pipeline--flow .sf-pipeline__node:nth-child(4)::before { inset-inline-end: calc(100% - var(--sf-space-4) - 19px); }
	/* Arrowhead: pointing right, at the column edge, aimed at the next
	   station. A stage that opens a row is not entered from its left. */
	.sf-pipeline--flow .sf-pipeline__node::after {
		inset-block-start: 36px;
		inset-inline-start: 3px;
		width: 8px;
		height: 10px;
		clip-path: polygon(0 0, 100% 50%, 0 100%);
	}
	.sf-pipeline--flow .sf-pipeline__node:nth-child(3)::after { display: none; }
}

/* --- >= 900px: all four processing stages on one row --------------------- */

@media (min-width: 900px) {
	.sf-pipeline.sf-pipeline--flow { grid-template-columns: repeat(4, minmax(0, 1fr)); }
	/* Column dividers are painted, not borders: the 600px block's
	   :nth-child(odd) { border-inline-start: 0 } outspecified a plain border
	   here and silently dropped the FILTERS|MAPPING rule. A background paint
	   sidesteps that, and — with ::before/::after busy carrying the wire — it
	   is also the free channel for the facts-rail finish: the rule stops 18px
	   short of the gradient bar and the feed-band border (inset-block: 18px,
	   same as the fact cells' dividers). */
	.sf-pipeline--flow .sf-pipeline__node {
		border-top: 0;
		border-inline-start: 0;
		background-image: linear-gradient(var(--sf-line), var(--sf-line));
		background-repeat: no-repeat;
		background-size: 1px calc(100% - 36px);
		background-position: 0 18px;
	}
	.sf-pipeline--flow .sf-pipeline__node:first-child { background-image: none; }
	/* The third stage is mid-row now, so its line spans the whole column and
	   the second stage's line no longer terminates. */
	.sf-pipeline--flow .sf-pipeline__node:nth-child(3)::before { inset-inline-start: 0; }
	.sf-pipeline--flow .sf-pipeline__node:nth-child(2)::before { inset-inline-end: 0; }
	.sf-pipeline--flow .sf-pipeline__node:nth-child(3)::after { display: block; }
}
@media (min-width: 1200px) {
	.sf-pipeline--flow .sf-pipeline__node { padding-inline: var(--sf-space-5); }
	.sf-pipeline--flow .sf-pipeline__station { inset-inline-start: var(--sf-space-5); }
	.sf-pipeline--flow .sf-pipeline__node:first-child::before { inset-inline-start: calc(var(--sf-space-5) + 19px); }
	.sf-pipeline--flow .sf-pipeline__node:nth-child(4)::before { inset-inline-end: calc(100% - var(--sf-space-5) - 19px); }
}

/* --- the terminus, as a band across the panel ---------------------------- */
/* Declared after the stage rules at every width so it always wins the borders. */

.sf-pipeline--flow .sf-pipeline__node--out {
	background: linear-gradient(90deg, var(--sf-brand-tint) 0%, #F5F3FF 100%);
	--sf-flow-ring: #F0F1FE;
}
/* On this tinted ground --sf-muted was the tightest pair on the whole page
   (4.84:1 at 11px). Brand ink is 8.88:1 here and marks the output stage. */
.sf-pipeline--flow .sf-pipeline__node--out .sf-pipeline__label { color: var(--sf-brand-ink); }
@media (min-width: 600px) {
	.sf-pipeline--flow .sf-pipeline__node--out {
		grid-column: 1 / -1;
		display: grid;
		grid-template-columns: auto minmax(0, 190px) minmax(0, 1fr);
		align-items: center;
		gap: 0 var(--sf-space-5);
		padding: var(--sf-space-5) var(--sf-space-4);
		border-top: 1px solid var(--sf-line);
		border-inline-start: 0;
	}
	/* The station stops floating and becomes the band's first column, so the
	   terminus reads as the same kind of object as the four stages above it. */
	.sf-pipeline--flow .sf-pipeline__node--out .sf-pipeline__station {
		position: static;
		grid-area: 1 / 1 / 3 / 2;
		align-self: center;
		box-shadow: var(--sf-e1);
	}
	/* The chips column can span both rows and stretch them; end/start keeps the
	   label and its title a tight pair on the row line instead of drifting to
	   opposite ends of a 95px-tall band. */
	.sf-pipeline--flow .sf-pipeline__node--out .sf-pipeline__label { grid-area: 1 / 2; align-self: end; gap: 8px; }
	.sf-pipeline--flow .sf-pipeline__node--out .sf-pipeline__title { grid-area: 2 / 2; align-self: start; margin-top: 4px; }
	.sf-pipeline--flow .sf-pipeline__node--out .sf-pipeline__list { grid-area: 1 / 3 / 3 / 4; margin-top: 0; }
	/* The chips row starts under the FEED URL text, not under the icon chip,
	   so its left edge shares the cluster grid above it. */
	.sf-pipeline--flow .sf-pipeline__node--out .sf-pipeline__channels { grid-area: 3 / 2 / 4 / 4; margin-top: var(--sf-space-4); }
	/* The flow ends here, so ::before stops being a connector and becomes the
	   gradient edge that marks the output, and the incoming arrow goes with
	   the vertical spine it belonged to. */
	.sf-pipeline--flow .sf-pipeline__node--out::before {
		inset: 0 auto 0 0;
		width: 3px;
		height: auto;
		background-color: transparent;
		background-image: var(--sf-grad-brand);
		animation: none;
	}
	.sf-pipeline--flow .sf-pipeline__node--out::after { display: none; }
}
@media (min-width: 900px) {
	/* Three clusters — name, cadence, chips — sized to their content and set on
	   one shared centre line, with an even gutter between them. The chips flow
	   from the start of their column instead of being pinned to the far edge,
	   so the band reads as one row of related objects, not two groups with a
	   void between them. */
	.sf-pipeline--flow .sf-pipeline__node--out {
		grid-template-columns: auto minmax(0, max-content) minmax(0, max-content) minmax(0, 1fr);
		column-gap: var(--sf-space-6);
		border-top: 1px solid var(--sf-line);
		border-inline-start: 0;
	}
	.sf-pipeline--flow .sf-pipeline__node--out .sf-pipeline__channels {
		grid-area: 1 / 4 / 3 / 5;
		margin-top: 0;
		align-self: center;
	}
}
@media (min-width: 1200px) {
	.sf-pipeline--flow .sf-pipeline__node--out { padding-inline: var(--sf-space-5); }
}

/* The drift the spec asks for, on the wire's highlight rather than the wire
   itself, so the rail never thins or gaps while it travels. */
html.js .sf-pipeline--flow .sf-pipeline__node::before { animation: sf-flow-drift-v 1.4s linear infinite; }
@media (min-width: 600px) {
	html.js .sf-pipeline--flow .sf-pipeline__node::before { animation: sf-flow-drift-h 1.4s linear infinite; }
	html.js .sf-pipeline--flow .sf-pipeline__node--out::before { animation: none; }
}
@keyframes sf-flow-drift-h { to { background-position-x: 14px; } }
@keyframes sf-flow-drift-v { to { background-position-y: 14px; } }

/* --- stage type ---------------------------------------------------------- */

/* The station icon carries the stage colour, so the label's own square is
   redundant noise on every node including the terminus. */
.sf-pipeline--flow .sf-pipeline__label::before { display: none; }
.sf-pipeline--flow .sf-pipeline__label { gap: 0; font-size: 0.6875rem; letter-spacing: 0.09em; color: var(--sf-muted); }
.sf-pipeline--flow .sf-pipeline__title {
	margin-top: 6px;
	font-family: var(--sf-font-display);
	font-size: 1.0625rem;
	line-height: 1.25;
	letter-spacing: -0.015em;
}

/* Facts: row rules plus column dividers plus a connector was too much line.
   A small square in the stage colour ties each fact to its stage instead. */
.sf-pipeline--flow .sf-pipeline__list { margin-top: var(--sf-space-3); font-size: 0.8125rem; line-height: 1.5; }
.sf-pipeline--flow .sf-pipeline__list li {
	position: relative;
	display: block;
	margin-top: 7px;
	padding: 0;
	padding-inline-start: 15px;
	border-top: 0;
}
.sf-pipeline--flow .sf-pipeline__list li:first-child { margin-top: 0; }
.sf-pipeline--flow .sf-pipeline__list li::before {
	content: "";
	position: absolute;
	inset-block-start: 0.58em;
	inset-inline-start: 0;
	width: 5px;
	height: 5px;
	border-radius: 1px;
	background: var(--sf-stage, var(--sf-brand));
	opacity: .5;
}
.sf-pipeline--flow .sf-pipeline__list .sf-badge { margin-inline-start: 6px; vertical-align: 1px; }
.sf-pipeline--flow .sf-pipeline__list code { font-size: 0.75rem; color: var(--sf-brand-ink); overflow-wrap: anywhere; }

.sf-pipeline--flow .sf-pipeline__channels { margin-top: var(--sf-space-4); gap: 5px; }
.sf-pipeline--flow .sf-pipeline__channels span {
	gap: 5px;
	padding: 3px 8px 3px 7px;
	font-size: 0.6875rem;
	background: rgba(255, 255, 255, .82);
	border-color: rgba(79, 70, 229, .16);
	color: var(--sf-ink-2);
}
.sf-pipeline--flow .sf-pipeline__channels span::before { width: 6px; height: 6px; }

/* ===========================================================================
 * Motion guard. Everything above must resolve to opacity 1 / transform none
 * with no running animation.
 * ======================================================================== */
@media (prefers-reduced-motion: reduce) {
	html.js .sf-pipeline--flow .sf-pipeline__node::before { animation: none; }
	.sf-facts-strip--rail .sf-fact { transition: none; }
}
