/*
 * Fluent Commerce 2026 design system — layout engine.
 *
 * Adopted from the export's system/responsive.css. That file describes itself as
 * a proposal held outside the read-only _ds/ bundle; it is the only stylesheet in
 * the design build, because container queries and fluid type cannot be expressed
 * as inline styles. Everything structural about the design lives here.
 *
 * ── THE MODEL ───────────────────────────────────────────────────────────────
 *
 * The page is a CONTAINER, not a viewport. Every breakpoint below is a
 * @container query against a named container, so the same markup reflows
 * correctly inside a 390px frame or a 1920px canvas. Named breakpoints are
 * 1920 / 1440 / 1024 / 768 / 390, and each query threshold sits just ABOVE its
 * breakpoint (1500 / 1100 / 820 / 440) so the named width itself receives the
 * treatment intended for it.
 *
 * ── THE ONE STRUCTURAL CHANGE FROM THE EXPORT ───────────────────────────────
 *
 * The export puts the container on <body>:
 *
 *     body { container-type: inline-size; container-name: page; width: 1920px; … }
 *
 * That cannot ship on WordPress. container-type: inline-size applies layout
 * containment, and a layout-contained element becomes the containing block for
 * every position:fixed descendant inside it. On a screen wider than 1920 the
 * body is centred, so anything fixed would be offset by the left margin and
 * measured against the page's height rather than the viewport. Two things break:
 *
 *   1. #wpadminbar — WordPress's own fixed bar, a child of <body>.
 *   2. Any fixed overlay of ours, e.g. the nav drawer.
 *
 * So the container moves to a wrapper, .fc-shell, and #wpadminbar stays outside
 * it as a normal body child and is unaffected. The design's two-element split is
 * preserved for the reason the export gives: a container cannot be restyled by
 * its own @container query, so the tokens have to hang on an inner element.
 *
 *     .fc-shell   the container      — width, centring, container-type
 *     .fc-page    the token bearer   — all the fluid constants and type ramps
 *
 * The drawer is then solved without fixed positioning at all — see chrome.css.
 * It is absolutely positioned inside the sticky nav shell, which gets the same
 * result with none of the containment trouble.
 *
 * ── WHAT IS IN HERE, AND WHAT IS IN pages.css ───────────────────────────────
 *
 * This file is the engine: the container, the scale, and the primitives that any
 * future page will reach for — grids, splits, the fold, the marquee, the record
 * sleeve, the stat band, type roles. pages.css holds the COMPOSITIONS that only
 * the home and OMS pages make out of them (the bento, the capability rows, the
 * pattern panels, the FAQ). The test for which file a rule belongs in is whether
 * a third page could plausibly use it, not which page it first appeared on.
 *
 * Still deliberately absent, because nothing on the site uses them yet: the
 * quote rail and its fade lead-in, .fc-wordmark-*, .fc-grid-7, the .fc-hero /
 * .fc-plate min-heights, and the TestimonialCard width release. They come back
 * with the pages that need them.
 *
 * @package Fluent_Commerce
 */

/* ─────────────────────────────────────────────────────────────────────────────
 * THE CONTAINER
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-shell {
	container-type: inline-size;
	container-name: page;
	width: var(--canvas, 1920px);
	max-width: 100%;
	margin: 0 auto;
}

/*
 * overflow-x: clip, not hidden. clip prevents sideways scroll WITHOUT creating a
 * scroll container, which matters because the nav is position:sticky — hidden
 * here would make .fc-page the scrollport and the nav would never stick.
 */
body.fc-ds .fc-page {
	width: 100%;
	overflow-x: clip;
	overflow-y: visible;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE PAGE'S SCALE
 * Layout constants and fluid type, on the inner element.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-page {
	/* Layout constants, now fluid. Each 1920 value is the system's number. */
	--gutter-page: 207px;

	/*
	 * THE FOOTER GUTTER RAMPS. IT USED TO STEP.
	 *
	 * This is the only gutter in the system that interpolates rather than
	 * steps, and it is the only one that has to. 356px is a quarter of the
	 * footer's width at 1920 — far and away the biggest inset here — so held
	 * flat between breakpoints it eats a share of the page that grows as the
	 * page narrows, and it is doing that to the one region of the site that
	 * has to fit four columns of link text side by side. Every other gutter is
	 * small enough that a step costs nothing. Measured 2026-08-26, stepped:
	 *
	 *   viewport 1920  →  footer content 1193px  →  four link columns @ 191px
	 *   viewport 1680  →  footer content  953px  →  four link columns @ 138px
	 *   viewport 1536  →  footer content  809px  →  four link columns @ 102px
	 *   viewport 1440  →  footer content 1065px  →  four link columns @ 166px
	 *   viewport 1180  →  footer content  805px  →  four link columns @ 101px
	 *
	 * Read the middle two lines again: the footer was NARROWER at 1536 than at
	 * 1440. Each breakpoint dropped the gutter in one move — 356 → 180 → 72 —
	 * so crossing one made the content jump wider, and the widths just above a
	 * step were worse than the widths well below it. The band above each step
	 * carried the damage: 102px at 1536 and 101px at 1180, and 100px is not a
	 * column, it is a stack of two-word fragments. This is the second half of
	 * the overlap reported on 2026-08-26; the first half was the nowrap in
	 * chrome.css.
	 *
	 * So interpolate. One straight line spans the entire four-column range,
	 * from the widest canvas down to the width where the columns become two,
	 * and it is pinned at both ends to a number the design already gives us —
	 * 356 at 1920, and the 72 the tablet step uses at 1100. Slope 284/820 =
	 * 34.63cqw, intercept −309px. Only the line between the two anchors is
	 * ours, and a straight line between two of a system's own values is the
	 * smaller deviation.
	 *
	 * One line, not one per band. The first attempt at this ramped 356→180
	 * above the 1500 step and 180→72 below it, keeping all three of the
	 * system's numbers; but two lines with different slopes meeting at a
	 * breakpoint still leave a kink, and measurement showed content dipping
	 * 5px crossing 1500 — the original bug in miniature. A single line has no
	 * seam to get wrong. The cost is that 1440 now sits at 185 rather than
	 * exactly 180, and 180 was only ever a step value, not a design mark.
	 *
	 * cqw, not vw: the container is .fc-shell, capped at --canvas, so the
	 * gutter stops growing where the canvas does rather than tracking a 3440
	 * monitor. The line reaches 72 exactly at container 1100, so the handover
	 * to the tablet step below is continuous and the clamp floor never fights
	 * it. That the arithmetic lands on the step's own value is the check that
	 * says the two anchors were consistent to begin with.
	 *
	 * Footer content width now rises the whole way — 958 at 1120, 976 at 1180,
	 * 1056 at 1440, 1086 at 1536, 1130 at 1680, 1204 at 1920 — and the columns
	 * with it: 139 / 144 / 164 / 170 / 178 / 193. Monotonic at last, so no
	 * width is worse than a narrower one, and 1920 keeps the design's inset to
	 * the pixel.
	 */
	--gutter-footer: clamp(72px, calc(34.63cqw - 309px), 356px);
	--indent-body: 132px;
	--gap-nav: 44px;
	--gap-cards: 33px;
	--gap-blocks: 120px;
	--pad-section: 120px;
	--logo-h-nav: 40px;
	--logo-clear-nav: calc(var(--logo-h-nav) * 0.62); /* the clear-space rule, as a token */
	--nav-height: 90px;
	--card-max: 420px;
	--gap-marquee: 96px;      /* between phrases in the scrolling band */
	--marquee-height: 62px;
	--sleeve-max: 420px;      /* a record sleeve is square, so this is its height too */

	/*
	 * Fluid type. Each ramp is linear between 390 and 1920 and clamped at both
	 * ends, so the display serif never steps at a breakpoint. These override the
	 * fixed values in tokens.css — same names, deliberately.
	 *
	 * The three body steps are the exception, and they are pinned on purpose — see
	 * the note on them below.
	 */
	--type-display-80: clamp(40px, calc(29.80px + 2.614cqw), 80px);
	--type-display-72: clamp(36px, calc(26.82px + 2.353cqw), 72px);
	--type-display-62: clamp(32px, calc(24.35px + 1.961cqw), 62px);
	--type-display-48: clamp(28px, calc(22.90px + 1.307cqw), 48px);
	/*
	 * 40 is Build-15's, and the export references it without ever defining it — an
	 * undefined var in the file it came from, so the intent (40px) is all it gives us.
	 * Derived here from this ramp's own rule rather than invented: floor 26 sits between
	 * display-48's 28 and title-32's 24, slope is (40 − 26) / 15.30 per cqw, and the
	 * intercept puts it at exactly 40.00px in a 1920 container and on its floor at 390,
	 * like every other step.
	 */
	--type-display-40: clamp(26px, calc(22.43px + 0.915cqw), 40px);
	--type-h3-48: clamp(30px, calc(25.40px + 1.176cqw), 48px);
	--type-title-32: clamp(24px, calc(21.96px + 0.523cqw), 32px);
	--type-lead-26: clamp(20px, calc(18.47px + 0.392cqw), 26px);
	--type-h5-24: clamp(20px, calc(18.98px + 0.261cqw), 24px);

	/*
	 * ── READING SIZE: PINNED, AND TWO STEPS ABOVE THE EXPORT ────────────────
	 *
	 * Body copy does not scale with the viewport, and it is set two pixels above
	 * the export's own numbers. Decided 2026-08-21 after review, and it is the one
	 * place the 2026 system knowingly departs from the design file, so it is worth
	 * being explicit about what changed and why the neighbours did not.
	 *
	 *   token             export   here   used for
	 *   --type-body-18      18      20    kickers, leads — display-adjacent
	 *   --type-body-16      16      18    the paragraph size on every page
	 *   --type-body-15      15      17    copy inside a card, a table, a panel
	 *
	 * Two things follow, both deliberate. First, +2 across all three keeps the
	 * 2/1 spacing between the steps, so the hierarchy is unchanged — this is a
	 * reading-size decision, not a re-scale. Second, dropping the clamp means the
	 * measure now shortens as the viewport does instead of the type shrinking with
	 * it, which is the normal way to set body copy and the reason the ramps were
	 * questioned in the first place: at 1440 the old --type-body-16 resolved to
	 * about 15px and on a phone to 14px, so the site's reading size was a function
	 * of the reader's window.
	 *
	 * Everything around them stays fluid — display serif, leads, eyebrows, labels,
	 * numerals, mono. Those are composition, and they are sized against the layout
	 * rather than read at length.
	 *
	 * tokens.css still carries 18 / 16 / 15, because that file is the export's
	 * literal values and should keep saying what the export said. This is the
	 * override layer; the difference between the two files is the record.
	 *
	 * /?fc-body=16 and /?fc-body=fluid on the home page hold the two alternatives
	 * this was chosen over — see fluent_commerce_ds_body_size_preview() in
	 * inc/ds.php, which is temporary and says so.
	 */
	--type-body-18: 20px;
	--type-body-16: 18px;
	--type-body-15: 17px;

	--type-eyebrow-16: clamp(13px, calc(12.24px + 0.196cqw), 16px);
	--type-label-18: clamp(15px, calc(14.24px + 0.196cqw), 18px);
	--type-label-12: clamp(10.5px, calc(9.99px + 0.131cqw), 12.47px);
	--type-quote-32: clamp(24px, calc(21.96px + 0.523cqw), 32px);
	--type-quote-24: clamp(20px, calc(18.47px + 0.392cqw), 24px);
	--type-numeral-96: clamp(56px, calc(45.80px + 2.615cqw), 96px);
	--type-numeral-48: clamp(32px, calc(27.92px + 1.046cqw), 48px);
	--type-numeral-32: clamp(24px, calc(21.96px + 0.523cqw), 32px);
	--type-numeral-24: clamp(18px, calc(16.47px + 0.392cqw), 24px);
	--type-mono-15: clamp(12px, calc(11.24px + 0.196cqw), 15px);
	--type-mono-14: clamp(12px, calc(11.49px + 0.131cqw), 14px);

	/*
	 * ── FORM SIZE: ONE NUMBER FOR THE FIELD AND ITS LABEL ───────────────────
	 *
	 * Flat, off the ramps, and off the body scale above. Two rules in one token:
	 *
	 *   1. A control is never below 16px. iOS zooms the page when a field under
	 *      16px takes focus, and a ramped size drops under it on exactly the
	 *      device where a long form is hardest to fill in. Every form in the
	 *      system had written this number out with its own copy of that reason;
	 *      the reason lives here now.
	 *   2. Any visible label inside a form is set to the same number, at the same
	 *      weight — --fw-medium, and not bold. Asked for 2026-08-24 after the
	 *      event form's "Will you be staying for dinner?" came through semibold at
	 *      --type-body-18 — 20px here — against 16px fields, so the question read
	 *      as a heading over the controls it belongs to. A label and its field are
	 *      one thing and are set as one. Position and wording are what mark a
	 *      label as a label; it does not need weight as well.
	 *
	 * Two exceptions, both deliberate and both documented where they are — the
	 * uppercase .fc-meta micro-labels on the two single-field email forms, which
	 * are eyebrows rather than field labels, and .fc-consent at 14px, which is the
	 * consent record's own size (see inc/ds-consent.php).
	 */
	--fc-field-size: 16px;
}

/* ── 1440 ── wide desktop. Gutters tighten; nothing else moves. */
@container page (max-width: 1500px) {
	body.fc-ds .fc-page {
		--gutter-page: 120px;
		/* No --gutter-footer here. It ramps continuously through this
		 * breakpoint and the next — see the note on the base value. */
		--gap-blocks: 96px;
	}
}

/* ── 1024 ── tablet landscape. Splits stack; the 132 indent halves. */
@container page (max-width: 1100px) {
	body.fc-ds .fc-page {
		--gutter-page: 72px;
		--gutter-footer: 72px;
		--indent-body: 66px;
		--gap-nav: 20px;
		--gap-blocks: 72px;
		--pad-section: 96px;
	}
}

/* ── 768 ── tablet portrait. The indent collapses; the nav shrinks. */
@container page (max-width: 820px) {
	body.fc-ds .fc-page {
		--gutter-page: 40px;
		--gutter-footer: 40px;
		--indent-body: 0px;
		--gap-cards: 20px;
		--gap-blocks: 54px;
		--pad-section: 72px;
		--nav-height: 84px;
		--gap-marquee: 54px;
		--marquee-height: 56px;
	}
}

/* ── 390 ── phone. */
@container page (max-width: 440px) {
	body.fc-ds .fc-page {
		--gutter-page: 20px;
		--gutter-footer: 20px;
		--gap-blocks: 32px;
		--pad-section: 54px;
		--nav-height: 76px;
	}
}

/* ─────────────────────────────────────────────────────────────────────────────
 * SECTION SHELL
 * Vertical rhythm is padding inside a section; the gutter is horizontal. Two
 * adjacent sections that must read as one composition kill the seam with
 * .fc-section-b0 on the first and .fc-section-t0 on the second.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-section {
	padding: var(--pad-section) var(--gutter-page);
}

body.fc-ds .fc-section-t0 {
	padding-top: 0;
}

body.fc-ds .fc-section-b0 {
	padding-bottom: 0;
}

body.fc-ds .fc-bleed {
	padding-left: 0;
	padding-right: 0;
}

body.fc-ds .fc-center {
	max-width: min(1202px, 100%);
	margin-left: auto;
	margin-right: auto;
}

body.fc-ds .fc-indent {
	padding-left: var(--indent-body);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE RULED COLUMN
 * Two hairlines running the full height of a run of sections at the gutter, with
 * the copy inset a further 40px from them. The design draws the pair once, as
 * ::before/::after on a single wrapper around every section in the run; here each
 * section draws its own pair, and because the sections stack with no gap between
 * them the segments meet and read as two continuous lines. inc/ds-security.php
 * has the long version of why per-section beats a wrapper — chiefly that every
 * section stays a top-level sibling, the way every other composed page is built.
 *
 * Here rather than in security.css, where it started, for the reason the crosslink
 * moved out of blog.css: the Trust Center was the first page to rule its column
 * and the Integrations page is the second, so it is a primitive and not one page's
 * treatment. Two consequences worth knowing before editing:
 *
 *   · A ruled section's horizontal padding is gutter + 40, NOT the gutter. The
 *     verticals sit at the gutter and the copy has to clear them.
 *   · A dark section HIDES the ink hairlines its neighbours draw, so it redraws
 *     them in bone with .fc-ruled--dark. That is the export's [data-tone="dark"]
 *     switch, and its .fc-ruled-carry + two .fc-ruled-line spans, written as one
 *     class because it is a surface change and not two more empty elements.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-ruled {
	--fc-rule: var(--fc-ink-a20);
	position: relative;
}

/*
 * --fc-rule is declared on .fc-ruled and not on .fc-section.fc-ruled below, so that
 * this override can be a single class and still win: same specificity, later source.
 */
body.fc-ds .fc-ruled--dark {
	--fc-rule: var(--fc-bone-a20);
}

body.fc-ds .fc-section.fc-ruled {
	padding-left: calc(var(--gutter-page) + 40px);
	padding-right: calc(var(--gutter-page) + 40px);
}

body.fc-ds .fc-ruled::before,
body.fc-ds .fc-ruled::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	width: var(--stroke-1);
	background: var(--fc-rule);
	pointer-events: none;
}

body.fc-ds .fc-ruled::before {
	left: var(--gutter-page);
}

body.fc-ds .fc-ruled::after {
	right: var(--gutter-page);
}

/*
 * The 40px inset halves below 768. The gutter is already down to 40px there and on
 * to 20 at 390, so holding a 40px inset as well would leave a phone about 270px of
 * measure — the rules would be costing more than they are worth.
 */
@container page (max-width: 820px) {
	body.fc-ds .fc-section.fc-ruled {
		padding-left: calc(var(--gutter-page) + 20px);
		padding-right: calc(var(--gutter-page) + 20px);
	}
}

/*
 * A hairline BETWEEN two sections of the same surface, drawn as its own element
 * because a border on either section would sit inside that section's padding rather
 * than on the seam between them. Full-bleed, so it also closes the 1px gap the ruled
 * column's verticals leave as they pass it. Ink by default, bone beside a dark
 * section.
 */
body.fc-ds .fc-seam {
	height: var(--stroke-1);
	background: var(--fc-ink-a20);
}

body.fc-ds .fc-seam--dark {
	background: var(--fc-bone-a20);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * GRIDS
 * N-up at 1920/1440, then the documented step-downs.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-grid {
	display: grid;
	gap: var(--gap-cards);
}

body.fc-ds .fc-grid-2 {
	grid-template-columns: repeat(2, 1fr);
}

body.fc-ds .fc-grid-3 {
	grid-template-columns: repeat(3, 1fr);
}

body.fc-ds .fc-grid-4 {
	grid-template-columns: repeat(4, 1fr);
}

body.fc-ds .fc-grid-5 {
	grid-template-columns: repeat(5, 1fr);
}

/*
 * .fc-cols-5 is not a grid of cards — it is a five-column RULED TABLE, the
 * hairline-divided comparison block. Hence its own name: the borders come from
 * the composition (see pages.css), and it never inherits --gap-cards, because a
 * gap would break the shared rules that are the whole point of it.
 */
body.fc-ds .fc-cols-5 {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
}

/* 1024: 5→3, 4→2, 2→1. The 3-up holds — three cards still read at this width. */
@container page (max-width: 1100px) {
	body.fc-ds .fc-grid-5,
	body.fc-ds .fc-cols-5 {
		grid-template-columns: repeat(3, 1fr);
	}

	body.fc-ds .fc-grid-4 {
		grid-template-columns: repeat(2, 1fr);
	}

	body.fc-ds .fc-grid-2 {
		grid-template-columns: 1fr;
	}
}

/* 768: 3→2, 5→2 */
@container page (max-width: 820px) {
	body.fc-ds .fc-grid-3,
	body.fc-ds .fc-grid-5,
	body.fc-ds .fc-cols-5 {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* 390: everything is one column */
@container page (max-width: 440px) {
	body.fc-ds .fc-grid-3,
	body.fc-ds .fc-grid-4,
	body.fc-ds .fc-grid-5,
	body.fc-ds .fc-cols-5 {
		grid-template-columns: 1fr;
	}
}

/* ─────────────────────────────────────────────────────────────────────────────
 * BLOCK — CROSSLINK
 * Three destinations on hairlines. Same hover grammar as the card: the rule and the
 * kicker come up to full ink together.
 *
 * Here rather than in blog.css, where it started, because it is no longer a blog
 * block: a post ends with one and so does the contact page, and those two views load
 * different composition stylesheets. Ink-on-light throughout — every section that has
 * ever carried this block is bone, including the one under the dark contact page.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-crosslink__grid {
	column-gap: var(--sp-54);
	row-gap: var(--sp-54);
}

body.fc-ds .fc-crosslink__item {
	display: flex;
	flex-direction: column;
	gap: var(--sp-24);
	padding-top: var(--sp-32);
	border-top: var(--stroke-1) solid var(--fc-ink-a20);
	color: var(--fc-ink-a60);
	transition: color var(--dur-base) var(--ease-out), border-top-color var(--dur-base) var(--ease-out);
}

body.fc-ds .fc-crosslink__item:hover {
	color: var(--fc-ink-12);
	border-top-color: var(--fc-ink-12);
}

body.fc-ds .fc-crosslink__top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--sp-24);
}

body.fc-ds .fc-crosslink__kicker {
	color: inherit;
}

body.fc-ds .fc-crosslink__title {
	font-family: var(--font-display);
	font-weight: var(--fw-regular);
	/* The design's own clamp for this block — it runs larger than a card title. */
	font-size: clamp(30px, 3.1cqw, 48px);
	line-height: 1.05;
	letter-spacing: var(--ls-display);
	color: var(--fc-ink-12);
	text-wrap: pretty;
}

body.fc-ds .fc-crosslink__blurb {
	font-size: var(--type-body-18);
	line-height: var(--lh-body);
	color: var(--fc-ink-a80);
}

/* ═════════════════════════════════════════════════════════════════════════════
 * BLOCK — EMAIL CTA
 *
 * One eyebrow, one serif question, one field, one button. The design ships six copy
 * variants and three tones from a single component; the copy is in
 * fluent_commerce_ds_cta_copy() and the tones are the two classes below.
 *
 * Here rather than in blog.css, where it started, for the same reason the crosslink
 * moved: a post and a listing end with one, and so does the Integrations page, which
 * loads pages.css instead of blog.css. Third caller, different composition
 * stylesheet — it is a primitive.
 *
 * TONE IS SEVEN CUSTOM PROPERTIES, not a second copy of the block. Every colour in
 * here reads one of them, so .fc-emailcta--dark is seven declarations and no
 * duplicated geometry. They are named for their JOB and not their value, which is why
 * --fc-cta-inv (the submit label) is white on light but ink on dark: it is always the
 * colour of the surface behind the block.
 *
 * `white` on light is flagged in the design as a third surface the system does not
 * sanction (System gaps.md) — used where a page needs a light break before the ink
 * footer. Kept, because the alternative is bone-on-bone against the page and the
 * block would disappear.
 *
 * NOT WIRED TO SALESFORCE — but it does not drop the address either. The Salesforce
 * work is parked pending the custom Lead field IDs from the SF admin, so this posts
 * to admin-post.php, stores the lead in fc_leads marked 'skipped' with the reason,
 * and returns the design's success panel with the row's own reference. The report
 * page's gate posts to the same handler. See fluent_commerce_ds_handle_cta() in
 * inc/ds-blocks.php.
 *
 * SINCE 2026-08-26 IT CAPTURES NOTHING AT ALL. The field is replaced by a "Talk to us"
 * button to /contact/ while the site's forms move to Pardot one at a time — see
 * fluent_commerce_ds_cta_captures() and THE ASK below. Every rule above is still the
 * live styling of the form branch, which returns with one filter.
 * ══════════════════════════════════════════════════════════════════════════ */
body.fc-ds .fc-emailcta {
	background: var(--surface-lightest);
	--fc-cta-on: var(--fc-ink-12);
	--fc-cta-inv: var(--fc-white);
	--fc-cta-muted: var(--fc-ink-a80);
	--fc-cta-dim: var(--fc-ink-a60);
	--fc-cta-hair: var(--fc-ink-a20);
	--fc-cta-field: var(--fc-white);
	--fc-cta-ghost: var(--fc-ink-a40);
}

/*
 * On ink. The field loses its fill rather than taking a dark one — a filled box on
 * ink reads as a second surface, and the design draws it as an outline. bone-a40 for
 * the placeholder is the token's stated purpose, not an approximation.
 */
body.fc-ds .fc-emailcta--dark {
	background: var(--fc-ink-12);
	--fc-cta-on: var(--fc-bone);
	--fc-cta-inv: var(--fc-ink-12);
	--fc-cta-muted: var(--fc-bone-a80);
	--fc-cta-dim: var(--fc-bone-a60);
	--fc-cta-hair: var(--fc-bone-a20);
	--fc-cta-field: transparent;
	--fc-cta-ghost: var(--fc-bone-a40);
}

body.fc-ds .fc-emailcta__eyebrow {
	color: var(--fc-cta-dim);
}

body.fc-ds .fc-emailcta__title {
	margin-top: var(--sp-24);
	color: var(--fc-cta-on);
}

body.fc-ds .fc-emailcta__body {
	max-width: 520px;
	margin-top: var(--sp-32);
	font-size: var(--type-body-18);
	line-height: var(--lh-loose);
	color: var(--fc-cta-muted);
}

body.fc-ds .fc-emailcta__form {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

body.fc-ds .fc-emailcta__label {
	color: var(--fc-cta-dim);
}

body.fc-ds .fc-emailcta__row {
	display: flex;
	gap: 12px;
	flex-wrap: wrap;
}

body.fc-ds .fc-emailcta__input {
	/* 320px basis, but it may shrink — the row wraps before the field gets silly. */
	flex: 1 1 320px;
	height: 48px;
	padding: 0 var(--sp-16);
	border: var(--stroke-1) solid var(--fc-cta-hair);
	border-radius: var(--radius-10);
	background: var(--fc-cta-field);
	font-family: var(--font-core);
	/* The form size — see THE CONSENT BLOCK below. */
	font-size: var(--fc-field-size);
	font-weight: var(--fw-medium);
	color: var(--fc-cta-on);
}

body.fc-ds .fc-emailcta__input::placeholder {
	color: var(--fc-cta-ghost);
}

body.fc-ds .fc-emailcta__input:focus {
	outline: var(--stroke-1) solid var(--fc-violet);
	outline-offset: 0;
	border-color: var(--fc-violet);
}

body.fc-ds .fc-emailcta__input[aria-invalid="true"] {
	border-color: var(--fc-red);
}

body.fc-ds .fc-emailcta__submit {
	flex: none;
	height: 48px;
	padding: 0 var(--sp-24);
	border: var(--stroke-1) solid var(--fc-cta-on);
	border-radius: var(--radius-10);
	background: var(--fc-cta-on);
	font-family: var(--font-core);
	font-size: 14px;
	font-weight: var(--fw-medium);
	letter-spacing: var(--ls-label);
	text-transform: uppercase;
	color: var(--fc-cta-inv);
	cursor: pointer;
	transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

body.fc-ds .fc-emailcta__submit:hover {
	background: transparent;
	color: var(--fc-cta-on);
}

body.fc-ds .fc-emailcta__submit[aria-busy="true"] {
	opacity: 0.6;
	pointer-events: none;
}

/*
 * THE ASK. While the block points at the contact page instead of collecting an address
 * — see fluent_commerce_ds_cta_captures() — the field and the row are gone and the
 * button is an <a>. It keeps .fc-emailcta__submit, so it is the same button in both
 * tones and cannot drift from the one it stands in for; these are the declarations an
 * anchor needs that a <button> gets for nothing.
 *
 * align-items: flex-start on the column, because a stretched anchor would run the full
 * width of the split's second half, and this button is 48px of type on the same optical
 * line as the one it replaces.
 *
 * The type overrides are the difference between a submit and a CTA. .fc-emailcta__submit is
 * set in uppercase 14px with label tracking, which is how every form control on the site
 * reads; this is no longer a form control, so the caps and the tracking come off and the
 * arrow goes on at .fc-btn's 12px gap. They are stated here rather than removed from the
 * submit above, because that submit returns the day this block captures again.
 *
 * The size is --fc-field-size, NOT --type-mono-14. .fc-btn is set in the mono token and that
 * would be the obvious match, but the token is fluid in this sheet —
 * clamp(12px, calc(11.49px + 0.131cqw), 14px) — so it reaches 14px only in a container wider
 * than about 1250px and renders 12px on a phone. Uppercase carries that; sentence case does
 * not, and the label read undersized everywhere below full width. --fc-field-size is 16px
 * flat, it is what the input beside it used, and it is the site's control size. So the ask is
 * a touch larger than a .fc-btn and does not shrink, which is correct for the one button a
 * page closes on.
 */
body.fc-ds .fc-emailcta__ask {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--sp-16);
}

body.fc-ds .fc-emailcta__ask-btn {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	font-size: var(--fc-field-size);
	letter-spacing: normal;
	text-transform: none;
	text-decoration: none;
	white-space: nowrap;
}

body.fc-ds .fc-emailcta__fine {
	color: var(--fc-cta-dim);
}

/*
 * The opt-in, added 2026-08-25 when every form on the site got one. On top of the
 * form's own 12px gap, not instead of it: 12px is this form's FIELD rhythm, and at that
 * distance a consent statement reads as another control to fill in rather than a
 * sentence about the one above it. See THE CONSENT BLOCK below for the component.
 */
body.fc-ds .fc-emailcta__form .fc-consent {
	margin-top: var(--sp-8);
}

/*
 * The bracket-and-glyph error mark — [ ! ] set in mono. This is one of the two
 * places the signal colours are allowed, and the mono face is legitimate here
 * because the bracket pair is a machine mark, not typography.
 */
body.fc-ds .fc-emailcta__error {
	display: flex;
	align-items: baseline;
	gap: var(--sp-8);
	font-size: 14px;
	color: var(--fc-red);
}

body.fc-ds .fc-emailcta__mark {
	font-family: var(--font-mono);
	font-size: var(--type-mono-14);
	font-weight: var(--fw-regular);
	letter-spacing: var(--ls-mono);
	font-variant-ligatures: none;
}

body.fc-ds .fc-emailcta__panel {
	display: flex;
	flex-direction: column;
	gap: var(--sp-16);
	padding: var(--sp-32);
	border: var(--stroke-1) solid var(--fc-cta-hair);
}

body.fc-ds .fc-emailcta__panel--ok .fc-emailcta__mark {
	color: var(--fc-green);
}

body.fc-ds .fc-emailcta__panel--fail {
	border-color: var(--fc-red);
}

body.fc-ds .fc-emailcta__panel-title {
	display: flex;
	align-items: baseline;
	gap: var(--sp-8);
	font-family: var(--font-display);
	font-size: var(--type-h5-24);
	line-height: var(--lh-snug);
	color: var(--fc-cta-on);
}

/* Copy inside a panel, so the same step as card and table copy. */
body.fc-ds .fc-emailcta__panel-body {
	font-size: var(--type-body-15);
	line-height: var(--lh-loose);
	color: var(--fc-cta-muted);
}

/* The reference is machine-generated, so it is genuinely a mono string. */
body.fc-ds .fc-emailcta__ref {
	font-family: var(--font-mono);
	font-size: var(--type-mono-16);
	letter-spacing: var(--ls-mono);
	font-variant-ligatures: none;
	color: var(--fc-cta-on);
}

/* Hidden until the script swaps states; no-JS never sees either panel. */
body.fc-ds .fc-emailcta [hidden] {
	display: none !important;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE LOGO ROW
 * Twelve customer marks in a plain 6 × 2, centred. Not .fc-grid-*: the tracks are
 * a FIXED 104px rather than 1fr, because logos are normalised by optical weight,
 * not by column width — a 1fr track would make the H&M mark and the JD Sports
 * mark different sizes on every viewport. The row gap is larger than the column
 * gap for the same reason the wall's is: marks read as a field, and a square gap
 * makes them read as a table.
 *
 * A primitive rather than a composition because it is the design's own recurring
 * proof strip — the report page is simply the first page to ask for it.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-logo-row {
	display: grid;
	grid-template-columns: repeat(6, 104px);
	justify-content: center;
	align-items: center;
	gap: 32px 54px;
	width: 100%;
}

@container page (max-width: 1100px) {
	body.fc-ds .fc-logo-row {
		grid-template-columns: repeat(4, 104px);
		gap: 32px 48px;
	}
}

@container page (max-width: 820px) {
	body.fc-ds .fc-logo-row {
		grid-template-columns: repeat(4, 96px);
		gap: 28px 40px;
	}
}

@container page (max-width: 440px) {
	body.fc-ds .fc-logo-row {
		grid-template-columns: repeat(2, 88px);
		gap: 24px 32px;
	}
}

/*
 * One mark. Same --mark contract as the proof wall's tile, but deliberately NOT
 * its --mark-h: the wall normalises twelve logos by optical weight because they
 * sit in tiles of different sizes, whereas the row gives every mark the same
 * 104 × 26 box and lets background-size: contain fit it. That is the export's
 * own decision and it is the right one here — in a single even row, a mark drawn
 * 12px taller than its neighbour reads as a mistake rather than as balance.
 */
body.fc-ds .fc-logo-row__mark {
	display: block;
	width: 100%;
	height: 26px;
	opacity: 0.8;
	background-image: var(--mark);
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * SPLIT SECTIONS
 * Two columns until 1024, then stack.
 *
 * RULE: the argument leads. Mark the copy column .fc-first and it comes first
 * when stacked, whatever the source order — so an image-left composition becomes
 * copy-then-image on a phone.
 *
 * .fc-lead is honoured too, because a single 26px lead paragraph IS often the copy
 * column. But .fc-lead is a TYPE role — put it on a wrapping <div> and every
 * paragraph inside inherits 26px. So a column that wraps several elements gets
 * .fc-first, and only the paragraph itself ever gets .fc-lead.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-split {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--gap-blocks);
	align-items: start;
}

body.fc-ds .fc-split-center {
	align-items: center;
}

/*
 * 1fr 2fr — a heading against a much longer body. The export's own class name, and the
 * commonest split on the site after the primitive: the three Knowledge Hub pages have it on
 * eight sections between them and the About page's "We're global. We're local." is the
 * ninth.
 *
 * WRITTEN INSIDE A MIN-WIDTH QUERY, which is the whole trick and the reason this is four
 * lines rather than one. The rule below stacks .fc-split to a single column at
 * @container page (max-width: 1100px), and it comes AFTER this — so an unconditional
 * grid-template-columns here would be undone on a phone, which is the behaviour we want,
 * but only by accident of source order. Stating the width the split is two columns at is
 * what makes it survive a page stylesheet being reordered or a fourth caller arriving.
 *
 * It began as .fc-kb-split in knowledge.css and moved here when About Us became the first
 * caller from outside the Hub — which is the promotion that file's own header names as the
 * trigger. .fc-kb-split is still there and still identical; collapsing it means re-seeding
 * three pages to re-class markup nobody can see, so it goes on the next re-seed those pages
 * need for another reason. See THE SPLITS in knowledge.css.
 */
@container page (min-width: 1101px) {
	body.fc-ds .fc-split-13 {
		grid-template-columns: 1fr 2fr;
	}
}

@container page (max-width: 1100px) {
	body.fc-ds .fc-split {
		grid-template-columns: 1fr;
	}

	body.fc-ds .fc-split > .fc-first,
	body.fc-ds .fc-split > .fc-lead {
		order: -1;
	}
}

/*
 * A grid item defaults to min-width:auto, so any column whose content has a wide
 * min-content — a fixed-padding panel, a form control, a long unbroken URL —
 * forces its 1fr track wider than the container and silently eats the page
 * gutter. This is the fix for every narrow column, not one page.
 */
body.fc-ds .fc-split > *,
body.fc-ds .fc-grid > * {
	min-width: 0;
}

body.fc-ds input,
body.fc-ds select,
body.fc-ds textarea {
	min-width: 0;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * RAIL SPLIT
 * A narrow index that stays put beside a long column that scrolls — the design's
 * arrangement for the Innovation page's five capabilities, and the reason it is in
 * here rather than in innovation.css: the export declares it in its own shared
 * responsive sheet, not on the page, and the next long column that wants an index
 * beside it should not have to find it in a page file.
 *
 * The rail track is minmax(0, 400px) rather than a bare 400px so the rail gives way
 * first as the page narrows; the column beside it is minmax(0, 1fr) for the reason
 * stated under SPLIT SECTIONS above.
 *
 * top: 120px, which is --pad-section, not --nav-height: the rail should settle at the
 * same distance from the top of the viewport as a section's own top padding, so it
 * lines up with the content rather than tucking under the nav.
 *
 * Below 1100 it stops being a rail at all — a sticky index above a stacked column
 * would sit at the top of the viewport covering the thing it indexes. It becomes a
 * static heading with a list under it, and everything still works because the rows
 * are anchors.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-rail-split {
	display: grid;
	grid-template-columns: minmax(0, 400px) minmax(0, 1fr);
	gap: var(--gap-blocks);
	align-items: start;
}

body.fc-ds .fc-rail-split > * {
	min-width: 0;
}

body.fc-ds .fc-rail-split > .fc-sticky-rail {
	position: sticky;
	top: var(--pad-section);
}

@container page (max-width: 1100px) {
	body.fc-ds .fc-rail-split {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--sp-54);
	}

	body.fc-ds .fc-rail-split > .fc-sticky-rail {
		position: static;
	}
}

/* ─────────────────────────────────────────────────────────────────────────────
 * MEDIA
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-media {
	display: block;
	width: 100%;
	height: clamp(300px, 32cqw, 640px);
	object-fit: cover;
}

/*
 * Panel padding, fluid. 54 is a naked constant that would leave a phone about
 * 242px of field width.
 */
body.fc-ds .fc-panel {
	padding: clamp(24px, 5cqw, 54px);
}

/*
 * THE RECORD SLEEVE
 * The brand's frame for a photograph: a square, printed-card texture with the
 * image inset into it. In the export this is a JS component that hard-codes a
 * pixel size and then gets overridden by four !important rules; here the size is
 * the container's and the texture is the CSS, so there is nothing to override.
 * Callers set --sleeve-max when a composition needs it smaller than 420.
 */
body.fc-ds .fc-sleeve {
	position: relative;
	width: 100%;
	max-width: var(--sleeve-max);
	aspect-ratio: 1;
	overflow: hidden;
	background: url("img/record-sleeve.webp") center / cover no-repeat;
	flex-shrink: 0;
}

body.fc-ds .fc-sleeve > img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * STACKS
 * The design's single most repeated construct: a column of two or three things
 * with one gap between them. It appears as `display:flex;flex-direction:column;
 * gap:24px` roughly forty times across the two page files, so it is a primitive
 * rather than a composition. --stack-gap is the knob; --center is the section
 * head that every "headline, standfirst, button" block wants.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-stack {
	display: flex;
	flex-direction: column;
	gap: var(--stack-gap, var(--sp-24));
}

body.fc-ds .fc-stack--center {
	align-items: center;
	text-align: center;
}

/*
 * The gap steps, as modifiers rather than as a --stack-gap declaration in every
 * page rule. Only the scale is offered: if a composition wants 18 or 20 it says
 * so itself and takes the explanation with it.
 */
body.fc-ds .fc-stack--8 {
	--stack-gap: var(--sp-8);
}

body.fc-ds .fc-stack--16 {
	--stack-gap: var(--sp-16);
}

body.fc-ds .fc-stack--32 {
	--stack-gap: var(--sp-32);
}

body.fc-ds .fc-stack--54 {
	--stack-gap: var(--sp-54);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * IMAGE BANDS
 * A full-bleed photographic band with copy over it. The height is the image's
 * own ratio expressed against the page container, NOT aspect-ratio, because a
 * ratio is a ceiling as well as a floor: at 390 the waves band would be 127px
 * tall and would clip its own headline. min-height means the copy can always
 * push the band taller, and the image crops rather than distorting — which is
 * also why the background is object-fit: cover and not the export's `fill`.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-band {
	position: relative;
	min-height: calc(100cqw * var(--band-h, 1) / var(--band-w, 2));
	overflow: hidden;
}

/*
 * .fc-cover is the same declaration under a name that does not claim to be a band:
 * an image that fills its positioned parent. Three things need it that are not
 * bands — the home hero's magnetic field, and the two team cards on the OMS page —
 * and duplicating five lines three times is how a fourth one ends up subtly
 * different. .fc-band__bg stays as the band's own name for it.
 */
body.fc-ds .fc-band__bg,
body.fc-ds .fc-cover {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

body.fc-ds .fc-band__inner {
	position: relative;
	z-index: 2;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * MOTION — A STILL THAT MOVES
 * The brand has two pieces of artwork that also exist as film: the hero's field
 * and the globe. Neither is a video slot in the design — each one is the still,
 * with the film laid over it and cross-faded in once it is actually playing.
 *
 * So .fc-motion is a <video> that covers its parent and starts invisible. The
 * still underneath is the poster, the fallback and the print: if the file never
 * loads, if the visitor asked for less motion, if the browser declines autoplay,
 * or if JavaScript never runs, the page looks finished — because the picture is
 * the same picture. assets/ds/video.js is what adds .is-playing, and it is the
 * only thing that ever sets a src. See the note there on why.
 *
 * Ported from .fc-home-hero__video / .fc-home-twoup__video in assets/home.css,
 * which are the same declarations written twice. Their positioning offsets are
 * NOT ported: those framed the film against the legacy hero's own height, and
 * this hero is a fold. Here the video is framed exactly as its still is, which is
 * what makes the handover invisible.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-motion {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	transition: opacity var(--dur-slow) var(--ease-out);
	pointer-events: none;
}

body.fc-ds .fc-motion.is-playing {
	opacity: 1;
}

/*
 * The positioning parent, for the slots that do not already have one. A fold and
 * a band are position: relative in their own right; a .fc-media in a split column
 * is not, so it gets wrapped in this. Nothing else: the height is still the
 * image's, which is what keeps the two layers the same size.
 */
body.fc-ds .fc-motion-frame {
	position: relative;
}

/*
 * Reduced motion: not faded out, removed. video.js returns before it loads
 * anything in this case, so this is belt and braces — but it is also the only
 * layer that can help if the class is ever added by something else, since the
 * global rule in tokens.css collapses transition durations and would turn the
 * fade into a cut rather than preventing it.
 */
@media (prefers-reduced-motion: reduce) {
	body.fc-ds .fc-motion {
		display: none;
	}
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE MARQUEE BAND
 * A single-line ink band of scrolling claims. The track holds the phrase list
 * TWICE and travels -50%, which is what makes the loop seamless — so a caller
 * that changes the phrase count must still emit two identical halves.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-marquee-band {
	display: flex;
	align-items: center;
	height: var(--marquee-height);
	overflow: hidden;
}

body.fc-ds .fc-marquee-track {
	display: flex;
	align-items: center;
	flex: none;
	width: max-content;
	gap: var(--gap-marquee);
	padding-left: var(--gap-marquee);
	animation: fcMarquee 96s linear infinite;
}

@keyframes fcMarquee {
	from {
		transform: translateX(0);
	}

	to {
		transform: translateX(-50%);
	}
}

/* ────────────────────────────────────────────────────────────────────────────
 * THE PHOTO GALLERY
 *
 * A long horizontal track of photographs over white, the one on the centre line held at
 * full opacity and the rest dimmed to 0.45, with a line of flat ink laid across all of it.
 * Build-16's Partners header; the Customers page is its second caller since 2026-08-27,
 * which is when this block moved here from partners.css. The section was
 * .fc-partners-gallery-sec then and is .fc-gallery-sec now — everything inside it was
 * already named as though it were shared, so one class changed and nothing else did.
 *
 * The markup is fluent_commerce_ds_gallery_markup() in inc/ds-blocks.php. Callers supply
 * their own frames, their own line of type and, if the type needs a narrower measure than
 * one word, one modifier class of their own — .fc-customers-gallery-sec is the only one.
 *
 * ── EVERY BOX IS THE DESIGN'S, MULTIPLIED BY ONE NUMBER ────────────────────
 *
 * A frame's width, height and PLACE on the track are the export's own pixels and they arrive
 * INLINE on the frame as --fc-cell-w/h/x, because only the markup knows which frame is which.
 * Every one of those numbers is then multiplied by --fc-gallery-scale, declared here on the
 * section and stepped down by the container queries at the foot of this block. That is the
 * same division of labour --fc-flip-cols made, for the same reason: an inline custom property
 * beats every container query trying to override it, so the markup states facts and this
 * sheet states the responsive numbers. One multiplier moves the band's height, every box,
 * their spacing, the slide distance and the type's inset together.
 *
 * The export gives no responsive behaviour for this section at all — Build-16's
 * system/responsive.css says nothing about it, and 640px of fixed-pixel photographs would be
 * a phone screen and a half. The four steps below are this theme's, and they are in
 * fluent_commerce_ds_gallery_cell() as well, in each frame's `sizes` attribute: sizes is
 * resolved before any CSS is, so it cannot be handed a custom property. If a breakpoint or a
 * scale moves here it moves there too, or a phone fetches the desktop file.
 *
 * ── THE TRACK IS A ZERO-WIDTH ORIGIN ON THE CENTRE LINE ────────────────────
 *
 * left: 50% with width: 0, which is the export's own construction and the reason the geometry
 * is simple: a frame is centred when the track is slid left by the distance from the origin
 * to that frame's middle. --fc-gallery-shift is that distance, unitless, in design pixels,
 * written inline by the markup for the resting frame and rewritten by gallery.js after that.
 * It is unitless so this sheet can put it through the scale before turning it into pixels.
 *
 * ── THE RESTING STATE IS THE WHOLE SECTION ─────────────────────────────────
 *
 * With no script this is a still band with the resting photograph lit, which is a
 * composition. Everything gallery.js adds is gated below on .is-live, which only the script
 * sets — the house bargain, and here it also covers cursor: none, because taking the pointer
 * away is only safe once something is drawing one in its place.
 *
 * prefers-reduced-motion is handled globally in tokens.css, which zeroes every transition
 * under body.fc-ds: the band then cuts between frames instead of sliding, and gallery.js
 * separately declines to run its own timer at all. Nothing auto-advances, and a click or a
 * drag still works.
 * ──────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-gallery-sec {
	--fc-gallery-scale: 1;
	/* The ruled column's inset, mirrored so the type lines up with the copy below it.
	   Halved at 820 in THE RULED COLUMN above, and here, in the one query at the foot of
	   this block. */
	--fc-gallery-inset: calc(var(--gutter-page) + 40px);
	position: relative;
	height: calc(640px * var(--fc-gallery-scale));
	background: var(--surface-lightest);
	/* The track is thousands of pixels wide and this is what keeps it off the scrollbar. */
	overflow: hidden;
}

/*
 * The viewport the track slides inside, and the element the script listens on. role="img"
 * lives here rather than on the section, because it makes its whole subtree presentational
 * and the section also holds the h1.
 */
body.fc-ds .fc-gallery {
	position: absolute;
	inset: 0;
	overflow: hidden;
}

body.fc-ds .fc-gallery__track {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 50%;
	width: 0;
	transform: translateX(calc(var(--fc-gallery-shift) * var(--fc-gallery-scale) * -1px));
	/* The export's own easing. It leaves late and lands slowly, which is what makes a 500ms
	   slide of this distance read as one movement rather than a jump. The export's own duration
	   was 620; this band was asked to move faster, and the slide came down with the interval. */
	transition: transform 500ms cubic-bezier(0.2, 0, 0, 1);
	will-change: transform;
}

/*
 * A finger is holding the track, so it goes where the finger is with no easing at all — the
 * same rule story.js makes. The transition comes back the moment the pointer lifts, which is
 * what animates the settle onto the committed frame.
 */
body.fc-ds .fc-gallery-sec.is-dragging .fc-gallery__track {
	transition: none;
}

body.fc-ds .fc-gallery__cell {
	position: absolute;
	top: 50%;
	left: calc(var(--fc-cell-x) * var(--fc-gallery-scale));
	width: calc(var(--fc-cell-w) * var(--fc-gallery-scale));
	height: calc(var(--fc-cell-h) * var(--fc-gallery-scale));
	/* Centred on the track's own middle, whatever this frame's height is. */
	margin-top: calc(var(--fc-cell-h) * var(--fc-gallery-scale) / -2);
	overflow: hidden;
	opacity: 0.45;
	/* Matched to the track's slide, so the frame arrives and lights at the same moment. */
	transition: opacity 500ms ease-out;
}

body.fc-ds .fc-gallery__cell.is-active {
	opacity: 1;
}

body.fc-ds .fc-gallery__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * ── THE TYPE ────────────────────
 *
 * 132px of Instrument Sans semibold, and it is the only place in the system that goes above
 * the display ramp's 80 — so there is no token for it and the ramp is written out here. It is
 * derived the way this file derives every other one rather than lifted from the export's
 * `clamp(53px, 7.15vw, 132px)`: linear between a 390 container and a 1920 one, floored at the
 * export's own 53 and reaching its own 132 at 1920. The slope is (132 - 53) / 15.30 per cqw.
 * cqw and not vw, because every other measurement in this system is against the container.
 *
 * That ramp is sized for ONE WORD. A caller with a sentence in it overrides the size and adds
 * a measure — see .fc-customers-gallery-sec in customers.css, which is the only one, and
 * which is why nothing here sets a max-width: a width on a single word would be a wrap
 * waiting to happen at some container size nobody tested.
 *
 * The line height and tracking are the export's two numbers and there are no tokens near
 * them: --lh-flush is 1 where this wants 0.86, and --ls-display is -0.01em where a word this
 * size wants -0.03em. Both are properties of one 132px word rather than of the type system.
 *
 * The type sits ON the photographs, flat ink, no blend. It was built the other way first —
 * mix-blend-mode: difference, white text, so the word inverted wherever a frame passed under
 * it — and that was pulled: over the brighter frames difference lands the letter close enough
 * to the photograph beneath it that the word reads as half transparent rather than as type on
 * top of a picture. Flat ink at z-index 2 has no such failure mode; the frames are already
 * dimmed to 0.45 behind it and the active one is a photograph rather than a white field, so
 * the contrast is there without a scrim. Nothing here is @supports-gated any more, which also
 * means every browser now gets the same header.
 *
 * pointer-events: none, because the whole band is one click target and the type must not
 * take the click or the drawn cursor's position.
 */
body.fc-ds .fc-gallery__word {
	position: absolute;
	top: calc(54px * var(--fc-gallery-scale));
	left: var(--fc-gallery-inset);
	z-index: 2;
	margin: 0;
	font-family: var(--font-core);
	font-weight: var(--fw-semibold);
	font-size: clamp(53px, calc(32.86px + 5.163cqw), 132px);
	line-height: 0.86;
	letter-spacing: -0.03em;
	color: var(--text-on-light);
	pointer-events: none;
}

/*
 * ── THE DRAWN CURSOR ────────────────────
 *
 * The band replaces the pointer with a 34px arrow that points the way a click will go, which
 * is the section's only affordance — there is no dot row, no arrow buttons and nothing to
 * read. Both halves of that are gated on .is-live: the arrow is invisible until the script
 * is placing it, and the real pointer is only taken away once the arrow can stand in for it.
 *
 * The script writes --fc-cursor-x/y on this element and flips the arrow with
 * --fc-cursor-flip. Custom properties rather than inline top/left, so one style attribute on
 * one element carries the whole thing and the sheet keeps the geometry — including the 32px
 * that centres the box on the pointer, which the script then never has to know about.
 */
body.fc-ds .fc-gallery__cursor {
	position: absolute;
	top: var(--fc-cursor-y, 50%);
	left: var(--fc-cursor-x, 50%);
	z-index: 4;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 64px;
	height: 64px;
	/* The box is centred on the pointer, so the arrow sits where the cursor was. */
	margin: -32px 0 0 -32px;
	color: var(--text-on-light);
	opacity: 0;
	transition: opacity 200ms ease-out;
	pointer-events: none;
}

body.fc-ds .fc-gallery__cursor svg {
	transform: scaleX(var(--fc-cursor-flip, 1));
}

body.fc-ds .fc-gallery-sec.is-live .fc-gallery__cursor.is-shown {
	opacity: 1;
}

/*
 * user-select and touch-action are the drag's, so they wait for the drag. pan-y and not none:
 * a horizontal gesture is the band's, a vertical one is the page's, and taking both would
 * make a full-width band at the top of the page a place a phone cannot scroll past.
 */
body.fc-ds .fc-gallery-sec.is-live {
	touch-action: pan-y;
	-webkit-user-select: none;
	user-select: none;
}

/*
 * Only where there is a real pointer to hide. A touch device has no cursor to replace and
 * cursor: none on a hybrid would take the mouse away from anyone who plugs one in.
 */
@media (hover: hover) and (pointer: fine) {
	body.fc-ds .fc-gallery-sec.is-live {
		cursor: none;
	}
}

/*
 * The step-downs. 640px of band is most of a phone screen for something decorative, and the
 * frames inside it are up to 640px wide on their own. These bring the band to 544 / 461 / 371
 * / 307 and every box with it, which is a header rather than a fold.
 *
 * Written widest-first: each query also matches every container narrower than itself, so the
 * narrow ones have to come last to win on source order.
 *
 * These four numbers appear twice. Every frame's `sizes` attribute states the same table, in
 * fluent_commerce_ds_gallery_cell() — see the note at the head of this block.
 */
@container page (max-width: 1100px) {
	body.fc-ds .fc-gallery-sec {
		--fc-gallery-scale: 0.85;
	}
}

@container page (max-width: 900px) {
	body.fc-ds .fc-gallery-sec {
		--fc-gallery-scale: 0.72;
	}
}

/* The ruled inset halves here in THE RULED COLUMN, so the type follows it. */
@container page (max-width: 820px) {
	body.fc-ds .fc-gallery-sec {
		--fc-gallery-inset: calc(var(--gutter-page) + 20px);
	}
}

@container page (max-width: 640px) {
	body.fc-ds .fc-gallery-sec {
		--fc-gallery-scale: 0.58;
	}
}

@container page (max-width: 440px) {
	body.fc-ds .fc-gallery-sec {
		--fc-gallery-scale: 0.48;
	}
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE FOLD
 * A hero that owns the first screen. svh, not vh — on mobile Safari vh is the
 * LARGEST viewport, so a vh fold is always taller than what you can see and the
 * CTA sits under the address bar.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-fold {
	position: relative;
	height: calc(100svh - var(--nav-height));
	min-height: 420px;
	overflow: hidden;
}

body.fc-ds .fc-hero-copy {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	height: 100%;
}

/*
 * Copy sitting in the FOOT of the fold — the design's other hero arrangement, where the
 * artwork owns the whole frame and the words are pushed to the bottom-left of it rather
 * than centred in it. The OMS hero and the Integrations hero are the same composition at
 * this level; what differs is what is behind them (a dot grid and a wire drawing there, a
 * full-bleed cover image here) and that is each page's own stylesheet's business.
 *
 * .fc-oms-hero__copy in pages.css states these same four declarations and is NOT this
 * class, because that hero's markup lives in the OMS page's post_content: re-classing it
 * means re-seeding the page, which is a database write to fix a duplication nobody can
 * see. Left as a known duplicate deliberately — if a third fold wants a foot, that one
 * uses this and the note here is what tells you the OMS one exists.
 *
 * ORDER MATTERS: this sits ABOVE the two rules that follow, so the short-viewport
 * padding-bottom and the 820px padding-top still win over the shorthand here. Moving it
 * below them would silently undo both.
 */
body.fc-ds .fc-hero-copy--foot {
	justify-content: flex-end;
	align-items: flex-start;
	padding: 0 var(--gutter-page) 96px;
	text-align: left;
}

/*
 * A @media height query, not a container query, and it cannot be otherwise:
 * container queries need container-type: size to expose height, and that would
 * require every fold to declare its own height up front. This is the laptop-in-
 * landscape case, where 120px of hero padding is most of the screen.
 */
@media (max-height: 640px) {
	body.fc-ds .fc-hero-copy {
		padding-bottom: 32px;
		gap: var(--sp-16);
	}
}

/*
 * Below 768 a full-screen fold squeezes the copy, so it becomes a normal block.
 *
 * A fold whose copy is short enough not to be squeezed does not want this, and the
 * Integrations hero — one word and a button over a full-bleed picture — takes it back
 * in integrations.css. Read that note before generalising this one: releasing the
 * height there put the button in the middle of the artwork, because a foot padding
 * measured against 100svh is most of a collapsed band.
 */
@container page (max-width: 820px) {
	body.fc-ds .fc-fold {
		height: auto;
		min-height: 0;
	}

	body.fc-ds .fc-hero-copy {
		height: auto;
		padding-top: 32px;
	}
}

/* ─────────────────────────────────────────────────────────────────────────────
 * HERO WIRES
 * The violet lines that converge on the OMS hero. They draw themselves once, via
 * pathLength="1" on each path so one dash length works for every path whatever
 * its real geometry. The stagger is per-child and deliberately not uniform.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-wires {
	position: absolute;
	inset: 0;
	z-index: 1;
	width: 100%;
	height: 100%;
	pointer-events: none;
}

body.fc-ds .fc-wire {
	stroke-dasharray: 1;
	stroke-dashoffset: 1;
	animation: fcWireDraw 1400ms var(--ease-out) forwards;
}

body.fc-ds .fc-wire:nth-child(2) {
	animation-delay: 120ms;
}

body.fc-ds .fc-wire:nth-child(3) {
	animation-delay: 240ms;
}

body.fc-ds .fc-wire:nth-child(4) {
	animation-delay: 180ms;
}

body.fc-ds .fc-wire:nth-child(5) {
	animation-delay: 300ms;
}

body.fc-ds .fc-wire:nth-child(6) {
	animation-delay: 60ms;
}

@keyframes fcWireDraw {
	from {
		stroke-dashoffset: 1;
	}

	to {
		stroke-dashoffset: 0;
	}
}

/*
 * The global reduced-motion rule shortens animations, which for a self-drawing
 * line would flash. These need the END state, so they are named explicitly.
 */
@media (prefers-reduced-motion: reduce) {
	body.fc-ds .fc-wire {
		animation: none;
		stroke-dashoffset: 0;
	}
}

/*
 * Below 820 the fold releases its height, so the wires stop being the background
 * of the copy and become a band above it — and a band needs a different frame.
 *
 * On desktop the drawing deliberately uses only the top half and right two thirds
 * of its 1920 × 900 box; the empty part is where the copy sits. Put that same box
 * in flow at full width and the ratio collapses to a shallow strip in which the
 * routes are a sliver in the top-right corner, drawing themselves at a stroke of
 * under 2 device px. Nothing is wrong with the animation — there is just nothing
 * big enough to see, which is exactly how it reads.
 *
 * So the band frames the DRAWING rather than the SVG. --crop-* is the bounding box
 * of the routes in the SVG's own user units, declared by the view that owns the
 * geometry (the OMS hero, in pages.css); the group is scaled so that box fills the
 * viewBox, and the band's height comes from the same ratio, which means the crop is
 * rendered undistorted even though the SVG is still preserveAspectRatio="none".
 * The fallbacks are the whole viewBox — i.e. no crop, today's behaviour — so a view
 * that uses .fc-wires without declaring a crop is unaffected.
 */
@container page (max-width: 820px) {
	body.fc-ds .fc-wires {
		position: relative;
		height: calc(100cqw * var(--crop-h, 900) / var(--crop-w, 1920));
	}

	/*
	 * transform-origin must be stated: on an SVG element transform-box already
	 * defaults to the view-box, but transform-origin still defaults to 50% 50%,
	 * which would scale about the centre of the frame instead of its 0 0.
	 * The functions apply right to left — translate first, then scale.
	 */
	body.fc-ds .fc-wires > g {
		transform-box: view-box;
		transform-origin: 0 0;
		transform:
			scale(calc(1920 / var(--crop-w, 1920)), calc(900 / var(--crop-h, 900)))
			translate(calc(var(--crop-x, 0) * -1px), calc(var(--crop-y, 0) * -1px));
	}

	/*
	 * 6 units is 4.5 device px on a 1440 desktop. Through the crop on a phone it
	 * lands at 1.9, which reads as a hairline rather than as a route, so the weight
	 * is restated for the smaller frame.
	 */
	body.fc-ds .fc-wire {
		stroke-width: 10;
	}
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE STAT BAND
 * Three figures on shared hairlines, full-bleed to the section edges. The rules
 * are shared, so it is a ruled table like .fc-cols-5 and not a card grid: no
 * gap, one border-left per column, and the first column drops its own.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-statband {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	border-top: var(--stroke-1) solid var(--border-on-light);
	border-bottom: var(--stroke-1) solid var(--border-on-light);
}

body.fc-ds .fc-statcol {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--sp-16);
	padding: var(--sp-54) var(--sp-32);
	border-left: var(--stroke-1) solid var(--border-on-light);
	text-align: center;
}

body.fc-ds .fc-statcol:first-child {
	border-left: 0;
}

/* Three 96px numerals will not sit side by side on a phone. */
@container page (max-width: 820px) {
	body.fc-ds .fc-statband {
		grid-template-columns: 1fr;
	}

	body.fc-ds .fc-statcol {
		border-left: 0;
		border-top: var(--stroke-1) solid var(--border-on-light);
	}

	body.fc-ds .fc-statcol:first-child {
		border-top: 0;
	}
}

/* ─────────────────────────────────────────────────────────────────────────────
 * LONG-FORM MEASURE AND RHYTHM
 * 68ch is the article column. --sp-flow is the flow gap, overridable per block
 * so a stat grid or a pull quote can sit tighter than the paragraphs around it.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-measure {
	max-width: min(68ch, 100%);
}

body.fc-ds .fc-prose > * + * {
	margin-top: var(--sp-flow, 32px);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * TYPE ROLES
 * The export's ready-made classes from typography.css, carried so page CSS can
 * compose them instead of restating the numbers. Only the roles the blog uses.
 * ────────────────────────────────────────────────────────────────────────── */
/*
 * The step above the page hero. Its name is the export's, not ours — Build-16's
 * typography.css calls this role .fc-display-slide — and it earns a place here the
 * way .fc-split-13 did: the About page's "We're global. We're local." moved up to
 * it, and the next page that wants an 80px statement should compose the class
 * rather than restate the four declarations.
 */
body.fc-ds .fc-display-slide {
	font-family: var(--font-display);
	font-weight: var(--fw-regular);
	font-size: var(--type-display-80);
	line-height: var(--lh-flush);
	letter-spacing: var(--ls-display);
	text-wrap: pretty;
}

body.fc-ds .fc-display-hero {
	font-family: var(--font-display);
	font-weight: var(--fw-regular);
	font-size: var(--type-display-72);
	line-height: var(--lh-flush);
	letter-spacing: var(--ls-display);
	/* Serif display type at 72px breaks badly on a widow. */
	text-wrap: pretty;
}

body.fc-ds .fc-display-section {
	font-family: var(--font-display);
	font-weight: var(--fw-regular);
	font-size: var(--type-display-62);
	line-height: var(--lh-flush);
	letter-spacing: var(--ls-display);
	text-wrap: pretty;
}

body.fc-ds .fc-lead {
	font-family: var(--font-core);
	font-weight: var(--fw-regular);
	font-size: var(--type-lead-26);
	line-height: var(--lh-body);
}

body.fc-ds .fc-h5 {
	font-family: var(--font-core);
	font-weight: var(--fw-semibold);
	font-size: var(--type-h5-24);
	line-height: var(--lh-snug);
}

body.fc-ds .fc-body {
	font-family: var(--font-core);
	font-weight: var(--fw-medium);
	font-size: var(--type-body-18);
	line-height: var(--lh-body);
}

/*
 * The two smaller body sizes. --type-body-18 is the primary, but a paragraph set
 * INSIDE a composition — a card, a plate, a five-column table — steps down to 16
 * or 15 so the composition still has a hierarchy. 15 is the floor the brand
 * allows; there is no 14px body.
 *
 * The export sets these at 1.4/1.5/1.55 depending on where they appear. 1.55 is
 * not a fourth line-height token — it is a rounding of --lh-loose, and page CSS
 * that genuinely needs the looser leading sets it on the composition.
 */
body.fc-ds .fc-body-16 {
	font-family: var(--font-core);
	font-weight: var(--fw-medium);
	font-size: var(--type-body-16);
	line-height: var(--lh-body);
}

body.fc-ds .fc-body-15 {
	font-family: var(--font-core);
	font-weight: var(--fw-medium);
	font-size: var(--type-body-15);
	line-height: var(--lh-loose);
}

/*
 * THE DESIGN'S PARAGRAPH ROLE, and the one type class in here that also carries a
 * colour. Every composed page in Build-6 puts .fc-copy on every paragraph AND on the
 * sub-lead under a section heading, with bold strongs and violet links inside it — so
 * it is one class rather than a size, a leading, a colour and two descendant rules
 * restated at each call site.
 *
 * The size is --type-body-16, which is 18px here. That is not a departure from the
 * design: the export's own .fc-copy is clamp(16px, …, 18px), so 18 is its ceiling and
 * this is the same paragraph. See the reading-size note at the head of this file for
 * why the token is named 16 and set to 18, and the standing rule that body copy is
 * 18px even when a design file specifies 20.
 *
 * .fc-trust-copy in security.css is this role under the Trust Center's own name, and it
 * is deliberately NOT re-classed to this. That markup is stored in the page's
 * post_content, so renaming the class means re-seeding local, staging and live to
 * remove a duplication nobody can see — the same call .fc-hero-copy--foot makes about
 * .fc-oms-hero__copy. New pages use this one; that note is what tells you the other
 * exists.
 */
body.fc-ds .fc-copy {
	margin: 0;
	font-family: var(--font-core);
	font-weight: var(--fw-medium);
	font-size: var(--type-body-16);
	line-height: var(--lh-loose);
	color: var(--text-on-light);
	text-wrap: pretty;
}

body.fc-ds .fc-copy strong,
body.fc-ds .fc-copy b {
	font-weight: var(--fw-bold);
	color: var(--fc-ink-12);
}

body.fc-ds .fc-copy a {
	color: var(--fc-violet);
	border-bottom: var(--stroke-1) solid currentColor;
}

body.fc-ds .fc-copy a:hover {
	color: var(--fc-violet-bright);
}

/*
 * On ink. The link colour steps to --fc-violet-light because --fc-violet fails
 * contrast on #121212 — the same pairing .fc-em / .fc-em-dark makes below.
 */
body.fc-ds .fc-copy--dark {
	color: var(--text-on-dark);
}

body.fc-ds .fc-copy--dark strong,
body.fc-ds .fc-copy--dark b {
	color: var(--fc-white);
}

body.fc-ds .fc-copy--dark a {
	color: var(--fc-violet-light);
}

body.fc-ds .fc-copy--dark a:hover {
	color: var(--fc-bone);
}

body.fc-ds .fc-eyebrow {
	font-family: var(--font-core);
	font-weight: var(--fw-bold);
	font-size: var(--type-eyebrow-16);
	line-height: var(--lh-snug);
	letter-spacing: var(--ls-eyebrow);
	text-transform: uppercase;
}

/*
 * .fc-meta is the workhorse of this design — the 12px uppercase label that
 * carries topics, read times, breadcrumbs, dates, stat labels and attributions.
 * It appears more often on the blog than any other type role.
 */
body.fc-ds .fc-meta {
	font-family: var(--font-label);
	font-weight: var(--fw-medium);
	font-size: var(--type-label-12);
	line-height: 1.2;
	letter-spacing: var(--ls-label);
	text-transform: uppercase;
}

body.fc-ds .fc-quote {
	font-family: var(--font-quote);
	font-weight: var(--fw-regular);
	font-size: var(--type-quote-32);
	line-height: var(--lh-snug);
	letter-spacing: var(--ls-quote);
}

body.fc-ds .fc-numeral {
	font-family: var(--font-quote);
	font-weight: var(--fw-regular);
	font-size: var(--type-numeral-48);
	line-height: var(--lh-flush);
	letter-spacing: var(--ls-quote);
	/* Stat figures must align in a row, so tabular even in a proportional face. */
	font-variant-numeric: tabular-nums;
}

body.fc-ds .fc-mono {
	font-family: var(--font-mono);
	font-weight: var(--fw-regular);
	font-size: var(--type-mono-14);
	line-height: var(--lh-snug);
	letter-spacing: var(--ls-mono);
	font-variant-ligatures: none;
}

/*
 * INLINE EMPHASIS
 * Three roles for a phrase inside a sentence, from the export's responsive.css.
 * They change colour only — never weight, never size — because the display faces
 * carry the emphasis and a bolded serif at 32px is a different typeface.
 *
 * RULE: violet type is surface-dependent. On bone or white use .fc-em (#793DFF).
 * On ink or black use .fc-em-dark, because the same violet on #121212 fails
 * contrast. Getting this backwards is the one way to misuse these.
 *
 * .fc-mark is the washed version — violet on the violet tint. box-decoration-break
 * is what keeps the wash a continuous band when the phrase wraps across lines;
 * without it each line fragment gets its own padded box and the highlight breaks
 * into steps.
 */
body.fc-ds .fc-em {
	color: var(--fc-violet);
}

body.fc-ds .fc-em-dark {
	color: var(--fc-violet-light);
}

body.fc-ds .fc-mark {
	color: var(--fc-violet);
	background: var(--fc-violet-wash);
	padding: 0 0.12em;
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

/*
 * The same mark on ink. The violet wash is a light-surface colour and it disappears on
 * #121212, so on dark the band is white at 14% and the phrase is white — the highest
 * contrast on the page, which is what the design uses it for: the two cost figures on
 * Legacy OMS Modernization's "Where to start?".
 *
 * A separate class rather than .fc-mark inside .fc-copy--dark, for the reason stated
 * above: violet type is surface-dependent and .fc-em / .fc-em-dark already make the
 * reader choose. A mark that silently changed meaning by ancestor would be the one
 * inconsistency in the set.
 */
body.fc-ds .fc-mark--dark {
	color: var(--fc-white);
	background: rgba(255, 255, 255, 0.14);
	padding: 0 0.12em;
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

/*
 * THE SOLID MARK. Violet fill, white type — the strongest of the four, and the one the
 * design uses when the marked phrase is the sentence's subject rather than a stress inside
 * it: "Order Management System" in the home hero, the analyst naming the company in the
 * pricing page's Forrester quote.
 *
 * It was page-scoped on the pricing page as .fc-price-quote__mark, with a note saying the
 * second page to want it should lift it here as .fc-mark--fill. The home hero is that
 * second page, so here it is (2026-08-27). pricing.css still carries its own copy of these
 * declarations — identical, so nothing moved on that page — because switching it over means
 * rewriting a stored paragraph, and that is a separate errand from this one.
 *
 * WHY IT IS SURFACE-INDEPENDENT and the other two are not. .fc-mark and .fc-mark--dark
 * both put the ground's own colour behind the type, so which ground they are on decides
 * whether they are visible at all. This one brings its own ground. White on #793DFF is
 * 5.37:1 either way, so it needs no --dark twin and there should never be one.
 *
 * padding is the set's 0.12em and not the export's flat 4px, so the fill scales with the
 * phrase — the same mark has to work at the hero's 20px and at a 40px display line.
 */
body.fc-ds .fc-mark--fill {
	color: var(--fc-white);
	background: var(--fc-violet);
	padding: 0 0.12em;
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

/*
 * The washed mark, underlined. One quote in the Integrations carousel asks for it and
 * the reason is legible in the sentence: it marks three phrases in one breath — a
 * single view of the customer, of stock, of orders — and three washes in a row read as
 * a background, not as emphasis. The rule is what puts the stress back on each one.
 *
 * text-underline-offset is the export's 3px. Fraunces has a low descender and the
 * default offset cuts through it.
 */
body.fc-ds .fc-mark--u {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * BUTTONS
 * One geometry — 48 tall, 22 of side padding, the 10px control radius — and
 * three colourways, because the brand only ever has three: filled white on a
 * dark surface, outlined bone on a dark surface, outlined ink on a light one.
 * Every CTA in the design is one of these; if a fourth seems needed, it isn't.
 *
 * There is now one exception, and it is a real one rather than a slip: the
 * Security Trust Center header rests its button filled violet and hovers it to
 * ink. That is a resting colour, not a hover treatment to be talked out of, and
 * a page cannot state it in --fc-btn-bg without also owning the hover, the
 * border and the label. So it is .fc-btn--violet below, on the same two
 * custom properties as the other three. It is the page's primary action on
 * bone, and the only place on the site that uses it. Before adding a fifth,
 * check the same question this one passes: does the design REST it that way?
 *
 * The variants are written .fc-btn.fc-btn--x rather than .fc-btn--x on purpose:
 * base.css hangs a link colour off [data-surface="dark"] a:hover, and a single
 * class would tie with it on specificity and win only by load order. Two classes
 * settles it outright.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-btn {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	flex: none;
	align-self: flex-start;
	height: 48px;
	padding: 0 22px;
	border: var(--stroke-1) solid var(--fc-btn-edge, var(--fc-btn-on));
	border-radius: var(--radius-10);
	background: var(--fc-btn-bg);
	font-family: var(--font-core);
	font-size: var(--type-mono-14);
	font-weight: var(--fw-medium);
	color: var(--fc-btn-on);
	white-space: nowrap;
	cursor: pointer;
	transition: background 160ms var(--ease-out), color 160ms var(--ease-out), border-color 160ms var(--ease-out);
}

/* The arrow never rotates, slides or grows. It is a full stop, not an animation. */
body.fc-ds .fc-btn__arrow {
	flex: none;
}

/*
 * align-self on the button beats align-items on its parent, so a CTA in a centred
 * stack would sit hard left without this. Stated here rather than in page CSS
 * because it is a property of the pairing, not of any one page.
 */
body.fc-ds .fc-stack--center > .fc-btn {
	align-self: center;
}

/* Filled white — the primary action, and only ever on a dark surface. */
body.fc-ds .fc-btn--fill {
	--fc-btn-bg: var(--fc-white);
	--fc-btn-on: var(--fc-ink-12);
}

body.fc-ds .fc-btn.fc-btn--fill:hover {
	border-color: var(--fc-violet);
	background: var(--fc-violet);
	color: var(--fc-white);
}

/* Outlined bone — the secondary action on a dark surface. */
body.fc-ds .fc-btn--light {
	--fc-btn-bg: transparent;
	--fc-btn-on: var(--fc-bone);
}

body.fc-ds .fc-btn.fc-btn--light:hover {
	background: var(--fc-bone);
	color: var(--fc-ink-12);
}

/* Outlined ink — the action on a light surface. */
body.fc-ds .fc-btn--dark {
	--fc-btn-bg: transparent;
	--fc-btn-on: var(--fc-ink-12);
}

body.fc-ds .fc-btn.fc-btn--dark:hover {
	background: var(--fc-ink-12);
	color: var(--fc-bone);
}

/*
 * Filled ink — the primary action on a LIGHT surface, and the pair to --dark
 * beside it. It passes the test the note above sets: the Partners lead rests
 * "Become one" as a solid ink button next to an outlined "Find one", and both
 * sit on bone. Without it the two read as one button and the same button
 * mid-hover, because --dark's hover state IS this colourway.
 *
 * Hovers to violet like --fill does, rather than to bone: an ink button on bone
 * cannot hover to its own surface.
 */
body.fc-ds .fc-btn--ink {
	--fc-btn-bg: var(--fc-ink-12);
	--fc-btn-on: var(--fc-bone);
	--fc-btn-edge: var(--fc-ink-12);
}

body.fc-ds .fc-btn.fc-btn--ink:hover {
	border-color: var(--fc-violet);
	background: var(--fc-violet);
	color: var(--fc-white);
}

/*
 * Filled violet — see the exception in the note above. The label stays white
 * through the hover: the fill goes violet → ink, and both carry white.
 */
body.fc-ds .fc-btn--violet {
	--fc-btn-bg: var(--fc-violet);
	--fc-btn-on: var(--fc-white);
	--fc-btn-edge: var(--fc-violet);
}

body.fc-ds .fc-btn.fc-btn--violet:hover {
	border-color: var(--fc-ink-12);
	background: var(--fc-ink-12);
	color: var(--fc-white);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE LOCKUP
 * A field and its button inside one bordered row, 62px tall. The design's own
 * primitive, and its own name: the export declares it in system/responsive.css
 * under .fc-lockup and seven pages use it — the email CTA block, Compare Us,
 * the Breitling story, the Buyer's Guide, Price Us, the Report, and Request a
 * Demo. So it is here rather than in any one page's sheet. An unprefixed class
 * used by seven views is a component whether or not it is declared as one, and
 * declaring it twice in two page sheets is how the two drift apart.
 *
 * WHY IT IS NOT A .fc-btn INSIDE A FIELD. The button is 48px inside a 62px row,
 * flush to a 6px right inset, with no border of its own — it is a shape cut out
 * of the row rather than a button placed next to one. Giving it .fc-btn would
 * hand it that component's border, padding and height and then need all three
 * overridden back.
 *
 * ONE RADIUS, NOT TWO. The design draws 12px on the row and 10.47px on the
 * button. Both are var(--radius-10) here: tokens.css carries exactly one radius
 * and says of it that "if a new radius seems necessary, the answer is one of
 * these", and the difference is 1.5px on a shape nothing sits beside.
 *
 * 17px and 12px are literals. Neither is a scale step — 17 sits between the
 * body sizes and 12 is not on the 8/16/24 spacing scale — and writing them as
 * tokens would invite something else to reuse them.
 *
 * [data-tone="dark"] is the same row on an ink surface, for the CTA block and
 * the Report. Nothing uses it yet; it is here because the primitive is, and
 * because the alternative is discovering the dark case in a page sheet later.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-lockup {
	display: flex;
	align-items: center;
	gap: var(--sp-8);
	box-sizing: border-box;
	width: 100%;
	max-width: 520px;
	height: 62px;
	/* Right only. The button sits 6px inside the border; the field runs to the
	   left edge and pays its own 20px. */
	padding: 0 6px 0 0;
	background: var(--fc-white);
	border: var(--stroke-1) solid var(--border-on-light);
	border-radius: var(--radius-10);
}

/* The whole row takes the focus ring, because the field has no border of its own
   to put one on. */
body.fc-ds .fc-lockup:focus-within {
	border-color: var(--fc-violet);
}

body.fc-ds .fc-lockup input,
body.fc-ds .fc-lockup textarea {
	flex: 1 1 auto;
	min-width: 0;
	height: 100%;
	box-sizing: border-box;
	padding: 0 20px;
	background: transparent;
	border: 0;
	outline: none;
	font-family: var(--font-core);
	font-size: var(--type-body-18);
	font-weight: var(--fw-medium);
	color: var(--fc-ink-12);
}

body.fc-ds .fc-lockup input::placeholder {
	color: var(--fc-ink-a50);
}

body.fc-ds .fc-lockup-btn {
	flex: none;
	display: inline-flex;
	align-items: center;
	gap: 12px;
	box-sizing: border-box;
	height: 48px;
	padding: 0 24px;
	border: 0;
	border-radius: var(--radius-10);
	background: var(--fc-violet);
	color: var(--fc-white);
	font-family: var(--font-core);
	font-size: 17px;
	font-weight: var(--fw-medium);
	line-height: 1;
	white-space: nowrap;
	text-decoration: none;
	cursor: pointer;
	transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

body.fc-ds .fc-lockup-btn:hover {
	background: var(--fc-ink-12);
	color: var(--fc-white);
}

/* Its own ring as well as the row's: the row lights up when the FIELD has focus,
   which says nothing about the button. */
body.fc-ds .fc-lockup-btn:focus-visible {
	outline: var(--stroke-2) solid var(--fc-violet);
	outline-offset: 2px;
}

body.fc-ds .fc-lockup-btn > svg {
	flex: none;
}

body.fc-ds .fc-lockup[data-tone="dark"] {
	background: var(--fc-bone-a08);
	border-color: var(--border-on-dark);
}

body.fc-ds .fc-lockup[data-tone="dark"] input {
	color: var(--fc-bone);
}

body.fc-ds .fc-lockup[data-tone="dark"] input::placeholder {
	color: var(--fc-bone-a50);
}

body.fc-ds .fc-lockup[data-tone="dark"] .fc-lockup-btn:hover {
	background: var(--fc-bone);
	color: var(--fc-ink-12);
}

/*
 * On a phone the row stops being a row. 24px of button padding, a nowrap label
 * and a field that still has to hold an email address do not fit across 300-odd
 * pixels, and shrinking the label is worse than stacking it: the two stack
 * inside the same bordered box, which keeps the lockup a lockup.
 */
@container page (max-width: 440px) {
	body.fc-ds .fc-lockup {
		flex-wrap: wrap;
		height: auto;
		padding: 6px;
	}

	body.fc-ds .fc-lockup input,
	body.fc-ds .fc-lockup textarea {
		flex: 1 1 100%;
		height: 48px;
		padding: 0 14px;
	}

	body.fc-ds .fc-lockup-btn {
		flex: 1 1 100%;
		justify-content: center;
	}
}

/* ─────────────────────────────────────────────────────────────────────────────
 * THE CONSENT BLOCK
 * The marketing opt-in and the privacy line, one treatment for every form on the
 * site. Same argument as the buttons above: there is one of these, not one per
 * form. Four forms used to carry their own copy and had drifted to three
 * different sizes — see inc/ds-consent.php, which is the only thing that prints
 * this markup and is where the rule is written down.
 *
 * Here rather than in a per-view sheet because it is loaded by every view that
 * could hold a form: contact is in pages.css, the event form in event.css, the
 * video gate in watch.css, and a shared component cannot live in one of them.
 *
 * 14px is off the brand scale (tokens.css calls 15 the floor) and is the contact
 * page's own size — the reference this block matches. Stated as a literal rather
 * than a token so it does not read as a scale step anything else may use.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .fc-consent {
	display: flex;
	flex-direction: column;
	/* Close, because the two sentences are one statement. The form's own field gap
	   applies to this wrapper, not to the sentences inside it. */
	gap: var(--sp-8);
	/*
	 * The two colourways, as properties rather than as a second block of rules:
	 * light is the default because three of the four forms sit on a light surface,
	 * and .fc-consent--on-dark swaps the four values it differs by.
	 */
	--fc-consent-text: var(--text-on-light-muted);
	--fc-consent-fine: var(--fc-ink-a60);
	--fc-consent-link: var(--text-on-light);
	--fc-consent-rule: var(--fc-ink-a40);
}

body.fc-ds .fc-consent--on-dark {
	--fc-consent-text: var(--text-on-dark-muted);
	--fc-consent-fine: var(--fc-bone-a60);
	--fc-consent-link: var(--text-on-dark);
	--fc-consent-rule: var(--fc-bone-a40);
}

/* flex-start: the box aligns to the first line of a sentence that wraps to three. */
body.fc-ds .fc-consent__box {
	display: flex;
	align-items: flex-start;
	/* 12px is .fc-btn's own icon gap, and this is the same relationship: a mark and
	   the words it belongs to. Not a scale step. */
	gap: 12px;
	cursor: pointer;
	font-family: var(--font-core);
	font-weight: var(--fw-medium);
	font-size: 14px;
	line-height: var(--lh-loose);
	color: var(--fc-consent-text);
	text-wrap: pretty;
}

body.fc-ds .fc-consent__check {
	flex: none;
	/*
	 * 18px is the platform's own checkbox size. Shrinking it to match 14px type
	 * would make it harder to hit for no gain, so the 3px is the optical correction
	 * that buys instead: an 18px box against a 21px line box sits high without it.
	 */
	width: 18px;
	height: 18px;
	margin-top: 3px;
	accent-color: var(--fc-violet);
}

body.fc-ds .fc-consent__fine {
	margin: 0;
	font-family: var(--font-core);
	font-weight: var(--fw-medium);
	font-size: 14px;
	line-height: var(--lh-loose);
	color: var(--fc-consent-fine);
	text-wrap: pretty;
}

/*
 * On a 40% underline — legible without being the loudest thing in a paragraph
 * nobody is meant to be distracted by. text-decoration is off and the border does
 * the work, so the rule clears the descenders.
 */
body.fc-ds .fc-consent__link {
	color: var(--fc-consent-link);
	text-decoration: none;
	border-bottom: var(--stroke-1) solid var(--fc-consent-rule);
	transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}

body.fc-ds .fc-consent__link:hover,
body.fc-ds .fc-consent__link:focus-visible {
	color: var(--fc-violet-bright);
	border-color: var(--fc-violet-bright);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * SCREEN-READER-ONLY
 * WordPress's .screen-reader-text normally comes from style.css, which these
 * pages do not load. Restated here so pagination and form labels stay reachable.
 * ────────────────────────────────────────────────────────────────────────── */
body.fc-ds .screen-reader-text,
body.fc-ds .fc-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/*
 * Skip link — visible only when focused, and above the sticky nav's z-index.
 */
body.fc-ds .fc-skip:focus {
	position: fixed;
	top: 8px;
	left: 8px;
	z-index: 200;
	width: auto;
	height: auto;
	margin: 0;
	padding: 12px 20px;
	overflow: visible;
	clip-path: none;
	background: var(--surface-dark);
	color: var(--text-on-dark);
	font-size: var(--type-mono-14);
	border-radius: var(--radius-10);
}

/* ═════════════════════════════════════════════════════════════════════════════
 * EMBEDDED PARDOT FORMS
 *
 * The hole a go.fluentcommerce.com form sits in. Four pages have one — /contact/, the demo
 * page, the comparison test page and the Gartner gate — plus, since 2026-08-26, a gated
 * video's gate, which can be an embedded form instead of the site's own. The markup is the
 * same everywhere because one function builds it: fluent_commerce_pardot_iframe() in
 * inc/pardot-embed.php, which emits `.fc-pardot > .fc-pardot__frame` plus whatever class the
 * page adds.
 *
 * HERE RATHER THAN IN THREE PAGE STYLESHEETS, and that is the whole reason for this
 * block: it was written twice already — once in contact-pardot.css and once as
 * .fc-demo__frame in pages.css — and the two copies had already begun to disagree about
 * which properties belonged to the frame and which to the page. One builder, one set of
 * rules for what it builds. What stays with each page is the HEIGHT, which is the only
 * thing that genuinely differs per form.
 *
 * ── WHAT THIS CANNOT DO ─────────────────────────────────────────────────────
 *
 * Reach inside. Everything within the frame is a document served by another origin, so
 * every selector here stops at its edge: the fields, the labels, the button and the
 * opt-in are styled by CSS pasted into Pardot's own layout template — assets/ds/
 * pardot-form.css for the contact form, pardot-form-demo.css for the demo,
 * pardot-form-report.css for Forrester, pardot-form-gartner.css for Gartner and
 * pardot-form-video.css for the video gate. Those five files are enqueued by nothing and
 * exist to be copied out.
 * ══════════════════════════════════════════════════════════════════════════ */

/* min-width:0 so the frame can shrink inside a flex or grid column rather than forcing
   its parent wider than the viewport. */
body.fc-ds .fc-pardot {
	width: 100%;
	min-width: 0;
}

body.fc-ds .fc-pardot__frame {
	/*
	 * display:block, because an iframe is inline by default and an inline replaced element
	 * sits on a text baseline — which leaves a few px of descender space under it that
	 * reads as a stray gap in a flex column.
	 */
	display: block;
	width: 100%;
	/* No border, no background and no radius. Pardot's document has its own ground, and a
	   box drawn out here would be a box around a form that already looks like one. */
	border: 0;
	background: transparent;
	/*
	 * color-scheme:light, and it is the one line here that is load-bearing rather than
	 * hygiene. The frame otherwise inherits the browser's preferred scheme, so a visitor
	 * in dark mode gets a Pardot document rendering its form controls dark on a page that
	 * is bone — and the report back is "the form looks wrong" for a reason that has nothing
	 * to do with the form. The site is light in both schemes.
	 */
	color-scheme: light;
}

/*
 * NO min-height HERE ON PURPOSE. The floor is the height PHP declared for that form, so
 * it belongs with the page that knows the number — pages.css for the demo, contact.css's
 * section in pages.css for /contact/. A shared floor would be right for neither and would
 * hold the shorter frame open.
 *
 * Whatever sets it, assets/ds/pardot-frame.js sets it to 0 the moment a real measurement
 * arrives from inside the frame: the whole point of measuring is that the frame can then be
 * SHORTER than the guess, and a floor blocks exactly that.
 */
